From 13c5e09c6e28b1b60ab718a90add0f61a200cf10 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Thu, 9 Jul 2015 18:23:10 +0000 Subject: [PATCH] [llvm-readobj] Print MIPS PLT table Now the -mips-plt-got prints both MIPS GOT and PLT tables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241836 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Inputs/got-plt.exe.elf-mipsel | Bin 0 -> 6209 bytes test/tools/llvm-readobj/mips-plt.test | 34 +++ tools/llvm-readobj/ELFDumper.cpp | 237 ++++++++++++------ 3 files changed, 198 insertions(+), 73 deletions(-) create mode 100755 test/tools/llvm-readobj/Inputs/got-plt.exe.elf-mipsel create mode 100644 test/tools/llvm-readobj/mips-plt.test diff --git a/test/tools/llvm-readobj/Inputs/got-plt.exe.elf-mipsel b/test/tools/llvm-readobj/Inputs/got-plt.exe.elf-mipsel new file mode 100755 index 0000000000000000000000000000000000000000..8cdc69ffa56276b071d96e794a53f41bec9ea3e4 GIT binary patch literal 6209 zcmbVQUu>IK6+ix*rY`F`I}2+%vej_bb#WT14zKMPYcS1 zDoda|A$gS6!1Rl93;(B~bQ-qFH-X99!KRH-$VVX~hfz*8GGsrJsMD9v&GqFov1%zc zKt+}X!7wS~$4}y4ln?ZW<$w3dC6;+9emj7(&YMwISV$^iHIVO}m!K zZlqVyF6*+LgOInw?uYey=|z;+k<$JRq!)nySE8S6pZ#L&^td7eqFoZ(rXKye72SZtKE3#IT$i<6t zvL0%QJbML`;MJALd67=c&(7M@EBjYRth1|avP0r+ky;#%?)iEoe9?;Z)T~JVti^u$ zWT5MV`oX(eB-jO;D`;;8?cFk7Lmr7#$H~h zNt1fbU%~!K{y(Uu_EL9$HTB1n$p^zdkCc`w>1<^=oGfLsBiUklF+7=bvf+dM1BYS* z1HFe1e=4-8?CF`zwNV}UGnB{-}>F#@B9gJwOJx%J6u$W zJMgzqToRu;Y4{{oT`oAOIiyZSr;8?+D>~UqSz^VKlZ_=tCVHLJg2XD>gst?nUs@~ zSa#8#ucQiDiKU%Vr3$+`c|1+qB}doSx|Mv!E~MZo%Fz*BI9Elbbg59t7ExHvpjsw7 zx3pl)(!Z4BRC04mP8O;KC5@%#a))r3_;2YGP~`WID?*;rZ9QGOWg2UCydz8(Oc_Y9f-K8gZN+Yg#+g^lT7`)%kwhP)x_kc zxA+nE{s29QRQ$@&%L5pnP~6D>5qZY1pM@amnLIINr=^?!xnGj}ZmZlEHP$V2|I=6-s?l&aA>V@7{H0CX~dDrr*oe|@WeS+k7 zzpC61H0H~JUiTXBQkd&oV}5k?I@Z`7LCiOeIVzZk4b0mi;@iOL2#7Ui^xKu3>xtxd zZ`bCo=;y5)#Pvb)tJ|_*4H&Ff4ClL+?@_7w^9ygTP4WxBa!v9}XA>ajSErd~ksmYL z*MyiW@74K@IPJ!dr;^5mMmgmkb%mes6j1(UV%J}sQ)Pv)f!pL;z$RWkycYZbc-3vs zLVK?Rzv02$AKJIY@y~g_Q?4UrJm|Mi_Q?B49bnEh;%yN8%%i{6zYydt4Szy%FR&SZ zpWGn_fW7_=0pDni!@6$&IIto1_v99AWK1cah1{HbEv&>ZQr~T#uLWNPHtWTQ8W*<6 zzYom!9Zm1me+X>Oh;4|+FM#n=#J7t#3_wX3d>y#oZ7+iP_gCP&i-Xva{{d{)M;l+( zu%vgo@{olRU{gPY`geOa8_xbudGJ2qBfw_iF9>^&0UM&d zWni;D_?B{(81Y|&jQxEExYqE0k30+9?9U!~5m=x=IY+%fM!TpuL}aa1i*H z9{n)%-vJ(N#N#gcGw_tbSg-E`d)xo#mioJ~C93-iZ1F8f`l{(l%1JNwr3CNYgOQ(8qxK8E!N^_6*E%3dkw|SH4E#%5oR|{w2-rV7#!@cEnv!riqvM*g- z>Qm23v63v};LdY81TrF&; zV5jq?B2M48D6;KL$zI5p=2CfEo&D|9(ka1#zMRiG*-Y$#PaioV6xg}Usn`QU{R5&d z40dLzP*^tpj2$0U?i`&?92>I@qB|zvY(-r(R4aT3L!Yww`ChlD_SE!={O+aTDG%Ayp_3+ZJQ-3dSWk>QLJ9v5K>!Rd5nJZac*MfnB5H1 z%&{bcG?SXkXN7kg{a7b%%`eV%nI8^ k-_1acPo5Y_Oxh=o9(`nNrV;#kUh`}Q%uJz8;nJS`3zyfR1poj5 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-readobj/mips-plt.test b/test/tools/llvm-readobj/mips-plt.test new file mode 100644 index 00000000000..ab0824b0be6 --- /dev/null +++ b/test/tools/llvm-readobj/mips-plt.test @@ -0,0 +1,34 @@ +RUN: llvm-readobj -mips-plt-got %p/Inputs/got-plt.exe.elf-mipsel | FileCheck %s + +CHECK: PLT GOT { +CHECK-NEXT: Reserved entries [ +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410814 +CHECK-NEXT: Initial: 0x0 +CHECK-NEXT: Purpose: PLT lazy resolver +CHECK-NEXT: } +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410818 +CHECK-NEXT: Initial: 0x0 +CHECK-NEXT: Purpose: Module pointer +CHECK-NEXT: } +CHECK-NEXT: ] +CHECK-NEXT: Entries [ +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x41081C +CHECK-NEXT: Initial: 0x4007C0 +CHECK-NEXT: Value: 0x0 +CHECK-NEXT: Type: Function (0x2) +CHECK-NEXT: Section: Undefined (0x0) +CHECK-NEXT: Name: puts@GLIBC_2.0 (71) +CHECK-NEXT: } +CHECK-NEXT: Entry { +CHECK-NEXT: Address: 0x410820 +CHECK-NEXT: Initial: 0x4007C0 +CHECK-NEXT: Value: 0x0 +CHECK-NEXT: Type: Function (0x2) +CHECK-NEXT: Section: Undefined (0x0) +CHECK-NEXT: Name: __libc_start_main@GLIBC_2.0 (53) +CHECK-NEXT: } +CHECK-NEXT: ] +CHECK-NEXT: } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index a4b25efeb9b..967e8aa55c9 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -1162,9 +1162,10 @@ public: typedef typename ObjectFile::Elf_Shdr Elf_Shdr; typedef typename ObjectFile::Elf_Sym Elf_Sym; - MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {} + MipsGOTParser(const ObjectFile *Obj, StreamWriter &W); - void parseGOT(const Elf_Shdr &GOTShdr); + void parseGOT(); + void parsePLT(); private: typedef typename ObjectFile::Elf_Addr GOTEntry; @@ -1173,35 +1174,79 @@ private: const ObjectFile *Obj; StreamWriter &W; + llvm::Optional DtPltGot; + llvm::Optional DtLocalGotNum; + llvm::Optional DtGotSym; + llvm::Optional DtMipsPltGot; + llvm::Optional DtJmpRel; std::size_t getGOTTotal(ArrayRef GOT) const; GOTIter makeGOTIter(ArrayRef GOT, std::size_t EntryNum); - bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym); void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It); void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It, const Elf_Sym *Sym, bool IsDynamic); + void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, + StringRef Purpose); + void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, + const Elf_Sym *Sym); }; } template -void MipsGOTParser::parseGOT(const Elf_Shdr &GOTShdr) { +MipsGOTParser::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) + : Obj(Obj), W(W) { + for (const auto &Entry : Obj->dynamic_table()) { + switch (Entry.getTag()) { + case ELF::DT_PLTGOT: + DtPltGot = Entry.getVal(); + break; + case ELF::DT_MIPS_LOCAL_GOTNO: + DtLocalGotNum = Entry.getVal(); + break; + case ELF::DT_MIPS_GOTSYM: + DtGotSym = Entry.getVal(); + break; + case ELF::DT_MIPS_PLTGOT: + DtMipsPltGot = Entry.getVal(); + break; + case ELF::DT_JMPREL: + DtJmpRel = Entry.getVal(); + break; + } + } +} + +template void MipsGOTParser::parseGOT() { // See "Global Offset Table" in Chapter 5 in the following document // for detailed GOT description. // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + if (!DtPltGot) { + W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; + return; + } + if (!DtLocalGotNum) { + W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; + return; + } + if (!DtGotSym) { + W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; + return; + } - ErrorOr> GOT = Obj->getSectionContents(&GOTShdr); - if (!GOT) { - W.startLine() << "The .got section is empty.\n"; + const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot); + if (!GOTShdr) { + W.startLine() << "There is no .got section in the file.\n"; return; } - uint64_t DtLocalGotNum; - uint64_t DtGotSym; - if (!getGOTTags(DtLocalGotNum, DtGotSym)) + ErrorOr> GOT = Obj->getSectionContents(GOTShdr); + if (!GOT) { + W.startLine() << "The .got section is empty.\n"; return; + } - if (DtLocalGotNum > getGOTTotal(*GOT)) { + if (*DtLocalGotNum > getGOTTotal(*GOT)) { W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n"; return; } @@ -1210,37 +1255,37 @@ void MipsGOTParser::parseGOT(const Elf_Shdr &GOTShdr) { const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end(); std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); - if (DtGotSym > DynSymTotal) { + if (*DtGotSym > DynSymTotal) { W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n"; return; } - std::size_t GlobalGotNum = DynSymTotal - DtGotSym; + std::size_t GlobalGotNum = DynSymTotal - *DtGotSym; - if (DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { + if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n"; return; } GOTIter GotBegin = makeGOTIter(*GOT, 0); - GOTIter GotLocalEnd = makeGOTIter(*GOT, DtLocalGotNum); + GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); GOTIter It = GotBegin; DictScope GS(W, "Primary GOT"); - W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0); + W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); { ListScope RS(W, "Reserved entries"); { DictScope D(W, "Entry"); - printGotEntry(GOTShdr.sh_addr, GotBegin, It++); + 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++); + printGotEntry(GOTShdr->sh_addr, GotBegin, It++); W.printString("Purpose", StringRef("Module pointer (GNU extension)")); } } @@ -1248,24 +1293,88 @@ void MipsGOTParser::parseGOT(const Elf_Shdr &GOTShdr) { ListScope LS(W, "Local entries"); for (; It != GotLocalEnd; ++It) { DictScope D(W, "Entry"); - printGotEntry(GOTShdr.sh_addr, GotBegin, It); + printGotEntry(GOTShdr->sh_addr, GotBegin, It); } } { ListScope GS(W, "Global entries"); - GOTIter GotGlobalEnd = makeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum); - const Elf_Sym *GotDynSym = DynSymBegin + DtGotSym; + GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum); + const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; for (; It != GotGlobalEnd; ++It) { DictScope D(W, "Entry"); - printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++, true); + printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, true); } } - std::size_t SpecGotNum = getGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum; + std::size_t SpecGotNum = getGOTTotal(*GOT) - *DtLocalGotNum - GlobalGotNum; W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum)); } +template void MipsGOTParser::parsePLT() { + if (!DtMipsPltGot) { + W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n"; + return; + } + if (!DtJmpRel) { + W.startLine() << "Cannot find JMPREL dynamic table tag.\n"; + return; + } + + const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot); + if (!PLTShdr) { + W.startLine() << "There is no .got.plt section in the file.\n"; + return; + } + ErrorOr> PLT = Obj->getSectionContents(PLTShdr); + if (!PLT) { + W.startLine() << "The .got.plt section is empty.\n"; + return; + } + + const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel); + if (!PLTShdr) { + W.startLine() << "There is no .rel.plt section in the file.\n"; + return; + } + + GOTIter PLTBegin = makeGOTIter(*PLT, 0); + GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT)); + GOTIter It = PLTBegin; + + DictScope GS(W, "PLT GOT"); + { + ListScope RS(W, "Reserved entries"); + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver"); + if (It != PLTEnd) + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer"); + } + { + ListScope GS(W, "Entries"); + + switch (PLTRelShdr->sh_type) { + case ELF::SHT_REL: + for (typename ObjectFile::Elf_Rel_Iter RI = Obj->rel_begin(PLTRelShdr), + RE = Obj->rel_end(PLTRelShdr); + RI != RE && It != PLTEnd; ++RI, ++It) { + const Elf_Sym *Sym = + Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym); + } + break; + case ELF::SHT_RELA: + for (typename ObjectFile::Elf_Rela_Iter RI = Obj->rela_begin(PLTRelShdr), + RE = Obj->rela_end(PLTRelShdr); + RI != RE && It != PLTEnd; ++RI, ++It) { + const Elf_Sym *Sym = + Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym); + } + break; + } + } +} + template std::size_t MipsGOTParser::getGOTTotal(ArrayRef GOT) const { return GOT.size() / sizeof(GOTEntry); @@ -1278,36 +1387,6 @@ MipsGOTParser::makeGOTIter(ArrayRef GOT, std::size_t EntryNum) { return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry)); } -template -bool MipsGOTParser::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) { - bool FoundLocalGotNum = false; - bool FoundGotSym = false; - for (const auto &Entry : Obj->dynamic_table()) { - switch (Entry.getTag()) { - case ELF::DT_MIPS_LOCAL_GOTNO: - LocalGotNum = Entry.getVal(); - FoundLocalGotNum = true; - break; - case ELF::DT_MIPS_GOTSYM: - GotSym = Entry.getVal(); - FoundGotSym = true; - break; - } - } - - if (!FoundLocalGotNum) { - W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; - return false; - } - - if (!FoundGotSym) { - W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; - return false; - } - - return true; -} - template void MipsGOTParser::printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It) { @@ -1335,32 +1414,44 @@ void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, W.printNumber("Name", FullSymbolName, Sym->st_name); } -template void ELFDumper::printMipsPLTGOT() { - if (Obj->getHeader()->e_machine != EM_MIPS) { - W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; - return; - } +template +void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, + GOTIter It, StringRef Purpose) { + DictScope D(W, "Entry"); + int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); + W.printHex("Address", PLTAddr + Offset); + W.printHex("Initial", *It); + W.printString("Purpose", Purpose); +} - llvm::Optional DtPltGot; - for (const auto &Entry : Obj->dynamic_table()) { - if (Entry.getTag() == ELF::DT_PLTGOT) { - DtPltGot = Entry.getVal(); - break; - } - } +template +void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, + GOTIter It, const Elf_Sym *Sym) { + DictScope D(W, "Entry"); + int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); + W.printHex("Address", PLTAddr + Offset); + W.printHex("Initial", *It); + W.printHex("Value", Sym->st_value); + W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); - if (!DtPltGot) { - W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; - return; - } + unsigned SectionIndex = 0; + StringRef SectionName; + getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex); + W.printHex("Section", SectionName, SectionIndex); - const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot); - if (!GotShdr) { - W.startLine() << "There is no .got section in the file.\n"; + std::string FullSymbolName = getFullSymbolName(*Obj, Sym, true); + W.printNumber("Name", FullSymbolName, Sym->st_name); +} + +template void ELFDumper::printMipsPLTGOT() { + if (Obj->getHeader()->e_machine != EM_MIPS) { + W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; return; } - MipsGOTParser(Obj, W).parseGOT(*GotShdr); + MipsGOTParser GOTParser(Obj, W); + GOTParser.parseGOT(); + GOTParser.parsePLT(); } static const EnumEntry ElfMipsISAExtType[] = { -- 2.34.1