X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FGenFw%2FElf64Convert.c;h=15da89c755fe755f6edbb92ec9f7be9172d85113;hp=fb85b3821b38afa044e92541aa762f249baf9ed8;hb=c6a14de3ef30291918f3b15436cf6a75db413eea;hpb=0b6249f5902f85a9c1a438878b27f8d7ef960a41 diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index fb85b3821b..15da89c755 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -1,7 +1,7 @@ /** @file Elf64 convert solution -Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available @@ -94,6 +94,15 @@ STATIC Elf_Ehdr *mEhdr; STATIC Elf_Shdr *mShdrBase; STATIC Elf_Phdr *mPhdrBase; +// +// GOT information +// +STATIC Elf_Shdr *mGOTShdr = NULL; +STATIC UINT32 mGOTShindex = 0; +STATIC UINT32 *mGOTCoffEntries = NULL; +STATIC UINT32 mGOTMaxCoffEntries = 0; +STATIC UINT32 mGOTNumCoffEntries = 0; + // // Coff information // @@ -171,6 +180,10 @@ InitializeElf64 ( // VerboseMsg ("Create COFF Section Offset Buffer"); mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32)); + if (mCoffSectionsOffset == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return FALSE; + } memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32)); // @@ -197,8 +210,11 @@ GetShdrByIndex ( UINT32 Num ) { - if (Num >= mEhdr->e_shnum) - return NULL; + if (Num >= mEhdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num); + exit(EXIT_FAILURE); + } + return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize); } @@ -255,6 +271,194 @@ IsDataShdr ( return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); } +STATIC +BOOLEAN +IsStrtabShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0); +} + +STATIC +Elf_Shdr * +FindStrtabShdr ( + VOID + ) +{ + UINT32 i; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsStrtabShdr(shdr)) { + return shdr; + } + } + return NULL; +} + +STATIC +const UINT8 * +GetSymName ( + Elf_Sym *Sym + ) +{ + Elf_Shdr *StrtabShdr; + UINT8 *StrtabContents; + BOOLEAN foundEnd; + UINT32 i; + + if (Sym->st_name == 0) { + return NULL; + } + + StrtabShdr = FindStrtabShdr(); + if (StrtabShdr == NULL) { + return NULL; + } + + assert(Sym->st_name < StrtabShdr->sh_size); + + StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset; + + foundEnd = FALSE; + for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) { + foundEnd = (BOOLEAN)(StrtabContents[i] == 0); + } + assert(foundEnd); + + return StrtabContents + Sym->st_name; +} + +// +// Find the ELF section hosting the GOT from an ELF Rva +// of a single GOT entry. Normally, GOT is placed in +// ELF .text section, so assume once we find in which +// section the GOT is, all GOT entries are there, and +// just verify this. +// +STATIC +VOID +FindElfGOTSectionFromGOTEntryElfRva ( + Elf64_Addr GOTEntryElfRva + ) +{ + UINT32 i; + if (mGOTShdr != NULL) { + if (GOTEntryElfRva >= mGOTShdr->sh_addr && + GOTEntryElfRva < mGOTShdr->sh_addr + mGOTShdr->sh_size) { + return; + } + Error (NULL, 0, 3000, "Unsupported", "FindElfGOTSectionFromGOTEntryElfRva: GOT entries found in multiple sections."); + exit(EXIT_FAILURE); + } + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (GOTEntryElfRva >= shdr->sh_addr && + GOTEntryElfRva < shdr->sh_addr + shdr->sh_size) { + mGOTShdr = shdr; + mGOTShindex = i; + return; + } + } + Error (NULL, 0, 3000, "Invalid", "FindElfGOTSectionFromGOTEntryElfRva: ElfRva 0x%016LX for GOT entry not found in any section.", GOTEntryElfRva); + exit(EXIT_FAILURE); +} + +// +// Stores locations of GOT entries in COFF image. +// Returns TRUE if GOT entry is new. +// Simple implementation as number of GOT +// entries is expected to be low. +// + +STATIC +BOOLEAN +AccumulateCoffGOTEntries ( + UINT32 GOTCoffEntry + ) +{ + UINT32 i; + if (mGOTCoffEntries != NULL) { + for (i = 0; i < mGOTNumCoffEntries; i++) { + if (mGOTCoffEntries[i] == GOTCoffEntry) { + return FALSE; + } + } + } + if (mGOTCoffEntries == NULL) { + mGOTCoffEntries = (UINT32*)malloc(5 * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries = 5; + mGOTNumCoffEntries = 0; + } else if (mGOTNumCoffEntries == mGOTMaxCoffEntries) { + mGOTCoffEntries = (UINT32*)realloc(mGOTCoffEntries, 2 * mGOTMaxCoffEntries * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries += mGOTMaxCoffEntries; + } + mGOTCoffEntries[mGOTNumCoffEntries++] = GOTCoffEntry; + return TRUE; +} + +// +// 32-bit Unsigned integer comparator for qsort. +// +STATIC +int +UINT32Comparator ( + const void* lhs, + const void* rhs + ) +{ + if (*(const UINT32*)lhs < *(const UINT32*)rhs) { + return -1; + } + return *(const UINT32*)lhs > *(const UINT32*)rhs; +} + +// +// Emit accumulated Coff GOT entry relocations into +// Coff image. This function performs its job +// once and then releases the entry list, so +// it can safely be called multiple times. +// +STATIC +VOID +EmitGOTRelocations ( + VOID + ) +{ + UINT32 i; + if (mGOTCoffEntries == NULL) { + return; + } + // + // Emit Coff relocations with Rvas ordered. + // + qsort( + mGOTCoffEntries, + mGOTNumCoffEntries, + sizeof *mGOTCoffEntries, + UINT32Comparator); + for (i = 0; i < mGOTNumCoffEntries; i++) { + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mGOTCoffEntries[i]); + CoffAddFixup( + mGOTCoffEntries[i], + EFI_IMAGE_REL_BASED_DIR64); + } + free(mGOTCoffEntries); + mGOTCoffEntries = NULL; + mGOTMaxCoffEntries = 0; + mGOTNumCoffEntries = 0; +} + // // Elf functions interface implementation // @@ -287,7 +491,7 @@ ScanSections64 ( mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); break; default: - VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine); + VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine); mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); break; } @@ -309,6 +513,15 @@ ScanSections64 ( } } + // + // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT + // + if (mCoffAlignment > MAX_COFF_ALIGNMENT) { + Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT."); + assert (FALSE); + } + + // // Move the PE/COFF header right before the first section. This will help us // save space when converting to TE. @@ -458,6 +671,10 @@ ScanSections64 ( // Allocate base Coff file. Will be expanded later for relocations. // mCoffFile = (UINT8 *)malloc(mCoffOffset); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); memset(mCoffFile, 0, mCoffOffset); // @@ -563,6 +780,7 @@ WriteSections64 ( Elf_Shdr *SecShdr; UINT32 SecOffset; BOOLEAN (*Filter)(Elf_Shdr *); + Elf64_Addr GOTEntryRva; // // Initialize filter pointer @@ -590,6 +808,9 @@ WriteSections64 ( switch (Shdr->sh_type) { case SHT_PROGBITS: /* Copy. */ + if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) { + return FALSE; + } memcpy(mCoffFile + mCoffSectionsOffset[Idx], (UINT8*)mEhdr + Shdr->sh_offset, (size_t) Shdr->sh_size); @@ -622,6 +843,20 @@ WriteSections64 ( continue; } + // + // If this is a ET_DYN (PIE) executable, we will encounter a dynamic SHT_RELA + // section that applies to the entire binary, and which will have its section + // index set to #0 (which is a NULL section with the SHF_ALLOC bit cleared). + // + // In the absence of GOT based relocations, + // this RELA section will contain redundant R_xxx_RELATIVE relocations, one + // for every R_xxx_xx64 relocation appearing in the per-section RELA sections. + // (i.e., .rela.text and .rela.data) + // + if (RelShdr->sh_info == 0) { + continue; + } + // // Relocation section found. Now extract section information that the relocations // apply to in the ELF data and the new COFF data. @@ -664,9 +899,18 @@ WriteSections64 ( // header location. // if (Sym->st_shndx == SHN_UNDEF - || Sym->st_shndx == SHN_ABS - || Sym->st_shndx > mEhdr->e_shnum) { - Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName); + || Sym->st_shndx >= mEhdr->e_shnum) { + const UINT8 *SymName = GetSymName(Sym); + if (SymName == NULL) { + SymName = (const UINT8 *)""; + } + + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); + + exit(EXIT_FAILURE); } SymShdr = GetShdrByIndex(Sym->st_shndx); @@ -694,41 +938,90 @@ WriteSections64 ( // Absolute relocation. // VerboseMsg ("R_X86_64_64"); - VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", - (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), *(UINT64 *)Targ); *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); break; case R_X86_64_32: VerboseMsg ("R_X86_64_32"); - VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", - (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), *(UINT32 *)Targ); *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); break; case R_X86_64_32S: VerboseMsg ("R_X86_64_32S"); - VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", - (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), *(UINT32 *)Targ); *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); break; + + case R_X86_64_PLT32: + // + // Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is + // possible since we know all code symbol references resolve to + // definitions in the same module (UEFI has no shared libraries), + // and so there is never a reason to jump via a PLT entry, + // allowing us to resolve the reference using the symbol directly. + // + VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ..."); + /* fall through */ case R_X86_64_PC32: // // Relative relocation: Symbol - Ip + Addend // VerboseMsg ("R_X86_64_PC32"); - VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", - (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), *(UINT32 *)Targ); *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) - (SecOffset - SecShdr->sh_addr)); VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); break; + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + VerboseMsg ("R_X86_64_GOTPCREL family"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + GOTEntryRva = Rel->r_offset - Rel->r_addend + *(INT32 *)Targ; + FindElfGOTSectionFromGOTEntryElfRva(GOTEntryRva); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + GOTEntryRva += (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr); // ELF Rva -> COFF Rva + if (AccumulateCoffGOTEntries((UINT32)GOTEntryRva)) { + // + // Relocate GOT entry if it's the first time we run into it + // + Targ = mCoffFile + GOTEntryRva; + // + // Limitation: The following three statements assume memory + // at *Targ is valid because the section containing the GOT + // has already been copied from the ELF image to the Coff image. + // This pre-condition presently holds because the GOT is placed + // in section .text, and the ELF text sections are all copied + // prior to reaching this point. + // If the pre-condition is violated in the future, this fixup + // either needs to be deferred after the GOT section is copied + // to the Coff image, or the fixup should be performed on the + // source Elf image instead of the destination Coff image. + // + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)GOTEntryRva, + *(UINT64 *)Targ); + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); + } + break; default: Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } @@ -737,26 +1030,59 @@ WriteSections64 ( switch (ELF_R_TYPE(Rel->r_info)) { case R_AARCH64_ADR_PREL_PG_HI21: - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_LDST8_ABS_LO12_NC: - case R_AARCH64_LDST16_ABS_LO12_NC: - case R_AARCH64_LDST32_ABS_LO12_NC: - case R_AARCH64_LDST64_ABS_LO12_NC: - case R_AARCH64_LDST128_ABS_LO12_NC: // // AArch64 PG_H21 relocations are typically paired with ABS_LO12 // relocations, where a PC-relative reference with +/- 4 GB range is // split into a relative high part and an absolute low part. Since // the absolute low part represents the offset into a 4 KB page, we + // either have to convert the ADRP into an ADR instruction, or we + // need to use a section alignment of at least 4 KB, so that the + // binary appears at a correct offset at runtime. In any case, we // have to make sure that the 4 KB relative offsets of both the // section containing the reference as well as the section to which // it refers have not been changed during PE/COFF conversion (i.e., // in ScanSections64() above). // + if (mCoffAlignment < 0x1000) { + // + // Attempt to convert the ADRP into an ADR instruction. + // This is only possible if the symbol is within +/- 1 MB. + // + INT64 Offset; + + // Decode the ADRP instruction + Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8); + Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12)); + + // + // ADRP offset is relative to the previous page boundary, + // whereas ADR offset is relative to the instruction itself. + // So fix up the offset so it points to the page containing + // the symbol. + // + Offset -= (UINTN)(Targ - mCoffFile) & 0xfff; + + if (Offset < -0x100000 || Offset > 0xfffff) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.", + mInImageName); + break; + } + + // Re-encode the offset as an ADR instruction + *(UINT32 *)Targ &= 0x1000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + } + /* fall through */ + + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 || - ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0 || - mCoffAlignment < 0x1000) { - Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires 4 KB section alignment.", + ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.", mInImageName); break; } @@ -833,18 +1159,43 @@ WriteRelocations64 ( switch (ELF_R_TYPE(Rel->r_info)) { case R_X86_64_NONE: case R_X86_64_PC32: + case R_X86_64_PLT32: + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: break; case R_X86_64_64: - VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)), EFI_IMAGE_REL_BASED_DIR64); break; - case R_X86_64_32S: + // + // R_X86_64_32 and R_X86_64_32S are ELF64 relocations emitted when using + // the SYSV X64 ABI small non-position-independent code model. + // R_X86_64_32 is used for unsigned 32-bit immediates with a 32-bit operand + // size. The value is either not extended, or zero-extended to 64 bits. + // R_X86_64_32S is used for either signed 32-bit non-rip-relative displacements + // or signed 32-bit immediates with a 64-bit operand size. The value is + // sign-extended to 64 bits. + // EFI_IMAGE_REL_BASED_HIGHLOW is a PE relocation that uses 32-bit arithmetic + // for rebasing an image. + // EFI PE binaries declare themselves EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE and + // may load above 2GB. If an EFI PE binary with a converted R_X86_64_32S + // relocation is loaded above 2GB, the value will get sign-extended to the + // negative part of the 64-bit address space. The negative part of the 64-bit + // address space is unmapped, so accessing such an address page-faults. + // In order to support R_X86_64_32S, it is necessary to unset + // EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE, and the EFI PE loader must implement + // this flag and abstain from loading such a PE binary above 2GB. + // Since this feature is not supported, support for R_X86_64_32S (and hence + // the small non-position-independent code model) is disabled. + // + // case R_X86_64_32S: case R_X86_64_32: - VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", + VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] @@ -901,10 +1252,32 @@ WriteRelocations64 ( Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); } } + if (mEhdr->e_machine == EM_X86_64 && RelShdr->sh_info == mGOTShindex) { + // + // Tack relocations for GOT entries after other relocations for + // the section the GOT is in, as it's usually found at the end + // of the section. This is done in order to maintain Rva order + // of Coff relocations. + // + EmitGOTRelocations(); + } } } } + if (mEhdr->e_machine == EM_X86_64) { + // + // This is a safety net just in case the GOT is in a section + // with no other relocations and the first invocation of + // EmitGOTRelocations() above was skipped. This invocation + // does not maintain Rva order of Coff relocations. + // At present, with a single text section, all references to + // the GOT and the GOT itself reside in section .text, so + // if there's a GOT at all, the first invocation above + // is executed. + // + EmitGOTRelocations(); + } // // Pad by adding empty entries. // @@ -956,7 +1329,7 @@ WriteDebug64 ( NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; DataDir->VirtualAddress = mDebugOffset; - DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); } STATIC