X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-readobj%2FELFDumper.cpp;h=3deeb8dfe5b414e3b82b1aa375813524afe328d2;hb=d60ced8e086559b48d03e8392b2e9fe964a8fcf6;hp=99969fd469f994c4d853e5ebc34f7f604f8cfbd6;hpb=883d498abf4db0e059a1250147e07f4e9c47d9e3;p=oota-llvm.git diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 99969fd469f..3deeb8dfe5b 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -17,6 +17,7 @@ #include "ARMEHABIPrinter.h" #include "Error.h" #include "ObjDumper.h" +#include "StackMapPrinter.h" #include "StreamWriter.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" @@ -47,6 +48,7 @@ public: void printFileHeaders() override; void printSections() override; void printRelocations() override; + void printDynamicRelocations() override; void printSymbols() override; void printDynamicSymbols() override; void printUnwindInfo() override; @@ -54,18 +56,21 @@ public: void printDynamicTable() override; void printNeededLibraries() override; void printProgramHeaders() override; + void printHashTable() override; void printAttributes() override; void printMipsPLTGOT() override; void printMipsABIFlags() override; void printMipsReginfo() override; + void printStackMap() const override; + private: typedef ELFFile ELFO; typedef typename ELFO::Elf_Shdr Elf_Shdr; typedef typename ELFO::Elf_Sym Elf_Sym; - void printSymbol(typename ELFO::Elf_Sym_Iter Symbol); + void printSymbol(const Elf_Sym *Symbol, bool IsDynamic); void printRelocations(const Elf_Shdr *Sec); void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel); @@ -119,9 +124,10 @@ std::error_code createELFDumper(const object::ObjectFile *Obj, template static std::string getFullSymbolName(const ELFO &Obj, - typename ELFO::Elf_Sym_Iter Symbol) { - StringRef SymbolName = errorOrDefault(Obj.getSymbolName(Symbol)); - if (!Symbol.isDynamic()) + const typename ELFO::Elf_Sym *Symbol, + bool IsDynamic) { + StringRef SymbolName = errorOrDefault(Obj.getSymbolName(Symbol, IsDynamic)); + if (!IsDynamic) return SymbolName; std::string FullSymbolName(SymbolName); @@ -139,7 +145,7 @@ static std::string getFullSymbolName(const ELFO &Obj, template static void -getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol, +getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; if (Symbol->isUndefined()) @@ -156,11 +162,10 @@ getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol, SectionName = "Reserved"; else { if (SectionIndex == SHN_XINDEX) - SectionIndex = Obj.getSymbolTableIndex(&*Symbol); - assert(SectionIndex != SHN_XINDEX && - "getSymbolTableIndex should handle this"); - const typename ELFO::Elf_Shdr *Sec = Obj.getSection(SectionIndex); - SectionName = errorOrDefault(Obj.getSectionName(Sec)); + SectionIndex = Obj.getExtendedSymbolTableIndex(&*Symbol); + ErrorOr Sec = Obj.getSection(SectionIndex); + error(Sec.getError()); + SectionName = errorOrDefault(Obj.getSectionName(*Sec)); } } @@ -382,7 +387,8 @@ static const EnumEntry ElfMachineType[] = { LLVM_READOBJ_ENUM_ENT(ELF, EM_RL78 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR ), - LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ) + LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ), + LLVM_READOBJ_ENUM_ENT(ELF, EM_AMDGPU ) }; static const EnumEntry ElfSymbolBindings[] = { @@ -574,7 +580,13 @@ void ELFDumper::printFileHeaders() { W.printEnum ("DataEncoding", Header->e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding)); W.printNumber("FileVersion", Header->e_ident[ELF::EI_VERSION]); - W.printEnum ("OS/ABI", Header->e_ident[ELF::EI_OSABI], + + // Handle architecture specific OS/ABI values. + if (Header->e_machine == ELF::EM_AMDGPU && + Header->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA) + W.printHex("OS/ABI", "AMDGPU_HSA", ELF::ELFOSABI_AMDGPU_HSA); + else + W.printEnum ("OS/ABI", Header->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI)); W.printNumber("ABIVersion", Header->e_ident[ELF::EI_ABIVERSION]); W.printBinary("Unused", makeArrayRef(Header->e_ident).slice(ELF::EI_PAD)); @@ -606,46 +618,44 @@ void ELFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionIndex = -1; - for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; ++SecI) { + for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) { ++SectionIndex; - const Elf_Shdr *Section = &*SecI; - StringRef Name = errorOrDefault(Obj->getSectionName(Section)); + StringRef Name = errorOrDefault(Obj->getSectionName(&Sec)); DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); - W.printNumber("Name", Name, Section->sh_name); + W.printNumber("Name", Name, Sec.sh_name); W.printHex("Type", - getElfSectionType(Obj->getHeader()->e_machine, Section->sh_type), - Section->sh_type); - W.printFlags ("Flags", Section->sh_flags, makeArrayRef(ElfSectionFlags)); - W.printHex ("Address", Section->sh_addr); - W.printHex ("Offset", Section->sh_offset); - W.printNumber("Size", Section->sh_size); - W.printNumber("Link", Section->sh_link); - W.printNumber("Info", Section->sh_info); - W.printNumber("AddressAlignment", Section->sh_addralign); - W.printNumber("EntrySize", Section->sh_entsize); + getElfSectionType(Obj->getHeader()->e_machine, Sec.sh_type), + Sec.sh_type); + W.printFlags("Flags", Sec.sh_flags, makeArrayRef(ElfSectionFlags)); + W.printHex("Address", Sec.sh_addr); + W.printHex("Offset", Sec.sh_offset); + W.printNumber("Size", Sec.sh_size); + W.printNumber("Link", Sec.sh_link); + W.printNumber("Info", Sec.sh_info); + W.printNumber("AddressAlignment", Sec.sh_addralign); + W.printNumber("EntrySize", Sec.sh_entsize); if (opts::SectionRelocations) { ListScope D(W, "Relocations"); - printRelocations(Section); + printRelocations(&Sec); } if (opts::SectionSymbols) { ListScope D(W, "Symbols"); - for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), - SymE = Obj->end_symbols(); - SymI != SymE; ++SymI) { - if (Obj->getSection(&*SymI) == Section) - printSymbol(SymI); + for (const typename ELFO::Elf_Sym &Sym : Obj->symbols()) { + ErrorOr SymSec = Obj->getSection(&Sym); + if (!SymSec) + continue; + if (*SymSec == &Sec) + printSymbol(&Sym, false); } } - if (opts::SectionData && Section->sh_type != ELF::SHT_NOBITS) { - ArrayRef Data = errorOrDefault(Obj->getSectionContents(Section)); + if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { + ArrayRef Data = errorOrDefault(Obj->getSectionContents(&Sec)); W.printBinaryBlock("SectionData", StringRef((const char *)Data.data(), Data.size())); } @@ -657,32 +667,63 @@ void ELFDumper::printRelocations() { ListScope D(W, "Relocations"); int SectionNumber = -1; - for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; ++SecI) { + for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) { ++SectionNumber; - if (SecI->sh_type != ELF::SHT_REL && SecI->sh_type != ELF::SHT_RELA) + if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) continue; - StringRef Name = errorOrDefault(Obj->getSectionName(&*SecI)); + StringRef Name = errorOrDefault(Obj->getSectionName(&Sec)); W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; W.indent(); - printRelocations(&*SecI); + printRelocations(&Sec); W.unindent(); W.startLine() << "}\n"; } } +template +void ELFDumper::printDynamicRelocations() { + W.startLine() << "Dynamic Relocations {\n"; + W.indent(); + for (typename ELFO::Elf_Rela_Iter RelI = Obj->dyn_rela_begin(), + RelE = Obj->dyn_rela_end(); + RelI != RelE; ++RelI) { + SmallString<32> RelocName; + Obj->getRelocationTypeName(RelI->getType(Obj->isMips64EL()), RelocName); + StringRef SymbolName; + uint32_t SymIndex = RelI->getSymbol(Obj->isMips64EL()); + const typename ELFO::Elf_Sym *Sym = Obj->dynamic_symbol_begin() + SymIndex; + SymbolName = errorOrDefault(Obj->getSymbolName(Sym, true)); + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", RelI->r_offset); + W.printNumber("Type", RelocName, (int)RelI->getType(Obj->isMips64EL())); + W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printHex("Addend", RelI->r_addend); + } + else { + raw_ostream& OS = W.startLine(); + OS << W.hex(RelI->r_offset) + << " " << RelocName + << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << W.hex(RelI->r_addend) + << "\n"; + } + } + W.unindent(); + W.startLine() << "}\n"; +} + template void ELFDumper::printRelocations(const Elf_Shdr *Sec) { switch (Sec->sh_type) { case ELF::SHT_REL: - for (typename ELFO::Elf_Rel_Iter RI = Obj->begin_rel(Sec), - RE = Obj->end_rel(Sec); + for (typename ELFO::Elf_Rel_Iter RI = Obj->rel_begin(Sec), + RE = Obj->rel_end(Sec); RI != RE; ++RI) { typename ELFO::Elf_Rela Rela; Rela.r_offset = RI->r_offset; @@ -692,8 +733,8 @@ void ELFDumper::printRelocations(const Elf_Shdr *Sec) { } break; case ELF::SHT_RELA: - for (typename ELFO::Elf_Rela_Iter RI = Obj->begin_rela(Sec), - RE = Obj->end_rela(Sec); + for (typename ELFO::Elf_Rela_Iter RI = Obj->rela_begin(Sec), + RE = Obj->rela_end(Sec); RI != RE; ++RI) { printRelocation(Sec, *RI); } @@ -710,12 +751,18 @@ void ELFDumper::printRelocation(const Elf_Shdr *Sec, std::pair Sym = Obj->getRelocationSymbol(Sec, &Rel); if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { - const Elf_Shdr *Sec = Obj->getSection(Sym.second); - ErrorOr SecName = Obj->getSectionName(Sec); + ErrorOr Sec = Obj->getSection(Sym.second); + error(Sec.getError()); + ErrorOr SecName = Obj->getSectionName(*Sec); if (SecName) TargetName = SecName.get(); } else if (Sym.first) { - TargetName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); + const Elf_Shdr *SymTable = Sym.first; + ErrorOr StrTableSec = Obj->getSection(SymTable->sh_link); + error(StrTableSec.getError()); + ErrorOr StrTableOrErr = Obj->getStringTable(*StrTableSec); + error(StrTableOrErr.getError()); + TargetName = errorOrDefault(Sym.second->getName(*StrTableOrErr)); } if (opts::ExpandRelocs) { @@ -736,30 +783,25 @@ void ELFDumper::printRelocation(const Elf_Shdr *Sec, template void ELFDumper::printSymbols() { ListScope Group(W, "Symbols"); - for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), - SymE = Obj->end_symbols(); - SymI != SymE; ++SymI) { - printSymbol(SymI); - } + for (const typename ELFO::Elf_Sym &Sym : Obj->symbols()) + printSymbol(&Sym, false); } template void ELFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); - for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_dynamic_symbols(), - SymE = Obj->end_dynamic_symbols(); - SymI != SymE; ++SymI) { - printSymbol(SymI); - } + for (const typename ELFO::Elf_Sym &Sym : Obj->dynamic_symbols()) + printSymbol(&Sym, true); } template -void ELFDumper::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) { +void ELFDumper::printSymbol(const typename ELFO::Elf_Sym *Symbol, + bool IsDynamic) { unsigned SectionIndex = 0; StringRef SectionName; getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex); - std::string FullSymbolName = getFullSymbolName(*Obj, Symbol); + std::string FullSymbolName = getFullSymbolName(*Obj, Symbol, IsDynamic); DictScope D(W, "Symbol"); W.printNumber("Name", FullSymbolName, Symbol->st_name); @@ -987,6 +1029,9 @@ static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, case DT_FLAGS_1: printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); break; + default: + OS << format("0x%" PRIX64, Value); + break; } } @@ -1056,9 +1101,9 @@ template void ELFDumper::printProgramHeaders() { ListScope L(W, "ProgramHeaders"); - for (typename ELFO::Elf_Phdr_Iter PI = Obj->begin_program_headers(), - PE = Obj->end_program_headers(); - PI != PE; ++PI) { + for (typename ELFO::Elf_Phdr_Iter PI = Obj->program_header_begin(), + PE = Obj->program_header_end(); + PI != PE; ++PI) { DictScope P(W, "ProgramHeader"); W.printHex ("Type", getElfSegmentType(Obj->getHeader()->e_machine, PI->p_type), @@ -1073,6 +1118,18 @@ void ELFDumper::printProgramHeaders() { } } +template +void ELFDumper::printHashTable() { + DictScope D(W, "HashTable"); + auto HT = Obj->getHashTable(); + if (!HT) + return; + W.printNumber("Num Buckets", HT->nbucket); + W.printNumber("Num Chains", HT->nchain); + W.printList("Buckets", HT->buckets()); + W.printList("Chains", HT->chains()); +} + template void ELFDumper::printAttributes() { W.startLine() << "Attributes not implemented.\n"; @@ -1086,12 +1143,11 @@ template <> void ELFDumper>::printAttributes() { } DictScope BA(W, "BuildAttributes"); - for (ELFO::Elf_Shdr_Iter SI = Obj->begin_sections(), SE = Obj->end_sections(); - SI != SE; ++SI) { - if (SI->sh_type != ELF::SHT_ARM_ATTRIBUTES) + for (const ELFO::Elf_Shdr &Sec : Obj->sections()) { + if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) continue; - ErrorOr > Contents = Obj->getSectionContents(&(*SI)); + ErrorOr> Contents = Obj->getSectionContents(&Sec); if (!Contents) continue; @@ -1115,87 +1171,132 @@ template class MipsGOTParser { public: typedef object::ELFFile ObjectFile; 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_Sym_Iter Elf_Sym_Iter; typedef typename ObjectFile::Elf_Addr GOTEntry; typedef typename ObjectFile::template ELFEntityIterator GOTIter; 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, - Elf_Sym_Iter Sym); + 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; } - Elf_Sym_Iter DynSymBegin = Obj->begin_dynamic_symbols(); - Elf_Sym_Iter DynSymEnd = Obj->end_dynamic_symbols(); + const Elf_Sym *DynSymBegin = Obj->dynamic_symbol_begin(); + 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)")); } } @@ -1203,24 +1304,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); - Elf_Sym_Iter 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++); + 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); @@ -1233,36 +1398,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) { @@ -1274,7 +1409,8 @@ void MipsGOTParser::printGotEntry(uint64_t GotAddr, GOTIter BeginIt, template void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, - GOTIter It, Elf_Sym_Iter Sym) { + GOTIter It, const Elf_Sym *Sym, + bool IsDynamic) { printGotEntry(GotAddr, BeginIt, It); W.printHex("Value", Sym->st_value); @@ -1285,36 +1421,48 @@ void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex); W.printHex("Section", SectionName, SectionIndex); - std::string FullSymbolName = getFullSymbolName(*Obj, Sym); + std::string FullSymbolName = getFullSymbolName(*Obj, Sym, IsDynamic); 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[] = { @@ -1452,3 +1600,25 @@ template void ELFDumper::printMipsReginfo() { W.printHex("Co-Proc Mask2", Reginfo->ri_cprmask[2]); W.printHex("Co-Proc Mask3", Reginfo->ri_cprmask[3]); } + +template void ELFDumper::printStackMap() const { + const typename ELFFile::Elf_Shdr *StackMapSection = nullptr; + for (const auto &Sec : Obj->sections()) { + ErrorOr Name = Obj->getSectionName(&Sec); + if (*Name == ".llvm_stackmaps") { + StackMapSection = &Sec; + break; + } + } + + if (!StackMapSection) + return; + + StringRef StackMapContents; + ErrorOr> StackMapContentsArray = + Obj->getSectionContents(StackMapSection); + + prettyPrintStackMap( + llvm::outs(), + StackMapV1Parser(*StackMapContentsArray)); +}