From 0eba9bcf82b3f7b913738c2b52fc5483b916890c Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Sat, 2 Dec 2017 13:06:35 +0000 Subject: [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 --- tools/llvm-readobj/ELFDumper.cpp | 85 ++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 30 deletions(-) (limited to 'tools') 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[] = { -- cgit v1.2.3