From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=66.163.189.82; helo=sonic306-20.consmr.mail.ne1.yahoo.com; envelope-from=zenith432@users.sourceforge.net; receiver=edk2-devel@lists.01.org Received: from sonic306-20.consmr.mail.ne1.yahoo.com (sonic306-20.consmr.mail.ne1.yahoo.com [66.163.189.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 8763E2119705D for ; Thu, 7 Jun 2018 05:49:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1528375784; bh=KFFKDRrLJoda1bCGV0Bi8U8X+za5F1NBmBOJSAMrMug=; h=Date:From:Reply-To:To:Cc:Subject:References:From:Subject; b=TyzLIa0EOn9KVS45wolQDXhCdWdvq5dU2mZl0peS66jv2ZcOKj92UAWebS/Qzzp21Zg5injw1KgF5iMoXOf83KOEYdVncB6Cu+5ldgnNKvwdKdHOT+ZQoXjI6qS3zi5mxb6Wo7jd8s0ub4NbD74AFi3Z6UH6/R3jkiS6oNCNiJGUwytb6F0UvX8tNhhIqUkgObyEi/nStnHJi6cQE8WJ7c3CTFQNdCnlies4j6vqKwZJiJH6SGuolNFWoAdjICphh/7AWrH1QJOtauTZxGr3wNQYGxqqkGJhkDqbTxkiJFXLyPLmYL5P5xaNN3hG0bp1WII50ICbbAqMP5zDiC/BAQ== X-YMail-OSG: wiTi9oAVM1nlVM.HFC9myuIRxDlq5e0nOVJtkR3OxGu2fnoe497ylKbwiW10LJz LosQgyDDu946.HP6aXKJvlxy6Q4iekbi2cfOAsXBWwh_HYRK6I7yJic8KFIdDmausWShDBjnGoD. nHkqi.aq012e2pJwgkyaSecDXMZqDc6yXGS1TT9hUTDpjyiYSXrhCaNPisqEosfobMuZv.suIA.i XmQljCFjd5AgVTxXgOtMBFXvEurcI1aA8zCTiUfKctBGOXcOygbXiR7ieJt6uwgUCM4P39hRkFun kpJhSd_Hr9jbzeFQyN43C9Ji9CTMyQBOM2tKC8DFlt7PIoqoyelX70vwpB5qasVtoV3nPGpVsmt_ _hGkAbLVrJIEz1EXck2x4DFZLUG1lAC1ac38QMPNQGs7KVRWUCu0AbEzweqCIz9RWjpc0EHGSi.R 9XUZ_G.7VPEceLXBBASoukcGotqJ5ZizNUBeq4DrsHfhrpJDTfmXNXVZZaCidxiTQIFugY8sSlHz UDnBGAB4SMvRMT9ClfcT0InoI5OE3gaYbTnFZLTvnSVnFMCFwd8hca6OHPV0iVLc_k46.c9oCRNo .evPzYfwQF5Ns97wgfo3fF0q5u3HGXMUkmPYAIX6y4XIXv7nndnhcSQLJ1fB9.Kws8Ryck3Z0hxj LORT01ofkI69bxUV3Kw.fxnIZFE_UWwkK8bQqCY78t.nu3mQlqh6Jt7nA4nz5nfervT61r5rqM9I trfZgxzDgkzgiOlGkdJxBDcBQ6sdQM2o7fuBS9y38pKUDwrkZJ9VK..DkY9I_aHKl0iHMNnLAGJN 99pc72G9osJgomkfafzqSJ01Pl2Hvzru7pYXpvaRafexoNwI1VcLZegE7s_oANmpKql08A01O3Zt tvFVVSfbKcZsaF6agaYTYv8_Cc7AtAC3Kgi1T_azcxtJehoaFBPbJ5USIphk7TXKL.NJmYNY_2Q- - Received: from sonic.gate.mail.ne1.yahoo.com by sonic306.consmr.mail.ne1.yahoo.com with HTTP; Thu, 7 Jun 2018 12:49:44 +0000 Date: Thu, 7 Jun 2018 12:49:41 +0000 (UTC) From: Zenith432 Reply-To: Zenith432 To: "edk2-devel@lists.01.org" Cc: LimingGao Message-ID: <1917777633.1686290.1528375781778@mail.yahoo.com> MIME-Version: 1.0 References: <1917777633.1686290.1528375781778.ref@mail.yahoo.com> X-Mailer: WebService/1.1.11950 YahooMailBasic Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0 Subject: [PATCH v2] BaseTools/GenFw: Add X64 GOTPCREL Support to GenFw X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jun 2018 12:49:47 -0000 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Adds support for the following X64 ELF relocations to GenFw R_X86_64_GOTPCREL R_X86_64_GOTPCRELX R_X86_64_REX_GOTPCRELX CC: Shi Steven CC: Yonghong Zhu CC: Liming Gao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Zenith432 --- BaseTools/Source/C/GenFw/Elf64Convert.c | 166 +++++++++++++++++++++++- BaseTools/Source/C/GenFw/elf_common.h | 23 ++++ 2 files changed, 188 insertions(+), 1 deletion(-) diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index c39bdff0..1518c395 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -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 // @@ -322,6 +331,117 @@ GetSymName ( 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; +} + +STATIC +int +__comparator ( + const void* lhs, + const void* rhs + ) +{ + if (*(const UINT32*)lhs < *(const UINT32*)rhs) + return -1; + return *(const UINT32*)lhs > *(const UINT32*)rhs; +} + +STATIC +VOID +EmitGOTRelocations ( + VOID + ) +{ + UINT32 i; + if (mGOTCoffEntries == NULL) + return; + qsort( + mGOTCoffEntries, + mGOTNumCoffEntries, + sizeof *mGOTCoffEntries, + __comparator); + 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 // @@ -698,7 +818,7 @@ WriteSections64 ( // 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 (which we currently don't support), + // 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) @@ -780,6 +900,7 @@ WriteSections64 ( // Determine how to handle each relocation type based on the machine type. // if (mEhdr->e_machine == EM_X86_64) { + Elf64_Addr GOTEntryRva; switch (ELF_R_TYPE(Rel->r_info)) { case R_X86_64_NONE: break; @@ -834,6 +955,32 @@ WriteSections64 ( - (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; + 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)); } @@ -972,6 +1119,9 @@ WriteRelocations64 ( 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", @@ -1040,10 +1190,24 @@ 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. + // + EmitGOTRelocations(); + } } } } + if (mEhdr->e_machine == EM_X86_64) { + // + // Just in case GOT is in a section with no other relocations + // + EmitGOTRelocations(); + } // // Pad by adding empty entries. // diff --git a/BaseTools/Source/C/GenFw/elf_common.h b/BaseTools/Source/C/GenFw/elf_common.h index 766d0e42..50b4e1f2 100644 --- a/BaseTools/Source/C/GenFw/elf_common.h +++ b/BaseTools/Source/C/GenFw/elf_common.h @@ -544,6 +544,12 @@ typedef struct { #define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ #define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ #define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_SIZE32 38 /* 32-bit symbol size */ +#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ +#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS descriptor for relaxation. */ +#define R_386_TLS_DESC 41 /* TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol. */ +#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ +#define R_386_GOT32X 43 /* Load from 32 bit GOT entry, relaxable. */ /* Null relocation */ #define R_AARCH64_NONE 256 /* No relocation */ @@ -1052,6 +1058,23 @@ typedef struct { #define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ #define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ #define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ +#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. */ +#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ #endif /* !_SYS_ELF_COMMON_H_ */ -- 2.17.1