Add support for ARM MOVW & MOVT relocations. These relocations are different than...
authorandrewfish <andrewfish@c2973edb-eda0-4c78-bc6a-9341b269661f>
Wed, 24 Mar 2010 17:29:20 +0000 (17:29 +0000)
committerandrewfish <andrewfish@c2973edb-eda0-4c78-bc6a-9341b269661f>
Wed, 24 Mar 2010 17:29:20 +0000 (17:29 +0000)
git-svn-id: https://edk2-buildtools.svn.sourceforge.net/svnroot/edk2-buildtools/trunk/BaseTools@1941 c2973edb-eda0-4c78-bc6a-9341b269661f

Source/C/Common/BasePeCoff.c
Source/C/Common/PeCoffLib.h
Source/C/Common/PeCoffLoaderEx.c
Source/C/GenFw/GenFw.c
Source/C/GenFw/elf_common.h
Source/C/Include/Common/BaseTypes.h
Source/C/Include/IndustryStandard/PeImage.h

index 5ffb5d4..beef08a 100644 (file)
@@ -71,6 +71,14 @@ PeCoffLoaderRelocateIpfImage (
   IN UINT64      Adjust\r
   );\r
 \r
+RETURN_STATUS\r
+PeCoffLoaderRelocateArmImage (\r
+  IN UINT16      **Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  );\r
+\r
 STATIC\r
 RETURN_STATUS\r
 PeCoffLoaderGetPeHeader (\r
@@ -777,9 +785,11 @@ Returns:
       default:\r
         switch (MachineType) {\r
         case EFI_IMAGE_MACHINE_IA32:\r
-        case EFI_IMAGE_MACHINE_ARMT:\r
           Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust);\r
           break;\r
+        case EFI_IMAGE_MACHINE_ARMT:\r
+          Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust);\r
+          break;\r
         case EFI_IMAGE_MACHINE_X64:\r
           Status = PeCoffLoaderRelocateX64Image (Reloc, Fixup, &FixupData, Adjust);\r
           break;\r
index 077a66c..f2adf08 100644 (file)
@@ -144,4 +144,38 @@ PeCoffLoaderGetEntryPoint (
   )\r
 ;\r
 \r
+//\r
+// These functions are used by the ARM PE/COFF relocation code and by\r
+// the ELF to PE/COFF converter so that is why they are public\r
+//\r
+\r
+/**\r
+  Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and \r
+  return the immediate data encoded in the instruction\r
+\r
+  @param  Instruction   Pointer to ARM MOVT or MOVW immediate instruction\r
+\r
+  @return Immediate address encoded in the instruction\r
+\r
+**/\r
+UINT16\r
+ThumbMovtImmediateAddress (\r
+  IN UINT16 *Instruction\r
+  );\r
+\r
+/**\r
+  Update an ARM MOVT or MOVW immediate instruction immediate data.\r
+\r
+  @param  Instruction   Pointer to ARM MOVT or MOVW immediate instruction\r
+  @param  Address       New addres to patch into the instruction\r
+\r
+**/\r
+VOID\r
+ThumbMovtImmediatePatch (\r
+  IN OUT UINT16 *Instruction,\r
+  IN     UINT16 Address\r
+  );\r
+\r
+\r
+\r
 #endif\r
index fedc094..e5185be 100644 (file)
@@ -315,3 +315,121 @@ PeCoffLoaderRelocateX64Image (
   return RETURN_SUCCESS;\r
 }\r
 \r
+/**\r
+  Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and \r
+  return the immediate data encoded in the instruction\r
+\r
+  @param  Instruction   Pointer to ARM MOVT or MOVW immediate instruction\r
+\r
+  @return Immediate address encoded in the instruction\r
+\r
+**/\r
+UINT16\r
+ThumbMovtImmediateAddress (\r
+  IN UINT16 *Instruction\r
+  )\r
+{\r
+  UINT32  Movt;\r
+  UINT16  Address;\r
+\r
+  // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction\r
+  // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000\r
+  Movt = (*Instruction << 16) | (*(Instruction + 1)); \r
+\r
+  // imm16 = imm4:i:imm3:imm8\r
+  //         imm4 -> Bit19:Bit16\r
+  //         i    -> Bit26\r
+  //         imm3 -> Bit14:Bit12\r
+  //         imm8 -> Bit7:Bit0\r
+  Address  = (UINT16)(Movt & 0x000000ff);          // imm8\r
+  Address |= (UINT16)((Movt >> 4) &  0x0000f700);  // imm4 imm3\r
+  Address |= (((Movt & BIT26) != 0) ? BIT11 : 0);  // i\r
+  return Address;\r
+}\r
+\r
+\r
+/**\r
+  Update an ARM MOVT or MOVW immediate instruction immediate data.\r
+\r
+  @param  Instruction   Pointer to ARM MOVT or MOVW immediate instruction\r
+  @param  Address       New addres to patch into the instruction\r
+**/\r
+VOID\r
+ThumbMovtImmediatePatch (\r
+  IN OUT UINT16 *Instruction,\r
+  IN     UINT16 Address\r
+  )\r
+{\r
+  UINT16  Patch;\r
+\r
+  // First 16-bit chunk of instruciton\r
+  Patch  = ((Address >> 12) & 0x000f);             // imm4 \r
+  Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i\r
+  *Instruction = (*Instruction & ~0x040f) | Patch;\r
+\r
+  // Second 16-bit chunk of instruction\r
+  Patch  =  Address & 0x000000ff;          // imm8\r
+  Patch |=  ((Address << 4) & 0x00007000); // imm3\r
+  Instruction++;\r
+  *Instruction = (*Instruction & ~0x70ff) | Patch;\r
+}\r
+\r
+/**\r
+  Performs an ARM-based specific relocation fixup and is a no-op on other\r
+  instruction sets.\r
+\r
+  @param  Reloc       Pointer to the relocation record.\r
+  @param  Fixup       Pointer to the address to fix up.\r
+  @param  FixupData   Pointer to a buffer to log the fixups.\r
+  @param  Adjust      The offset to adjust the fixup.\r
+\r
+  @return Status code.\r
+\r
+**/\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateArmImage (\r
+  IN UINT16      **Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  )\r
+{\r
+  UINT16      *Fixup16;\r
+  UINT16      FixupVal;\r
+  UINT16      *Addend;\r
+\r
+  Fixup16    = (UINT16 *) Fixup;\r
+\r
+  switch ((**Reloc) >> 12) {\r
+  case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW:\r
+    FixupVal = ThumbMovtImmediateAddress (Fixup16) + (UINT16)Adjust;\r
+    ThumbMovtImmediatePatch (Fixup16, FixupVal);\r
+\r
+    if (*FixupData != NULL) {\r
+      *FixupData             = ALIGN_POINTER (*FixupData, sizeof (UINT16));\r
+      *(UINT16 *)*FixupData  = *Fixup16;\r
+      *FixupData             = *FixupData + sizeof (UINT16);\r
+    }\r
+    break;\r
+\r
+  case EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT:\r
+    // For MOVT you need to know the lower 16-bits do do the math\r
+    // So this relocation entry is really two entries.\r
+    *Reloc = *Reloc + 1;\r
+    Addend = *Reloc; \r
+    FixupVal = (UINT16)(((ThumbMovtImmediateAddress (Fixup16) << 16) + Adjust + *Addend) >> 16);\r
+    ThumbMovtImmediatePatch (Fixup16, FixupVal);\r
+\r
+    if (*FixupData != NULL) {\r
+      *FixupData             = ALIGN_POINTER (*FixupData, sizeof (UINT16));\r
+      *(UINT16 *)*FixupData  = *Fixup16;\r
+      *FixupData             = *FixupData + sizeof (UINT16);\r
+    }\r
+    break;\r
+  \r
+  default:\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
index ee02f85..d6bfc5f 100644 (file)
@@ -988,8 +988,9 @@ WriteSections(
   //\r
   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
-    if (RelShdr->sh_type != SHT_REL)\r
+    if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
       continue;\r
+    }\r
     SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
     SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
@@ -1002,6 +1003,7 @@ WriteSections(
         Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
         Elf_Shdr *SymShdr;\r
         UINT8 *Targ;\r
+        UINT16 Address;\r
 \r
         if (Sym->st_shndx == SHN_UNDEF\r
             || Sym->st_shndx == SHN_ABS\r
@@ -1040,14 +1042,29 @@ WriteSections(
           }\r
         } else if (Ehdr->e_machine == EM_ARM) {\r
           switch (ELF32_R_TYPE(Rel->r_info)) {\r
-          case R_ARM_RBASE:   // No relocation - no action required\r
+          case R_ARM_RBASE:   \r
+            // No relocation - no action required\r
           \r
-          // Thease are all PC-relative relocations and don't require modification\r
           case R_ARM_PC24:    \r
           case R_ARM_XPC25:   \r
           case R_ARM_THM_PC22:\r
           case R_ARM_THM_JUMP19:\r
           case R_ARM_CALL:\r
+          case R_ARM_JMP24:\r
+            // Thease are all PC-relative relocations and don't require modification\r
+            // GCC does not seem to have the concept of a application that just needs to get relocated. \r
+            break;\r
+            \r
+          case R_ARM_THM_MOVW_ABS_NC:\r
+            // MOVW is only lower 16-bits of the addres\r
+            Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx]);\r
+            ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
+            break;\r
+\r
+          case R_ARM_THM_MOVT_ABS:\r
+            // MOVT is only upper 16-bits of the addres\r
+            Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx]) >> 16);\r
+            ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
             break;\r
 \r
           case R_ARM_ABS32:\r
@@ -1057,6 +1074,7 @@ WriteSections(
             //\r
             *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];\r
             break;\r
\r
           default:\r
             Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
           }\r
@@ -1149,17 +1167,27 @@ WriteRelocations (
   UINT8                            *Targ;\r
   Elf32_Phdr                       *DynamicSegment;\r
   Elf32_Phdr                       *TargetSegment;\r
+  Elf_Sym                          *Sym;\r
+  Elf_Shdr                         *SymtabShdr;\r
+  UINT8                            *Symtab;\r
+  \r
 \r
   for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {\r
     Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
-    if (RelShdr->sh_type == SHT_REL) {\r
-      Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
+    if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
+      Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
         UINT32 RelIdx;\r
+\r
+        SymtabShdr = GetShdrByIndex (RelShdr->sh_link);\r
+        Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
         FoundRelocations = TRUE;\r
         for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
-          Elf_Rel *Rel = (Elf_Rel *)\r
-            ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
+          Elf_Rel  *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
+          Elf_Shdr *SymShdr;\r
+\r
+          Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
+          SymShdr = GetShdrByIndex (Sym->st_shndx);\r
           \r
           if (Ehdr->e_machine == EM_386) { \r
             switch (ELF_R_TYPE(Rel->r_info)) {\r
@@ -1176,15 +1204,36 @@ WriteRelocations (
             }\r
           } else if (Ehdr->e_machine == EM_ARM) {\r
             switch (ELF32_R_TYPE(Rel->r_info)) {\r
-            case R_ARM_RBASE: // No relocation - no action required\r
-          \r
-            // Thease are all PC-relative relocations and don't require modification\r
+            case R_ARM_RBASE: \r
+              // No relocation - no action required\r
             case R_ARM_PC24:\r
             case R_ARM_XPC25:\r
             case R_ARM_THM_PC22:\r
             case R_ARM_THM_JUMP19:\r
             case R_ARM_CALL:\r
+            case R_ARM_JMP24:\r
+              // Thease are all PC-relative relocations and don't require modification\r
               break;\r
+\r
+            case R_ARM_THM_MOVW_ABS_NC:\r
+              CoffAddFixup (\r
+                CoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr),\r
+                EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW\r
+                );\r
+              break;\r
+\r
+            case R_ARM_THM_MOVT_ABS:\r
+              CoffAddFixup (\r
+                CoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr),\r
+                EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT\r
+                );\r
+\r
+              // The relocation entry needs to contain the lower 16-bits so we can do math\r
+              CoffAddFixupEntry ((UINT16)(Sym->st_value - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx]));\r
+              break;\r
+\r
             case R_ARM_ABS32:\r
             case R_ARM_RABS32:\r
               CoffAddFixup (\r
@@ -1241,6 +1290,7 @@ WriteRelocations (
           Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
         }\r
 \r
+\r
         for (K = 0; K < RelSize; K += RelElementSize) {\r
 \r
           if (DynamicSegment->p_paddr == 0) {\r
@@ -1254,6 +1304,7 @@ WriteRelocations (
           switch (ELF32_R_TYPE (Rel->r_info)) {\r
           case  R_ARM_RBASE:\r
             break;\r
+\r
           case  R_ARM_RABS32:\r
             TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
 \r
@@ -1264,6 +1315,7 @@ WriteRelocations (
 \r
             CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
             break;\r
+          \r
           default:\r
             Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
             break;\r
index 3798c95..72fc6db 100644 (file)
@@ -597,7 +597,11 @@ typedef struct {
 #define        R_ARM_GOTPC             25      /* Add PC-relative GOT table address. */
 #define        R_ARM_GOT32             26      /* Add PC-relative GOT offset. */
 #define        R_ARM_PLT32             27      /* Add PC-relative PLT offset. */
-#define R_ARM_CALL          28
+#define R_ARM_CALL            28
+#define R_ARM_JMP24           29
+#define R_ARM_THM_MOVW_ABS_NC 47 
+#define R_ARM_THM_MOVT_ABS    48
+
 #define R_ARM_THM_JUMP19    51
 #define        R_ARM_GNU_VTENTRY       100
 #define        R_ARM_GNU_VTINHERIT     101
index 43721ae..7286038 100644 (file)
@@ -220,4 +220,69 @@ typedef INTN RETURN_STATUS;
 \r
 typedef UINT64 PHYSICAL_ADDRESS;\r
 \r
+#define  BIT0     0x00000001\r
+#define  BIT1     0x00000002\r
+#define  BIT2     0x00000004\r
+#define  BIT3     0x00000008\r
+#define  BIT4     0x00000010\r
+#define  BIT5     0x00000020\r
+#define  BIT6     0x00000040\r
+#define  BIT7     0x00000080\r
+#define  BIT8     0x00000100\r
+#define  BIT9     0x00000200\r
+#define  BIT10    0x00000400\r
+#define  BIT11    0x00000800\r
+#define  BIT12    0x00001000\r
+#define  BIT13    0x00002000\r
+#define  BIT14    0x00004000\r
+#define  BIT15    0x00008000\r
+#define  BIT16    0x00010000\r
+#define  BIT17    0x00020000\r
+#define  BIT18    0x00040000\r
+#define  BIT19    0x00080000\r
+#define  BIT20    0x00100000\r
+#define  BIT21    0x00200000\r
+#define  BIT22    0x00400000\r
+#define  BIT23    0x00800000\r
+#define  BIT24    0x01000000\r
+#define  BIT25    0x02000000\r
+#define  BIT26    0x04000000\r
+#define  BIT27    0x08000000\r
+#define  BIT28    0x10000000\r
+#define  BIT29    0x20000000\r
+#define  BIT30    0x40000000\r
+#define  BIT31    0x80000000\r
+#define  BIT32    0x0000000100000000ULL\r
+#define  BIT33    0x0000000200000000ULL\r
+#define  BIT34    0x0000000400000000ULL\r
+#define  BIT35    0x0000000800000000ULL\r
+#define  BIT36    0x0000001000000000ULL\r
+#define  BIT37    0x0000002000000000ULL\r
+#define  BIT38    0x0000004000000000ULL\r
+#define  BIT39    0x0000008000000000ULL\r
+#define  BIT40    0x0000010000000000ULL\r
+#define  BIT41    0x0000020000000000ULL\r
+#define  BIT42    0x0000040000000000ULL\r
+#define  BIT43    0x0000080000000000ULL\r
+#define  BIT44    0x0000100000000000ULL\r
+#define  BIT45    0x0000200000000000ULL\r
+#define  BIT46    0x0000400000000000ULL\r
+#define  BIT47    0x0000800000000000ULL\r
+#define  BIT48    0x0001000000000000ULL\r
+#define  BIT49    0x0002000000000000ULL\r
+#define  BIT50    0x0004000000000000ULL\r
+#define  BIT51    0x0008000000000000ULL\r
+#define  BIT52    0x0010000000000000ULL\r
+#define  BIT53    0x0020000000000000ULL\r
+#define  BIT54    0x0040000000000000ULL\r
+#define  BIT55    0x0080000000000000ULL\r
+#define  BIT56    0x0100000000000000ULL\r
+#define  BIT57    0x0200000000000000ULL\r
+#define  BIT58    0x0400000000000000ULL\r
+#define  BIT59    0x0800000000000000ULL\r
+#define  BIT60    0x1000000000000000ULL\r
+#define  BIT61    0x2000000000000000ULL\r
+#define  BIT62    0x4000000000000000ULL\r
+#define  BIT63    0x8000000000000000ULL\r
+\r
 #endif\r
index 69cca91..d03e34e 100644 (file)
@@ -513,6 +513,9 @@ typedef struct {
 #define EFI_IMAGE_REL_BASED_IA64_IMM64    9\r
 #define EFI_IMAGE_REL_BASED_DIR64         10\r
 \r
+#define EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW  11\r
+#define EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT  12\r
+\r
 ///\r
 /// Line number format.\r
 ///\r