From 0eba9bcf82b3f7b913738c2b52fc5483b916890c Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Sat, 2 Dec 2017 13:06:35 +0000 Subject: [PATCH] [llvm-readobj] Print static MIPS GOT If a linked binary file contains a dynamic section, the GOT layout defined by the dynamic section entries. In a statically linked file the GOT is just a series of entries. This change teaches `llvm-readobj` to print the GOT in that case. That provides a feature parity with GNU `readelf`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319616 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm-readobj/Inputs/got-static.exe.mips | Bin 0 -> 1168 bytes test/tools/llvm-readobj/mips-got.test | 39 +++++++- tools/llvm-readobj/ELFDumper.cpp | 85 +++++++++++------- 3 files changed, 93 insertions(+), 31 deletions(-) create mode 100755 test/tools/llvm-readobj/Inputs/got-static.exe.mips diff --git a/test/tools/llvm-readobj/Inputs/got-static.exe.mips b/test/tools/llvm-readobj/Inputs/got-static.exe.mips new file mode 100755 index 0000000000000000000000000000000000000000..a369e32bd8834049bd921c9bebc5608682741365 GIT binary patch literal 1168 zcmb7EO=}ZT6umQ@rl~HPf=Hn*MsN|j7_D|A1(^vXB19{+3petZ*vS~sOvt=KU0HYT z{5$@P?)o>fUkorW<)Z-25+GL#wFQ$M_l~=(iz!r%lF5nl0W1* zSh8*B@0zpS^4LG0i?=;TJ?A||zbCAB{SNQ&j-R(3nt31Y#6PZZy`NMvtg2_C%897q zX|8kf=lt0hrD~l|H3GUghf;&O_O8O@s@MIaPS#gPz20&6M4e=vepiVq#-}Jkwn$Qc z`>OK+w4Pf1*;{YlygyFz!D#p;FKbDrML8M|D@n|-q^z_gc-cv=^>j2i(*?Tym+VeN z_D~Vx4!IKqzYQ<^zR35G*MMf;B{Z>|$M;440^mMy2WHSj40vfd<0UkgYR$e2vtRsX zyfBYFUsdz@AMZp7->dIIx8FVLkPa&W{tJQ>_6BedU@z8f0!up?YVc2h7vB%7wUT!Q K{>~>so4mgcXmMWv literal 0 HcmV?d00001 diff --git a/test/tools/llvm-readobj/mips-got.test b/test/tools/llvm-readobj/mips-got.test index 20215871ef0..65ccf13f2b4 100644 --- a/test/tools/llvm-readobj/mips-got.test +++ b/test/tools/llvm-readobj/mips-got.test @@ -8,8 +8,10 @@ RUN: llvm-readobj -mips-plt-got %p/Inputs/got-tls.so.elf-mips64el | \ RUN: FileCheck %s -check-prefix GOT-TLS RUN: llvm-readobj -mips-plt-got %p/Inputs/got-empty.exe.mipsel | \ RUN: FileCheck %s -check-prefix GOT-EMPTY +RUN: llvm-readobj -mips-plt-got %p/Inputs/got-static.exe.mips | \ +RUN: FileCheck %s -check-prefix GOT-STATIC -GOT-OBJ: Cannot find PLTGOT dynamic table tag. +GOT-OBJ: Cannot find .got section GOT-EXE: Primary GOT { GOT-EXE-NEXT: Canonical gp value: 0x418880 @@ -329,3 +331,38 @@ GOT-EMPTY-NEXT: Global entries [ GOT-EMPTY-NEXT: ] GOT-EMPTY-NEXT: Number of TLS and multi-GOT entries: 2 GOT-EMPTY-NEXT: } + +GOT-STATIC: Static GOT { +GOT-STATIC-NEXT: Canonical gp value: 0x418100 +GOT-STATIC-NEXT: Reserved entries [ +GOT-STATIC-NEXT: Entry { +GOT-STATIC-NEXT: Address: 0x410110 +GOT-STATIC-NEXT: Access: -32752 +GOT-STATIC-NEXT: Initial: 0x0 +GOT-STATIC-NEXT: Purpose: Lazy resolver +GOT-STATIC-NEXT: } +GOT-STATIC-NEXT: Entry { +GOT-STATIC-NEXT: Address: 0x410114 +GOT-STATIC-NEXT: Access: -32748 +GOT-STATIC-NEXT: Initial: 0x80000000 +GOT-STATIC-NEXT: Purpose: Module pointer (GNU extension) +GOT-STATIC-NEXT: } +GOT-STATIC-NEXT: ] +GOT-STATIC-NEXT: Local entries [ +GOT-STATIC-NEXT: Entry { +GOT-STATIC-NEXT: Address: 0x410118 +GOT-STATIC-NEXT: Access: -32744 +GOT-STATIC-NEXT: Initial: 0x400000 +GOT-STATIC-NEXT: } +GOT-STATIC-NEXT: Entry { +GOT-STATIC-NEXT: Address: 0x41011C +GOT-STATIC-NEXT: Access: -32740 +GOT-STATIC-NEXT: Initial: 0x400100 +GOT-STATIC-NEXT: } +GOT-STATIC-NEXT: Entry { +GOT-STATIC-NEXT: Address: 0x410120 +GOT-STATIC-NEXT: Access: -32736 +GOT-STATIC-NEXT: Initial: 0x400104 +GOT-STATIC-NEXT: } +GOT-STATIC-NEXT: ] +GOT-STATIC-NEXT: } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index df01e265798..8bc088afe43 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -1910,6 +1910,7 @@ public: MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, Elf_Dyn_Range DynTable, ScopedPrinter &W); + void parseStaticGOT(); void parseGOT(); void parsePLT(); @@ -1926,6 +1927,7 @@ private: std::size_t getGOTTotal(ArrayRef GOT) const; const GOTEntry *makeGOTIter(ArrayRef GOT, std::size_t EntryNum); + void printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num); void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It); void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, @@ -1965,6 +1967,50 @@ MipsGOTParser::MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, } } +template +void MipsGOTParser::printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num) { + ArrayRef GOT = unwrapOrError(Obj->getSectionContents(GOTShdr)); + + const GOTEntry *GotBegin = makeGOTIter(GOT, 0); + const GOTEntry *GotEnd = makeGOTIter(GOT, Num); + const GOTEntry *It = GotBegin; + + W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); + { + ListScope RS(W, "Reserved entries"); + + { + DictScope D(W, "Entry"); + printGotEntry(GOTShdr->sh_addr, GotBegin, It++); + W.printString("Purpose", StringRef("Lazy resolver")); + } + + if (It != GotEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) { + DictScope D(W, "Entry"); + printGotEntry(GOTShdr->sh_addr, GotBegin, It++); + W.printString("Purpose", StringRef("Module pointer (GNU extension)")); + } + } + { + ListScope LS(W, "Local entries"); + for (; It != GotEnd; ++It) { + DictScope D(W, "Entry"); + printGotEntry(GOTShdr->sh_addr, GotBegin, It); + } + } +} + +template void MipsGOTParser::parseStaticGOT() { + const Elf_Shdr *GOTShdr = findSectionByName(*Obj, ".got"); + if (!GOTShdr) { + W.startLine() << "Cannot find .got section.\n"; + return; + } + + DictScope GS(W, "Static GOT"); + printLocalGOT(GOTShdr, GOTShdr->sh_size / sizeof(GOTEntry)); +} + template void MipsGOTParser::parseGOT() { // See "Global Offset Table" in Chapter 5 in the following document // for detailed GOT description. @@ -2007,42 +2053,17 @@ template void MipsGOTParser::parseGOT() { if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT)) report_fatal_error("Number of GOT entries exceeds the size of GOT section"); - const GOTEntry *GotBegin = makeGOTIter(GOT, 0); - const GOTEntry *GotLocalEnd = makeGOTIter(GOT, *DtLocalGotNum); - const GOTEntry *It = GotBegin; - DictScope GS(W, "Primary GOT"); + printLocalGOT(GOTShdr, *DtLocalGotNum); - W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); - { - ListScope RS(W, "Reserved entries"); - - { - DictScope D(W, "Entry"); - printGotEntry(GOTShdr->sh_addr, GotBegin, It++); - W.printString("Purpose", StringRef("Lazy resolver")); - } - - if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) { - DictScope D(W, "Entry"); - printGotEntry(GOTShdr->sh_addr, GotBegin, It++); - W.printString("Purpose", StringRef("Module pointer (GNU extension)")); - } - } - { - ListScope LS(W, "Local entries"); - for (; It != GotLocalEnd; ++It) { - DictScope D(W, "Entry"); - printGotEntry(GOTShdr->sh_addr, GotBegin, It); - } - } { ListScope GS(W, "Global entries"); + const GOTEntry *GotBegin = makeGOTIter(GOT, 0); const GOTEntry *GotGlobalEnd = makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum); const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; - for (; It != GotGlobalEnd; ++It) { + for (auto It = makeGOTIter(GOT, *DtLocalGotNum); It != GotGlobalEnd; ++It) { DictScope D(W, "Entry"); printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable); @@ -2197,8 +2218,12 @@ template void ELFDumper::printMipsPLTGOT() { } MipsGOTParser GOTParser(this, Obj, dynamic_table(), W); - GOTParser.parseGOT(); - GOTParser.parsePLT(); + if (dynamic_table().empty()) + GOTParser.parseStaticGOT(); + else { + GOTParser.parseGOT(); + GOTParser.parsePLT(); + } } static const EnumEntry ElfMipsISAExtType[] = { -- 2.50.1