Home | History | Annotate | Download | only in GenFw
      1 /** @file
      2 Elf32 Convert solution
      3 
      4 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
      5 Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
      6 
      7 This program and the accompanying materials are licensed and made available
      8 under the terms and conditions of the BSD License which accompanies this
      9 distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "WinNtInclude.h"
     18 
     19 #ifndef __GNUC__
     20 #include <windows.h>
     21 #include <io.h>
     22 #endif
     23 #include <assert.h>
     24 #include <stdbool.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <time.h>
     29 #include <ctype.h>
     30 
     31 #include <Common/UefiBaseTypes.h>
     32 #include <IndustryStandard/PeImage.h>
     33 
     34 #include "PeCoffLib.h"
     35 #include "EfiUtilityMsgs.h"
     36 
     37 #include "GenFw.h"
     38 #include "ElfConvert.h"
     39 #include "Elf32Convert.h"
     40 
     41 STATIC
     42 VOID
     43 ScanSections32 (
     44   VOID
     45   );
     46 
     47 STATIC
     48 BOOLEAN
     49 WriteSections32 (
     50   SECTION_FILTER_TYPES  FilterType
     51   );
     52 
     53 STATIC
     54 VOID
     55 WriteRelocations32 (
     56   VOID
     57   );
     58 
     59 STATIC
     60 VOID
     61 WriteDebug32 (
     62   VOID
     63   );
     64 
     65 STATIC
     66 VOID
     67 SetImageSize32 (
     68   VOID
     69   );
     70 
     71 STATIC
     72 VOID
     73 CleanUp32 (
     74   VOID
     75   );
     76 
     77 //
     78 // Rename ELF32 strucutres to common names to help when porting to ELF64.
     79 //
     80 typedef Elf32_Shdr Elf_Shdr;
     81 typedef Elf32_Ehdr Elf_Ehdr;
     82 typedef Elf32_Rel Elf_Rel;
     83 typedef Elf32_Sym Elf_Sym;
     84 typedef Elf32_Phdr Elf_Phdr;
     85 typedef Elf32_Dyn Elf_Dyn;
     86 #define ELFCLASS ELFCLASS32
     87 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
     88 #define ELF_R_SYM(r) ELF32_R_SYM(r)
     89 
     90 //
     91 // Well known ELF structures.
     92 //
     93 STATIC Elf_Ehdr *mEhdr;
     94 STATIC Elf_Shdr *mShdrBase;
     95 STATIC Elf_Phdr *mPhdrBase;
     96 
     97 //
     98 // Coff information
     99 //
    100 STATIC UINT32 mCoffAlignment = 0x20;
    101 
    102 //
    103 // PE section alignment.
    104 //
    105 STATIC const UINT16 mCoffNbrSections = 4;
    106 
    107 //
    108 // ELF sections to offset in Coff file.
    109 //
    110 STATIC UINT32 *mCoffSectionsOffset = NULL;
    111 
    112 //
    113 // Offsets in COFF file
    114 //
    115 STATIC UINT32 mNtHdrOffset;
    116 STATIC UINT32 mTextOffset;
    117 STATIC UINT32 mDataOffset;
    118 STATIC UINT32 mHiiRsrcOffset;
    119 STATIC UINT32 mRelocOffset;
    120 STATIC UINT32 mDebugOffset;
    121 
    122 //
    123 // Initialization Function
    124 //
    125 BOOLEAN
    126 InitializeElf32 (
    127   UINT8               *FileBuffer,
    128   ELF_FUNCTION_TABLE  *ElfFunctions
    129   )
    130 {
    131   //
    132   // Initialize data pointer and structures.
    133   //
    134   mEhdr = (Elf_Ehdr*) FileBuffer;
    135 
    136   //
    137   // Check the ELF32 specific header information.
    138   //
    139   if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) {
    140     Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32");
    141     return FALSE;
    142   }
    143   if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {
    144     Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
    145     return FALSE;
    146   }
    147   if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {
    148     Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
    149     return FALSE;
    150   }
    151   if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) {
    152     Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
    153     return FALSE;
    154   }
    155   if (mEhdr->e_version != EV_CURRENT) {
    156     Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);
    157     return FALSE;
    158   }
    159 
    160   //
    161   // Update section header pointers
    162   //
    163   mShdrBase  = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);
    164   mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);
    165 
    166   //
    167   // Create COFF Section offset buffer and zero.
    168   //
    169   mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));
    170   if (mCoffSectionsOffset == NULL) {
    171     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
    172     return FALSE;
    173   }
    174   memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));
    175 
    176   //
    177   // Fill in function pointers.
    178   //
    179   ElfFunctions->ScanSections = ScanSections32;
    180   ElfFunctions->WriteSections = WriteSections32;
    181   ElfFunctions->WriteRelocations = WriteRelocations32;
    182   ElfFunctions->WriteDebug = WriteDebug32;
    183   ElfFunctions->SetImageSize = SetImageSize32;
    184   ElfFunctions->CleanUp = CleanUp32;
    185 
    186   return TRUE;
    187 }
    188 
    189 
    190 //
    191 // Header by Index functions
    192 //
    193 STATIC
    194 Elf_Shdr*
    195 GetShdrByIndex (
    196   UINT32 Num
    197   )
    198 {
    199   if (Num >= mEhdr->e_shnum) {
    200     Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num);
    201     exit(EXIT_FAILURE);
    202   }
    203 
    204   return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);
    205 }
    206 
    207 STATIC
    208 Elf_Phdr*
    209 GetPhdrByIndex (
    210   UINT32 num
    211   )
    212 {
    213   if (num >= mEhdr->e_phnum) {
    214     Error (NULL, 0, 3000, "Invalid", "GetPhdrByIndex: Index %u is too high.", num);
    215     exit(EXIT_FAILURE);
    216   }
    217 
    218   return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize);
    219 }
    220 
    221 STATIC
    222 UINT32
    223 CoffAlign (
    224   UINT32 Offset
    225   )
    226 {
    227   return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);
    228 }
    229 
    230 STATIC
    231 UINT32
    232 DebugRvaAlign (
    233   UINT32 Offset
    234   )
    235 {
    236   return (Offset + 3) & ~3;
    237 }
    238 
    239 //
    240 // filter functions
    241 //
    242 STATIC
    243 BOOLEAN
    244 IsTextShdr (
    245   Elf_Shdr *Shdr
    246   )
    247 {
    248   return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);
    249 }
    250 
    251 STATIC
    252 BOOLEAN
    253 IsHiiRsrcShdr (
    254   Elf_Shdr *Shdr
    255   )
    256 {
    257   Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);
    258 
    259   return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
    260 }
    261 
    262 STATIC
    263 BOOLEAN
    264 IsDataShdr (
    265   Elf_Shdr *Shdr
    266   )
    267 {
    268   if (IsHiiRsrcShdr(Shdr)) {
    269     return FALSE;
    270   }
    271   return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
    272 }
    273 
    274 STATIC
    275 BOOLEAN
    276 IsStrtabShdr (
    277   Elf_Shdr *Shdr
    278   )
    279 {
    280   Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);
    281 
    282   return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0);
    283 }
    284 
    285 STATIC
    286 Elf_Shdr *
    287 FindStrtabShdr (
    288   VOID
    289   )
    290 {
    291   UINT32 i;
    292   for (i = 0; i < mEhdr->e_shnum; i++) {
    293     Elf_Shdr *shdr = GetShdrByIndex(i);
    294     if (IsStrtabShdr(shdr)) {
    295       return shdr;
    296     }
    297   }
    298   return NULL;
    299 }
    300 
    301 STATIC
    302 const UINT8 *
    303 GetSymName (
    304   Elf_Sym *Sym
    305   )
    306 {
    307   if (Sym->st_name == 0) {
    308     return NULL;
    309   }
    310 
    311   Elf_Shdr *StrtabShdr = FindStrtabShdr();
    312   if (StrtabShdr == NULL) {
    313     return NULL;
    314   }
    315 
    316   assert(Sym->st_name < StrtabShdr->sh_size);
    317 
    318   UINT8* StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset;
    319 
    320   bool foundEnd = false;
    321   UINT32 i;
    322   for (i = Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {
    323     foundEnd = StrtabContents[i] == 0;
    324   }
    325   assert(foundEnd);
    326 
    327   return StrtabContents + Sym->st_name;
    328 }
    329 
    330 //
    331 // Elf functions interface implementation
    332 //
    333 
    334 STATIC
    335 VOID
    336 ScanSections32 (
    337   VOID
    338   )
    339 {
    340   UINT32                          i;
    341   EFI_IMAGE_DOS_HEADER            *DosHdr;
    342   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
    343   UINT32                          CoffEntry;
    344   UINT32                          SectionCount;
    345   BOOLEAN                         FoundSection;
    346 
    347   CoffEntry = 0;
    348   mCoffOffset = 0;
    349 
    350   //
    351   // Coff file start with a DOS header.
    352   //
    353   mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;
    354   mNtHdrOffset = mCoffOffset;
    355   switch (mEhdr->e_machine) {
    356   case EM_386:
    357   case EM_ARM:
    358     mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);
    359   break;
    360   default:
    361     VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);
    362     mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);
    363   break;
    364   }
    365 
    366   mTableOffset = mCoffOffset;
    367   mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);
    368 
    369   //
    370   // Set mCoffAlignment to the maximum alignment of the input sections
    371   // we care about
    372   //
    373   for (i = 0; i < mEhdr->e_shnum; i++) {
    374     Elf_Shdr *shdr = GetShdrByIndex(i);
    375     if (shdr->sh_addralign <= mCoffAlignment) {
    376       continue;
    377     }
    378     if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {
    379       mCoffAlignment = (UINT32)shdr->sh_addralign;
    380     }
    381   }
    382 
    383   //
    384   // Move the PE/COFF header right before the first section. This will help us
    385   // save space when converting to TE.
    386   //
    387   if (mCoffAlignment > mCoffOffset) {
    388     mNtHdrOffset += mCoffAlignment - mCoffOffset;
    389     mTableOffset += mCoffAlignment - mCoffOffset;
    390     mCoffOffset = mCoffAlignment;
    391   }
    392 
    393   //
    394   // First text sections.
    395   //
    396   mCoffOffset = CoffAlign(mCoffOffset);
    397   mTextOffset = mCoffOffset;
    398   FoundSection = FALSE;
    399   SectionCount = 0;
    400   for (i = 0; i < mEhdr->e_shnum; i++) {
    401     Elf_Shdr *shdr = GetShdrByIndex(i);
    402     if (IsTextShdr(shdr)) {
    403       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
    404         // the alignment field is valid
    405         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
    406           // if the section address is aligned we must align PE/COFF
    407           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
    408         } else {
    409           Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");
    410         }
    411       }
    412 
    413       /* Relocate entry.  */
    414       if ((mEhdr->e_entry >= shdr->sh_addr) &&
    415           (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {
    416         CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;
    417       }
    418 
    419       //
    420       // Set mTextOffset with the offset of the first '.text' section
    421       //
    422       if (!FoundSection) {
    423         mTextOffset = mCoffOffset;
    424         FoundSection = TRUE;
    425       }
    426 
    427       mCoffSectionsOffset[i] = mCoffOffset;
    428       mCoffOffset += shdr->sh_size;
    429       SectionCount ++;
    430     }
    431   }
    432 
    433   if (!FoundSection) {
    434     Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");
    435     assert (FALSE);
    436   }
    437 
    438   mDebugOffset = DebugRvaAlign(mCoffOffset);
    439   mCoffOffset = CoffAlign(mCoffOffset);
    440 
    441   if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {
    442     Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);
    443   }
    444 
    445   //
    446   //  Then data sections.
    447   //
    448   mDataOffset = mCoffOffset;
    449   FoundSection = FALSE;
    450   SectionCount = 0;
    451   for (i = 0; i < mEhdr->e_shnum; i++) {
    452     Elf_Shdr *shdr = GetShdrByIndex(i);
    453     if (IsDataShdr(shdr)) {
    454       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
    455         // the alignment field is valid
    456         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
    457           // if the section address is aligned we must align PE/COFF
    458           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
    459         } else {
    460           Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");
    461         }
    462       }
    463 
    464       //
    465       // Set mDataOffset with the offset of the first '.data' section
    466       //
    467       if (!FoundSection) {
    468         mDataOffset = mCoffOffset;
    469         FoundSection = TRUE;
    470       }
    471 
    472       mCoffSectionsOffset[i] = mCoffOffset;
    473       mCoffOffset += shdr->sh_size;
    474       SectionCount ++;
    475     }
    476   }
    477 
    478   if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {
    479     Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);
    480   }
    481 
    482   //
    483   // Make room for .debug data in .data (or .text if .data is empty) instead of
    484   // putting it in a section of its own. This is explicitly allowed by the
    485   // PE/COFF spec, and prevents bloat in the binary when using large values for
    486   // section alignment.
    487   //
    488   if (SectionCount > 0) {
    489     mDebugOffset = DebugRvaAlign(mCoffOffset);
    490   }
    491   mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +
    492                 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +
    493                 strlen(mInImageName) + 1;
    494 
    495   mCoffOffset = CoffAlign(mCoffOffset);
    496   if (SectionCount == 0) {
    497     mDataOffset = mCoffOffset;
    498   }
    499 
    500   //
    501   //  The HII resource sections.
    502   //
    503   mHiiRsrcOffset = mCoffOffset;
    504   for (i = 0; i < mEhdr->e_shnum; i++) {
    505     Elf_Shdr *shdr = GetShdrByIndex(i);
    506     if (IsHiiRsrcShdr(shdr)) {
    507       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
    508         // the alignment field is valid
    509         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
    510           // if the section address is aligned we must align PE/COFF
    511           mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
    512         } else {
    513           Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");
    514         }
    515       }
    516       if (shdr->sh_size != 0) {
    517         mHiiRsrcOffset = mCoffOffset;
    518         mCoffSectionsOffset[i] = mCoffOffset;
    519         mCoffOffset += shdr->sh_size;
    520         mCoffOffset = CoffAlign(mCoffOffset);
    521         SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);
    522       }
    523       break;
    524     }
    525   }
    526 
    527   mRelocOffset = mCoffOffset;
    528 
    529   //
    530   // Allocate base Coff file.  Will be expanded later for relocations.
    531   //
    532   mCoffFile = (UINT8 *)malloc(mCoffOffset);
    533   if (mCoffFile == NULL) {
    534     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
    535   }
    536   assert (mCoffFile != NULL);
    537   memset(mCoffFile, 0, mCoffOffset);
    538 
    539   //
    540   // Fill headers.
    541   //
    542   DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;
    543   DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
    544   DosHdr->e_lfanew = mNtHdrOffset;
    545 
    546   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);
    547 
    548   NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;
    549 
    550   switch (mEhdr->e_machine) {
    551   case EM_386:
    552     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
    553     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
    554     break;
    555   case EM_ARM:
    556     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;
    557     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
    558     break;
    559   default:
    560     VerboseMsg ("%s unknown e_machine type %hu. Assume IA-32", mInImageName, mEhdr->e_machine);
    561     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
    562     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
    563   }
    564 
    565   NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections;
    566   NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);
    567   mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;
    568   NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
    569   NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;
    570   NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);
    571   NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE
    572     | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
    573     | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
    574     | EFI_IMAGE_FILE_32BIT_MACHINE;
    575 
    576   NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;
    577   NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;
    578   NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;
    579   NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;
    580 
    581   NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset;
    582 
    583   NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset;
    584   NtHdr->Pe32.OptionalHeader.ImageBase = 0;
    585   NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment;
    586   NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment;
    587   NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;
    588 
    589   NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset;
    590   NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
    591 
    592   //
    593   // Section headers.
    594   //
    595   if ((mDataOffset - mTextOffset) > 0) {
    596     CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,
    597             EFI_IMAGE_SCN_CNT_CODE
    598             | EFI_IMAGE_SCN_MEM_EXECUTE
    599             | EFI_IMAGE_SCN_MEM_READ);
    600   } else {
    601     // Don't make a section of size 0.
    602     NtHdr->Pe32.FileHeader.NumberOfSections--;
    603   }
    604 
    605   if ((mHiiRsrcOffset - mDataOffset) > 0) {
    606     CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,
    607             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
    608             | EFI_IMAGE_SCN_MEM_WRITE
    609             | EFI_IMAGE_SCN_MEM_READ);
    610   } else {
    611     // Don't make a section of size 0.
    612     NtHdr->Pe32.FileHeader.NumberOfSections--;
    613   }
    614 
    615   if ((mRelocOffset - mHiiRsrcOffset) > 0) {
    616     CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,
    617             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
    618             | EFI_IMAGE_SCN_MEM_READ);
    619 
    620     NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;
    621     NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;
    622   } else {
    623     // Don't make a section of size 0.
    624     NtHdr->Pe32.FileHeader.NumberOfSections--;
    625   }
    626 
    627 }
    628 
    629 STATIC
    630 BOOLEAN
    631 WriteSections32 (
    632   SECTION_FILTER_TYPES  FilterType
    633   )
    634 {
    635   UINT32      Idx;
    636   Elf_Shdr    *SecShdr;
    637   UINT32      SecOffset;
    638   BOOLEAN     (*Filter)(Elf_Shdr *);
    639 
    640   //
    641   // Initialize filter pointer
    642   //
    643   switch (FilterType) {
    644     case SECTION_TEXT:
    645       Filter = IsTextShdr;
    646       break;
    647     case SECTION_HII:
    648       Filter = IsHiiRsrcShdr;
    649       break;
    650     case SECTION_DATA:
    651       Filter = IsDataShdr;
    652       break;
    653     default:
    654       return FALSE;
    655   }
    656 
    657   //
    658   // First: copy sections.
    659   //
    660   for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {
    661     Elf_Shdr *Shdr = GetShdrByIndex(Idx);
    662     if ((*Filter)(Shdr)) {
    663       switch (Shdr->sh_type) {
    664       case SHT_PROGBITS:
    665         /* Copy.  */
    666         memcpy(mCoffFile + mCoffSectionsOffset[Idx],
    667               (UINT8*)mEhdr + Shdr->sh_offset,
    668               Shdr->sh_size);
    669         break;
    670 
    671       case SHT_NOBITS:
    672         memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);
    673         break;
    674 
    675       default:
    676         //
    677         //  Ignore for unkown section type.
    678         //
    679         VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);
    680         break;
    681       }
    682     }
    683   }
    684 
    685   //
    686   // Second: apply relocations.
    687   //
    688   for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {
    689     //
    690     // Determine if this is a relocation section.
    691     //
    692     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
    693     if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {
    694       continue;
    695     }
    696 
    697     //
    698     // Relocation section found.  Now extract section information that the relocations
    699     // apply to in the ELF data and the new COFF data.
    700     //
    701     SecShdr = GetShdrByIndex(RelShdr->sh_info);
    702     SecOffset = mCoffSectionsOffset[RelShdr->sh_info];
    703 
    704     //
    705     // Only process relocations for the current filter type.
    706     //
    707     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {
    708       UINT32 RelOffset;
    709 
    710       //
    711       // Determine the symbol table referenced by the relocation data.
    712       //
    713       Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
    714       UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;
    715 
    716       //
    717       // Process all relocation entries for this section.
    718       //
    719       for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {
    720         //
    721         // Set pointer to relocation entry
    722         //
    723         Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);
    724 
    725         //
    726         // Set pointer to symbol table entry associated with the relocation entry.
    727         //
    728         Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
    729 
    730         Elf_Shdr *SymShdr;
    731         UINT8 *Targ;
    732         UINT16 Address;
    733 
    734         //
    735         // Check section header index found in symbol table and get the section
    736         // header location.
    737         //
    738         if (Sym->st_shndx == SHN_UNDEF
    739             || Sym->st_shndx >= mEhdr->e_shnum) {
    740           const UINT8 *SymName = GetSymName(Sym);
    741           if (SymName == NULL) {
    742             SymName = (const UINT8 *)"<unknown>";
    743           }
    744 
    745           Error (NULL, 0, 3000, "Invalid",
    746                  "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type.  "
    747                  "For example, absolute and undefined symbols are not supported.",
    748                  mInImageName, SymName, Sym->st_value);
    749 
    750           exit(EXIT_FAILURE);
    751         }
    752         SymShdr = GetShdrByIndex(Sym->st_shndx);
    753 
    754         //
    755         // Convert the relocation data to a pointer into the coff file.
    756         //
    757         // Note:
    758         //   r_offset is the virtual address of the storage unit to be relocated.
    759         //   sh_addr is the virtual address for the base of the section.
    760         //
    761         Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);
    762 
    763         //
    764         // Determine how to handle each relocation type based on the machine type.
    765         //
    766         if (mEhdr->e_machine == EM_386) {
    767           switch (ELF_R_TYPE(Rel->r_info)) {
    768           case R_386_NONE:
    769             break;
    770           case R_386_32:
    771             //
    772             // Absolute relocation.
    773             //  Converts Targ from a absolute virtual address to the absolute
    774             //  COFF address.
    775             //
    776             *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr
    777               + mCoffSectionsOffset[Sym->st_shndx];
    778             break;
    779           case R_386_PC32:
    780             //
    781             // Relative relocation: Symbol - Ip + Addend
    782             //
    783             *(UINT32 *)Targ = *(UINT32 *)Targ
    784               + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
    785               - (SecOffset - SecShdr->sh_addr);
    786             break;
    787           default:
    788             Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));
    789           }
    790         } else if (mEhdr->e_machine == EM_ARM) {
    791           switch (ELF32_R_TYPE(Rel->r_info)) {
    792           case R_ARM_RBASE:
    793             // No relocation - no action required
    794             // break skipped
    795 
    796           case R_ARM_PC24:
    797           case R_ARM_REL32:
    798           case R_ARM_XPC25:
    799           case R_ARM_THM_PC22:
    800           case R_ARM_THM_JUMP19:
    801           case R_ARM_CALL:
    802           case R_ARM_JMP24:
    803           case R_ARM_THM_JUMP24:
    804           case R_ARM_PREL31:
    805           case R_ARM_MOVW_PREL_NC:
    806           case R_ARM_MOVT_PREL:
    807           case R_ARM_THM_MOVW_PREL_NC:
    808           case R_ARM_THM_MOVT_PREL:
    809           case R_ARM_THM_JMP6:
    810           case R_ARM_THM_ALU_PREL_11_0:
    811           case R_ARM_THM_PC12:
    812           case R_ARM_REL32_NOI:
    813           case R_ARM_ALU_PC_G0_NC:
    814           case R_ARM_ALU_PC_G0:
    815           case R_ARM_ALU_PC_G1_NC:
    816           case R_ARM_ALU_PC_G1:
    817           case R_ARM_ALU_PC_G2:
    818           case R_ARM_LDR_PC_G1:
    819           case R_ARM_LDR_PC_G2:
    820           case R_ARM_LDRS_PC_G0:
    821           case R_ARM_LDRS_PC_G1:
    822           case R_ARM_LDRS_PC_G2:
    823           case R_ARM_LDC_PC_G0:
    824           case R_ARM_LDC_PC_G1:
    825           case R_ARM_LDC_PC_G2:
    826           case R_ARM_GOT_PREL:
    827           case R_ARM_THM_JUMP11:
    828           case R_ARM_THM_JUMP8:
    829           case R_ARM_TLS_GD32:
    830           case R_ARM_TLS_LDM32:
    831           case R_ARM_TLS_IE32:
    832             // Thease are all PC-relative relocations and don't require modification
    833             // GCC does not seem to have the concept of a application that just needs to get relocated.
    834             break;
    835 
    836           case R_ARM_THM_MOVW_ABS_NC:
    837             // MOVW is only lower 16-bits of the addres
    838             Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);
    839             ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);
    840             break;
    841 
    842           case R_ARM_THM_MOVT_ABS:
    843             // MOVT is only upper 16-bits of the addres
    844             Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);
    845             ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);
    846             break;
    847 
    848           case R_ARM_ABS32:
    849           case R_ARM_RABS32:
    850             //
    851             // Absolute relocation.
    852             //
    853             *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];
    854             break;
    855 
    856           default:
    857             Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));
    858           }
    859         }
    860       }
    861     }
    862   }
    863 
    864   return TRUE;
    865 }
    866 
    867 UINTN gMovwOffset = 0;
    868 
    869 STATIC
    870 VOID
    871 WriteRelocations32 (
    872   VOID
    873   )
    874 {
    875   UINT32                           Index;
    876   EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;
    877   EFI_IMAGE_DATA_DIRECTORY         *Dir;
    878   BOOLEAN                          FoundRelocations;
    879   Elf_Dyn                          *Dyn;
    880   Elf_Rel                          *Rel;
    881   UINTN                            RelElementSize;
    882   UINTN                            RelSize;
    883   UINTN                            RelOffset;
    884   UINTN                            K;
    885   Elf32_Phdr                       *DynamicSegment;
    886 
    887   for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {
    888     Elf_Shdr *RelShdr = GetShdrByIndex(Index);
    889     if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {
    890       Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);
    891       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
    892         UINT32 RelIdx;
    893 
    894         FoundRelocations = TRUE;
    895         for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
    896           Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);
    897 
    898           if (mEhdr->e_machine == EM_386) {
    899             switch (ELF_R_TYPE(Rel->r_info)) {
    900             case R_386_NONE:
    901             case R_386_PC32:
    902               //
    903               // No fixup entry required.
    904               //
    905               break;
    906             case R_386_32:
    907               //
    908               // Creates a relative relocation entry from the absolute entry.
    909               //
    910               CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]
    911               + (Rel->r_offset - SecShdr->sh_addr),
    912               EFI_IMAGE_REL_BASED_HIGHLOW);
    913               break;
    914             default:
    915               Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));
    916             }
    917           } else if (mEhdr->e_machine == EM_ARM) {
    918             switch (ELF32_R_TYPE(Rel->r_info)) {
    919             case R_ARM_RBASE:
    920               // No relocation - no action required
    921               // break skipped
    922 
    923             case R_ARM_PC24:
    924             case R_ARM_REL32:
    925             case R_ARM_XPC25:
    926             case R_ARM_THM_PC22:
    927             case R_ARM_THM_JUMP19:
    928             case R_ARM_CALL:
    929             case R_ARM_JMP24:
    930             case R_ARM_THM_JUMP24:
    931             case R_ARM_PREL31:
    932             case R_ARM_MOVW_PREL_NC:
    933             case R_ARM_MOVT_PREL:
    934             case R_ARM_THM_MOVW_PREL_NC:
    935             case R_ARM_THM_MOVT_PREL:
    936             case R_ARM_THM_JMP6:
    937             case R_ARM_THM_ALU_PREL_11_0:
    938             case R_ARM_THM_PC12:
    939             case R_ARM_REL32_NOI:
    940             case R_ARM_ALU_PC_G0_NC:
    941             case R_ARM_ALU_PC_G0:
    942             case R_ARM_ALU_PC_G1_NC:
    943             case R_ARM_ALU_PC_G1:
    944             case R_ARM_ALU_PC_G2:
    945             case R_ARM_LDR_PC_G1:
    946             case R_ARM_LDR_PC_G2:
    947             case R_ARM_LDRS_PC_G0:
    948             case R_ARM_LDRS_PC_G1:
    949             case R_ARM_LDRS_PC_G2:
    950             case R_ARM_LDC_PC_G0:
    951             case R_ARM_LDC_PC_G1:
    952             case R_ARM_LDC_PC_G2:
    953             case R_ARM_GOT_PREL:
    954             case R_ARM_THM_JUMP11:
    955             case R_ARM_THM_JUMP8:
    956             case R_ARM_TLS_GD32:
    957             case R_ARM_TLS_LDM32:
    958             case R_ARM_TLS_IE32:
    959               // Thease are all PC-relative relocations and don't require modification
    960               break;
    961 
    962             case R_ARM_THM_MOVW_ABS_NC:
    963               CoffAddFixup (
    964                 mCoffSectionsOffset[RelShdr->sh_info]
    965                 + (Rel->r_offset - SecShdr->sh_addr),
    966                 EFI_IMAGE_REL_BASED_ARM_MOV32T
    967                 );
    968 
    969               // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction
    970               // Track this address so we can log an error for unsupported sequence of MOVW/MOVT
    971               gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);
    972               break;
    973 
    974             case R_ARM_THM_MOVT_ABS:
    975               if ((gMovwOffset + 4) !=  (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {
    976                 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));
    977               }
    978               break;
    979 
    980             case R_ARM_ABS32:
    981             case R_ARM_RABS32:
    982               CoffAddFixup (
    983                 mCoffSectionsOffset[RelShdr->sh_info]
    984                 + (Rel->r_offset - SecShdr->sh_addr),
    985                 EFI_IMAGE_REL_BASED_HIGHLOW
    986                 );
    987               break;
    988 
    989            default:
    990               Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));
    991             }
    992           } else {
    993             Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine);
    994           }
    995         }
    996       }
    997     }
    998   }
    999 
   1000   if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {
   1001     /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
   1002 
   1003     for (Index = 0; Index < mEhdr->e_phnum; Index++) {
   1004       RelElementSize = 0;
   1005       RelSize = 0;
   1006       RelOffset = 0;
   1007 
   1008       DynamicSegment = GetPhdrByIndex (Index);
   1009 
   1010       if (DynamicSegment->p_type == PT_DYNAMIC) {
   1011         Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);
   1012 
   1013         while (Dyn->d_tag != DT_NULL) {
   1014           switch (Dyn->d_tag) {
   1015             case  DT_REL:
   1016               RelOffset = Dyn->d_un.d_val;
   1017               break;
   1018 
   1019             case  DT_RELSZ:
   1020               RelSize = Dyn->d_un.d_val;
   1021               break;
   1022 
   1023             case  DT_RELENT:
   1024               RelElementSize = Dyn->d_un.d_val;
   1025               break;
   1026 
   1027             default:
   1028               break;
   1029           }
   1030           Dyn++;
   1031         }
   1032         if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {
   1033           Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);
   1034         }
   1035 
   1036         for (Index = 0; Index < mEhdr->e_shnum; Index++) {
   1037           Elf_Shdr *shdr = GetShdrByIndex(Index);
   1038 
   1039           //
   1040           // The PT_DYNAMIC section contains DT_REL relocations whose r_offset
   1041           // field is relative to the base of a segment (or the entire image),
   1042           // and not to the base of an ELF input section as is the case for
   1043           // SHT_REL sections. This means that we cannot fix up such relocations
   1044           // unless we cross-reference ELF sections and segments, considering
   1045           // that the output placement recorded in mCoffSectionsOffset[] is
   1046           // section based, not segment based.
   1047           //
   1048           // Fortunately, there is a simple way around this: we require that the
   1049           // in-memory layout of the ELF and PE/COFF versions of the binary is
   1050           // identical. That way, r_offset will retain its validity as a PE/COFF
   1051           // image offset, and we can record it in the COFF fixup table
   1052           // unmodified.
   1053           //
   1054           if (shdr->sh_addr != mCoffSectionsOffset[Index]) {
   1055             Error (NULL, 0, 3000,
   1056               "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",
   1057               mInImageName);
   1058           }
   1059         }
   1060 
   1061         for (K = 0; K < RelSize; K += RelElementSize) {
   1062 
   1063           if (DynamicSegment->p_paddr == 0) {
   1064             // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL
   1065             // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools
   1066             Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);
   1067           } else {
   1068             // This is how it reads in the generic ELF specification
   1069             Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);
   1070           }
   1071 
   1072           switch (ELF32_R_TYPE (Rel->r_info)) {
   1073           case  R_ARM_RBASE:
   1074             break;
   1075 
   1076           case  R_ARM_RABS32:
   1077             CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);
   1078             break;
   1079 
   1080           default:
   1081             Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));
   1082             break;
   1083           }
   1084         }
   1085         break;
   1086       }
   1087     }
   1088   }
   1089 
   1090   //
   1091   // Pad by adding empty entries.
   1092   //
   1093   while (mCoffOffset & (mCoffAlignment - 1)) {
   1094     CoffAddFixupEntry(0);
   1095   }
   1096 
   1097   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);
   1098   Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
   1099   Dir->Size = mCoffOffset - mRelocOffset;
   1100   if (Dir->Size == 0) {
   1101     // If no relocations, null out the directory entry and don't add the .reloc section
   1102     Dir->VirtualAddress = 0;
   1103     NtHdr->Pe32.FileHeader.NumberOfSections--;
   1104   } else {
   1105     Dir->VirtualAddress = mRelocOffset;
   1106     CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,
   1107             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
   1108             | EFI_IMAGE_SCN_MEM_DISCARDABLE
   1109             | EFI_IMAGE_SCN_MEM_READ);
   1110   }
   1111 
   1112 }
   1113 
   1114 STATIC
   1115 VOID
   1116 WriteDebug32 (
   1117   VOID
   1118   )
   1119 {
   1120   UINT32                              Len;
   1121   EFI_IMAGE_OPTIONAL_HEADER_UNION     *NtHdr;
   1122   EFI_IMAGE_DATA_DIRECTORY            *DataDir;
   1123   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY     *Dir;
   1124   EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;
   1125 
   1126   Len = strlen(mInImageName) + 1;
   1127 
   1128   Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);
   1129   Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
   1130   Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;
   1131   Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
   1132   Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
   1133 
   1134   Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);
   1135   Nb10->Signature = CODEVIEW_SIGNATURE_NB10;
   1136   strcpy ((char *)(Nb10 + 1), mInImageName);
   1137 
   1138 
   1139   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);
   1140   DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];
   1141   DataDir->VirtualAddress = mDebugOffset;
   1142   DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
   1143 }
   1144 
   1145 STATIC
   1146 VOID
   1147 SetImageSize32 (
   1148   VOID
   1149   )
   1150 {
   1151   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
   1152 
   1153   //
   1154   // Set image size
   1155   //
   1156   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);
   1157   NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;
   1158 }
   1159 
   1160 STATIC
   1161 VOID
   1162 CleanUp32 (
   1163   VOID
   1164   )
   1165 {
   1166   if (mCoffSectionsOffset != NULL) {
   1167     free (mCoffSectionsOffset);
   1168   }
   1169 }
   1170 
   1171 
   1172