]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/Elf32Convert.c
BaseTools-Source: Update displayed version information
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
index e1b92ebd713ef990899e5b48727e2703445f3d49..9bf58555c076c88a8cef657a7d2a4f98e4c37aac 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Elf32 Convert solution\r
 \r
-Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
 Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials are licensed and made available\r
@@ -218,6 +218,15 @@ CoffAlign (
   return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
 }\r
 \r
+STATIC\r
+UINT32\r
+DebugRvaAlign (\r
+  UINT32 Offset\r
+  )\r
+{\r
+  return (Offset + 3) & ~3;\r
+}\r
+\r
 //\r
 // filter functions\r
 //\r
@@ -331,12 +340,8 @@ ScanSections32 (
         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
           // if the section address is aligned we must align PE/COFF\r
           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
-        } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
-          // ARM RVCT tools have behavior outside of the ELF specification to try\r
-          // and make images smaller.  If sh_addr is not aligned to sh_addralign\r
-          // then the section needs to preserve sh_addr MOD sh_addralign.\r
-          // Normally doing nothing here works great.\r
-          Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+        } else {\r
+          Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
         }\r
       }\r
 \r
@@ -365,11 +370,8 @@ ScanSections32 (
     assert (FALSE);\r
   }\r
 \r
-  mDebugOffset = mCoffOffset;\r
-\r
-  if (mEhdr->e_machine != EM_ARM) {\r
-    mCoffOffset = CoffAlign(mCoffOffset);\r
-  }\r
+  mDebugOffset = DebugRvaAlign(mCoffOffset);\r
+  mCoffOffset = CoffAlign(mCoffOffset);\r
 \r
   if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
     Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
@@ -389,12 +391,8 @@ ScanSections32 (
         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
           // if the section address is aligned we must align PE/COFF\r
           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
-        } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
-          // ARM RVCT tools have behavior outside of the ELF specification to try\r
-          // and make images smaller.  If sh_addr is not aligned to sh_addralign\r
-          // then the section needs to preserve sh_addr MOD sh_addralign.\r
-          // Normally doing nothing here works great.\r
-          Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+        } else {\r
+          Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
         }\r
       }\r
 \r
@@ -423,7 +421,7 @@ ScanSections32 (
   // section alignment.\r
   //\r
   if (SectionCount > 0) {\r
-    mDebugOffset = mCoffOffset;\r
+    mDebugOffset = DebugRvaAlign(mCoffOffset);\r
   }\r
   mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
                 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
@@ -446,12 +444,8 @@ ScanSections32 (
         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
           // if the section address is aligned we must align PE/COFF\r
           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
-        } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
-          // ARM RVCT tools have behavior outside of the ELF specification to try\r
-          // and make images smaller.  If sh_addr is not aligned to sh_addralign\r
-          // then the section needs to preserve sh_addr MOD sh_addralign.\r
-          // Normally doing nothing here works great.\r
-          Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
+        } else {\r
+          Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
         }\r
       }\r
       if (shdr->sh_size != 0) {\r
@@ -722,6 +716,7 @@ WriteSections32 (
             // break skipped\r
 \r
           case R_ARM_PC24:\r
+          case R_ARM_REL32:\r
           case R_ARM_XPC25:\r
           case R_ARM_THM_PC22:\r
           case R_ARM_THM_JUMP19:\r
@@ -809,9 +804,7 @@ WriteRelocations32 (
   UINTN                            RelSize;\r
   UINTN                            RelOffset;\r
   UINTN                            K;\r
-  UINT8                            *Targ;\r
   Elf32_Phdr                       *DynamicSegment;\r
-  Elf32_Phdr                       *TargetSegment;\r
 \r
   for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
     Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
@@ -822,7 +815,7 @@ WriteRelocations32 (
 \r
         FoundRelocations = TRUE;\r
         for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
-          Elf_Rel  *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
+          Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
 \r
           if (mEhdr->e_machine == EM_386) { \r
             switch (ELF_R_TYPE(Rel->r_info)) {\r
@@ -850,6 +843,7 @@ WriteRelocations32 (
               // break skipped\r
 \r
             case R_ARM_PC24:\r
+            case R_ARM_REL32:\r
             case R_ARM_XPC25:\r
             case R_ARM_THM_PC22:\r
             case R_ARM_THM_JUMP19:\r
@@ -961,6 +955,31 @@ WriteRelocations32 (
           Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
         }\r
 \r
+        for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
+          Elf_Shdr *shdr = GetShdrByIndex(Index);\r
+\r
+          //\r
+          // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
+          // field is relative to the base of a segment (or the entire image),\r
+          // and not to the base of an ELF input section as is the case for\r
+          // SHT_REL sections. This means that we cannot fix up such relocations\r
+          // unless we cross-reference ELF sections and segments, considering\r
+          // that the output placement recorded in mCoffSectionsOffset[] is\r
+          // section based, not segment based.\r
+          //\r
+          // Fortunately, there is a simple way around this: we require that the\r
+          // in-memory layout of the ELF and PE/COFF versions of the binary is\r
+          // identical. That way, r_offset will retain its validity as a PE/COFF\r
+          // image offset, and we can record it in the COFF fixup table\r
+          // unmodified.\r
+          //\r
+          if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
+            Error (NULL, 0, 3000,\r
+              "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
+              mInImageName);\r
+          }\r
+        }\r
+\r
         for (K = 0; K < RelSize; K += RelElementSize) {\r
 \r
           if (DynamicSegment->p_paddr == 0) {\r
@@ -977,14 +996,7 @@ WriteRelocations32 (
             break;\r
 \r
           case  R_ARM_RABS32:\r
-            TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
-\r
-            // Note: r_offset in a memory address.  Convert it to a pointer in the coff file.\r
-            Targ = mCoffFile + mCoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
-\r
-            *(UINT32 *)Targ = *(UINT32 *)Targ + mCoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
-\r
-            CoffAddFixup (mCoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
+            CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
             break;\r
           \r
           default:\r