]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/Elf32Convert.c
Sync BaseTool trunk (version r2610) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
index 539fdf560a4a37afbef509375c85703f539036a4..58ac333888dcfdd65ba88c352698a4aa4fc35efa 100644 (file)
@@ -1,6 +1,7 @@
 /** @file
 
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
 
 This program and the accompanying materials are licensed and made available
 under the terms and conditions of the BSD License which accompanies this
@@ -18,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <windows.h>
 #include <io.h>
 #endif
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -263,9 +265,13 @@ ScanSections32 (
   EFI_IMAGE_DOS_HEADER            *DosHdr;
   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
   UINT32                          CoffEntry;
+  UINT32                          SectionCount;
+  BOOLEAN                         FoundText;
 
   CoffEntry = 0;
   mCoffOffset = 0;
+  mTextOffset = 0;
+  FoundText = FALSE;
 
   //
   // Coff file start with a DOS header.
@@ -290,7 +296,7 @@ ScanSections32 (
   // First text sections.
   //
   mCoffOffset = CoffAlign(mCoffOffset);
-  mTextOffset = mCoffOffset;
+  SectionCount = 0;
   for (i = 0; i < mEhdr->e_shnum; i++) {
     Elf_Shdr *shdr = GetShdrByIndex(i);
     if (IsTextShdr(shdr)) {
@@ -313,19 +319,39 @@ ScanSections32 (
           (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {
         CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;
       }
+
+      //
+      // Set mTextOffset with the offset of the first '.text' section
+      //
+      if (!FoundText) {
+        mTextOffset = mCoffOffset;
+        FoundText = TRUE;
+      }
+
       mCoffSectionsOffset[i] = mCoffOffset;
       mCoffOffset += shdr->sh_size;
+      SectionCount ++;
     }
   }
 
+  if (!FoundText) {
+    Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");
+    assert (FALSE);
+  }
+
   if (mEhdr->e_machine != EM_ARM) {
     mCoffOffset = CoffAlign(mCoffOffset);
   }
 
+  if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {
+    Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);
+  }
+
   //
   //  Then data sections.
   //
   mDataOffset = mCoffOffset;
+  SectionCount = 0;
   for (i = 0; i < mEhdr->e_shnum; i++) {
     Elf_Shdr *shdr = GetShdrByIndex(i);
     if (IsDataShdr(shdr)) {
@@ -344,10 +370,15 @@ ScanSections32 (
       }
       mCoffSectionsOffset[i] = mCoffOffset;
       mCoffOffset += shdr->sh_size;
+      SectionCount ++;
     }
   }
   mCoffOffset = CoffAlign(mCoffOffset);
 
+  if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {
+    Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);
+  }
+
   //
   //  The HII resource sections.
   //
@@ -650,18 +681,18 @@ WriteSections32 (
           case R_ARM_THM_ALU_PREL_11_0:
           case R_ARM_THM_PC12:
           case R_ARM_REL32_NOI:
-          case R_ARM_ALU_PC_G0_NC:\r
-          case R_ARM_ALU_PC_G0:\r
-          case R_ARM_ALU_PC_G1_NC:\r
-          case R_ARM_ALU_PC_G1:\r
-          case R_ARM_ALU_PC_G2:\r
-          case R_ARM_LDR_PC_G1:\r
-          case R_ARM_LDR_PC_G2:\r
-          case R_ARM_LDRS_PC_G0:\r
-          case R_ARM_LDRS_PC_G1:\r
-          case R_ARM_LDRS_PC_G2:\r
-          case R_ARM_LDC_PC_G0:\r
-          case R_ARM_LDC_PC_G1:\r
+          case R_ARM_ALU_PC_G0_NC:
+          case R_ARM_ALU_PC_G0:
+          case R_ARM_ALU_PC_G1_NC:
+          case R_ARM_ALU_PC_G1:
+          case R_ARM_ALU_PC_G2:
+          case R_ARM_LDR_PC_G1:
+          case R_ARM_LDR_PC_G2:
+          case R_ARM_LDRS_PC_G0:
+          case R_ARM_LDRS_PC_G1:
+          case R_ARM_LDRS_PC_G2:
+          case R_ARM_LDC_PC_G0:
+          case R_ARM_LDC_PC_G1:
           case R_ARM_LDC_PC_G2:
           case R_ARM_GOT_PREL:
           case R_ARM_THM_JUMP11:
@@ -704,6 +735,8 @@ WriteSections32 (
   return TRUE;
 }
 
+UINTN gMovwOffset = 0;
+
 STATIC
 VOID
 WriteRelocations32 (
@@ -723,10 +756,6 @@ WriteRelocations32 (
   UINT8                            *Targ;
   Elf32_Phdr                       *DynamicSegment;
   Elf32_Phdr                       *TargetSegment;
-  Elf_Sym                          *Sym;
-  Elf_Shdr                         *SymtabShdr;
-  UINT8                            *Symtab;
-  
 
   for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {
     Elf_Shdr *RelShdr = GetShdrByIndex(Index);
@@ -735,16 +764,10 @@ WriteRelocations32 (
       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
         UINT32 RelIdx;
 
-        SymtabShdr = GetShdrByIndex (RelShdr->sh_link);
-        Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;
         FoundRelocations = TRUE;
         for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
           Elf_Rel  *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);
-          Elf_Shdr *SymShdr;
 
-          Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
-          SymShdr = GetShdrByIndex (Sym->st_shndx);
-          
           if (mEhdr->e_machine == EM_386) { 
             switch (ELF_R_TYPE(Rel->r_info)) {
             case R_386_NONE:
@@ -786,18 +809,18 @@ WriteRelocations32 (
             case R_ARM_THM_ALU_PREL_11_0:
             case R_ARM_THM_PC12:
             case R_ARM_REL32_NOI:
-            case R_ARM_ALU_PC_G0_NC:\r
-            case R_ARM_ALU_PC_G0:\r
-            case R_ARM_ALU_PC_G1_NC:\r
-            case R_ARM_ALU_PC_G1:\r
-            case R_ARM_ALU_PC_G2:\r
-            case R_ARM_LDR_PC_G1:\r
-            case R_ARM_LDR_PC_G2:\r
-            case R_ARM_LDRS_PC_G0:\r
-            case R_ARM_LDRS_PC_G1:\r
-            case R_ARM_LDRS_PC_G2:\r
-            case R_ARM_LDC_PC_G0:\r
-            case R_ARM_LDC_PC_G1:\r
+            case R_ARM_ALU_PC_G0_NC:
+            case R_ARM_ALU_PC_G0:
+            case R_ARM_ALU_PC_G1_NC:
+            case R_ARM_ALU_PC_G1:
+            case R_ARM_ALU_PC_G2:
+            case R_ARM_LDR_PC_G1:
+            case R_ARM_LDR_PC_G2:
+            case R_ARM_LDRS_PC_G0:
+            case R_ARM_LDRS_PC_G1:
+            case R_ARM_LDRS_PC_G2:
+            case R_ARM_LDC_PC_G0:
+            case R_ARM_LDC_PC_G1:
             case R_ARM_LDC_PC_G2:
             case R_ARM_GOT_PREL:
             case R_ARM_THM_JUMP11:
@@ -812,19 +835,18 @@ WriteRelocations32 (
               CoffAddFixup (
                 mCoffSectionsOffset[RelShdr->sh_info]
                 + (Rel->r_offset - SecShdr->sh_addr),
-                EFI_IMAGE_REL_BASED_ARM_THUMB_MOVW
+                EFI_IMAGE_REL_BASED_ARM_MOV32T
                 );
+
+              // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction
+              // Track this address so we can log an error for unsupported sequence of MOVW/MOVT
+              gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);
               break;
 
             case R_ARM_THM_MOVT_ABS:
-              CoffAddFixup (
-                mCoffSectionsOffset[RelShdr->sh_info]
-                + (Rel->r_offset - SecShdr->sh_addr),
-                EFI_IMAGE_REL_BASED_ARM_THUMB_MOVT
-                );
-
-              // The relocation entry needs to contain the lower 16-bits so we can do math
-              CoffAddFixupEntry ((UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]));
+              if ((gMovwOffset + 4) !=  (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {
+                Error (NULL, 0, 3000, "Not Supported", "PE/COFF requires MOVW+MOVT instruction sequence %x +4 != %x.", gMovwOffset, mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));
+              }
               break;
 
             case R_ARM_ABS32: