]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/Elf32Convert.c
Sync BaseTools Trunk (version r2387) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
index 9e4a9a2c9a2a55fb25ee04b99a865bf65d715427..ddb45acc8677c408e4aa770fb1b03283325586cc 100644 (file)
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2011, Intel Corporation. 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
@@ -263,6 +263,7 @@ ScanSections32 (
   EFI_IMAGE_DOS_HEADER            *DosHdr;
   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
   UINT32                          CoffEntry;
+  UINT32                          SectionCount;
 
   CoffEntry = 0;
   mCoffOffset = 0;
@@ -291,6 +292,7 @@ ScanSections32 (
   //
   mCoffOffset = CoffAlign(mCoffOffset);
   mTextOffset = mCoffOffset;
+  SectionCount = 0;
   for (i = 0; i < mEhdr->e_shnum; i++) {
     Elf_Shdr *shdr = GetShdrByIndex(i);
     if (IsTextShdr(shdr)) {
@@ -315,6 +317,7 @@ ScanSections32 (
       }
       mCoffSectionsOffset[i] = mCoffOffset;
       mCoffOffset += shdr->sh_size;
+      SectionCount ++;
     }
   }
 
@@ -322,10 +325,15 @@ ScanSections32 (
     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 +352,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.
   //
@@ -632,6 +645,7 @@ WriteSections32 (
           switch (ELF32_R_TYPE(Rel->r_info)) {
           case R_ARM_RBASE:
             // No relocation - no action required
+            // break skipped
 
           case R_ARM_PC24:
           case R_ARM_XPC25:
@@ -639,6 +653,35 @@ WriteSections32 (
           case R_ARM_THM_JUMP19:
           case R_ARM_CALL:
           case R_ARM_JMP24:
+          case R_ARM_THM_JUMP24:  
+          case R_ARM_PREL31:  
+          case R_ARM_MOVW_PREL_NC:  
+          case R_ARM_MOVT_PREL:
+          case R_ARM_THM_MOVW_PREL_NC:
+          case R_ARM_THM_MOVT_PREL:
+          case R_ARM_THM_JMP6:
+          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:
+          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:
+          case R_ARM_THM_JUMP8:
+          case R_ARM_TLS_GD32:
+          case R_ARM_TLS_LDM32:
+          case R_ARM_TLS_IE32:
             // Thease are all PC-relative relocations and don't require modification
             // GCC does not seem to have the concept of a application that just needs to get relocated.
             break;
@@ -674,6 +717,8 @@ WriteSections32 (
   return TRUE;
 }
 
+UINTN gMovwOffset = 0;
+
 STATIC
 VOID
 WriteRelocations32 (
@@ -693,10 +738,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);
@@ -705,16 +746,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:
@@ -736,14 +771,45 @@ WriteRelocations32 (
             }
           } else if (mEhdr->e_machine == EM_ARM) {
             switch (ELF32_R_TYPE(Rel->r_info)) {
-            case R_ARM_RBASE: 
+            case R_ARM_RBASE:
               // No relocation - no action required
+              // break skipped
+
             case R_ARM_PC24:
             case R_ARM_XPC25:
             case R_ARM_THM_PC22:
             case R_ARM_THM_JUMP19:
             case R_ARM_CALL:
             case R_ARM_JMP24:
+            case R_ARM_THM_JUMP24:  
+            case R_ARM_PREL31:  
+            case R_ARM_MOVW_PREL_NC:  
+            case R_ARM_MOVT_PREL:
+            case R_ARM_THM_MOVW_PREL_NC:
+            case R_ARM_THM_MOVT_PREL:
+            case R_ARM_THM_JMP6:
+            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:
+            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:
+            case R_ARM_THM_JUMP8:
+            case R_ARM_TLS_GD32:
+            case R_ARM_TLS_LDM32:
+            case R_ARM_TLS_IE32:
               // Thease are all PC-relative relocations and don't require modification
               break;
 
@@ -751,19 +817,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: