X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=tools%2Fllvm-readobj%2FELFDumper.cpp;h=5b4a78cf52fa7e36be290c6cd0d5522ec3f2e709;hp=bf5fad2800d02d195ffc71cecad3564fa146cf3a;hb=600b09339deb5673aa2ade6b604dd7ba57f4e283;hpb=9ea117379c362ba32b51fbc03bd9b780ff079cbb diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index bf5fad2800d..5b4a78cf52f 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -42,8 +42,7 @@ namespace { template class ELFDumper : public ObjDumper { public: - ELFDumper(const ELFFile *Obj, StreamWriter &Writer) - : ObjDumper(Writer), Obj(Obj) {} + ELFDumper(const ELFFile *Obj, StreamWriter &Writer); void printFileHeaders() override; void printSections() override; @@ -57,6 +56,7 @@ public: void printNeededLibraries() override; void printProgramHeaders() override; void printHashTable() override; + void printGnuHashTable() override; void printLoadName() override; void printAttributes() override; @@ -70,13 +70,112 @@ private: typedef ELFFile ELFO; typedef typename ELFO::Elf_Shdr Elf_Shdr; typedef typename ELFO::Elf_Sym Elf_Sym; - - void printSymbol(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic); + typedef typename ELFO::Elf_Dyn Elf_Dyn; + typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; + typedef typename ELFO::Elf_Rel Elf_Rel; + typedef typename ELFO::Elf_Rela Elf_Rela; + typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; + typedef typename ELFO::Elf_Phdr Elf_Phdr; + typedef typename ELFO::Elf_Hash Elf_Hash; + typedef typename ELFO::Elf_GnuHash Elf_GnuHash; + typedef typename ELFO::Elf_Ehdr Elf_Ehdr; + typedef typename ELFO::Elf_Word Elf_Word; + typedef typename ELFO::uintX_t uintX_t; + typedef typename ELFO::Elf_Versym Elf_Versym; + typedef typename ELFO::Elf_Verneed Elf_Verneed; + typedef typename ELFO::Elf_Vernaux Elf_Vernaux; + typedef typename ELFO::Elf_Verdef Elf_Verdef; + + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; + + void printSymbolsHelper(bool IsDynamic); + void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, + StringRef StrTable, bool IsDynamic); void printRelocations(const Elf_Shdr *Sec); - void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel); + void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab); + void printValue(uint64_t Type, uint64_t Value); + + const Elf_Rela *dyn_rela_begin() const; + const Elf_Rela *dyn_rela_end() const; + Elf_Rela_Range dyn_relas() const; + StringRef getDynamicString(uint64_t Offset) const; + const Elf_Dyn *dynamic_table_begin() const { + ErrorOr Ret = Obj->dynamic_table_begin(DynamicProgHeader); + error(Ret.getError()); + return *Ret; + } + const Elf_Dyn *dynamic_table_end() const { + ErrorOr Ret = Obj->dynamic_table_end(DynamicProgHeader); + error(Ret.getError()); + return *Ret; + } + Elf_Dyn_Range dynamic_table() const { + ErrorOr Ret = Obj->dynamic_table(DynamicProgHeader); + error(Ret.getError()); + return *Ret; + } + + StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, + bool &IsDefault); + void LoadVersionMap(); + void LoadVersionNeeds(const Elf_Shdr *ec) const; + void LoadVersionDefs(const Elf_Shdr *sec) const; const ELFO *Obj; + DynRegionInfo DynRelaRegion; + const Elf_Phdr *DynamicProgHeader = nullptr; + StringRef DynamicStringTable; + const Elf_Sym *DynSymStart = nullptr; + StringRef SOName; + const Elf_Hash *HashTable = nullptr; + const Elf_GnuHash *GnuHashTable = nullptr; + const Elf_Shdr *DotDynSymSec = nullptr; + const Elf_Shdr *DotSymtabSec = nullptr; + ArrayRef ShndxTable; + + const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version + const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r + const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d + + // Records for each version index the corresponding Verdef or Vernaux entry. + // This is filled the first time LoadVersionMap() is called. + class VersionMapEntry : public PointerIntPair { + public: + // If the integer is 0, this is an Elf_Verdef*. + // If the integer is 1, this is an Elf_Vernaux*. + VersionMapEntry() : PointerIntPair(nullptr, 0) {} + VersionMapEntry(const Elf_Verdef *verdef) + : PointerIntPair(verdef, 0) {} + VersionMapEntry(const Elf_Vernaux *vernaux) + : PointerIntPair(vernaux, 1) {} + bool isNull() const { return getPointer() == nullptr; } + bool isVerdef() const { return !isNull() && getInt() == 0; } + bool isVernaux() const { return !isNull() && getInt() == 1; } + const Elf_Verdef *getVerdef() const { + return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr; + } + const Elf_Vernaux *getVernaux() const { + return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr; + } + }; + mutable SmallVector VersionMap; + +public: + std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, + bool IsDynamic); + const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } + const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } + ArrayRef getShndxTable() { return ShndxTable; } }; template T errorOrDefault(ErrorOr Val, T Default = T()) { @@ -123,10 +222,145 @@ std::error_code createELFDumper(const object::ObjectFile *Obj, } // namespace llvm -template -static std::string getFullSymbolName(const ELFO &Obj, - const typename ELFO::Elf_Sym *Symbol, - StringRef StrTable, bool IsDynamic) { +// Iterate through the versions needed section, and place each Elf_Vernaux +// in the VersionMap according to its index. +template +void ELFDumper::LoadVersionNeeds(const Elf_Shdr *sec) const { + unsigned vn_size = sec->sh_size; // Size of section in bytes + unsigned vn_count = sec->sh_info; // Number of Verneed entries + const char *sec_start = (const char *)Obj->base() + sec->sh_offset; + const char *sec_end = sec_start + vn_size; + // The first Verneed entry is at the start of the section. + const char *p = sec_start; + for (unsigned i = 0; i < vn_count; i++) { + if (p + sizeof(Elf_Verneed) > sec_end) + report_fatal_error("Section ended unexpectedly while scanning " + "version needed records."); + const Elf_Verneed *vn = reinterpret_cast(p); + if (vn->vn_version != ELF::VER_NEED_CURRENT) + report_fatal_error("Unexpected verneed version"); + // Iterate through the Vernaux entries + const char *paux = p + vn->vn_aux; + for (unsigned j = 0; j < vn->vn_cnt; j++) { + if (paux + sizeof(Elf_Vernaux) > sec_end) + report_fatal_error("Section ended unexpected while scanning auxiliary " + "version needed records."); + const Elf_Vernaux *vna = reinterpret_cast(paux); + size_t index = vna->vna_other & ELF::VERSYM_VERSION; + if (index >= VersionMap.size()) + VersionMap.resize(index + 1); + VersionMap[index] = VersionMapEntry(vna); + paux += vna->vna_next; + } + p += vn->vn_next; + } +} + +// Iterate through the version definitions, and place each Elf_Verdef +// in the VersionMap according to its index. +template +void ELFDumper::LoadVersionDefs(const Elf_Shdr *sec) const { + unsigned vd_size = sec->sh_size; // Size of section in bytes + unsigned vd_count = sec->sh_info; // Number of Verdef entries + const char *sec_start = (const char *)Obj->base() + sec->sh_offset; + const char *sec_end = sec_start + vd_size; + // The first Verdef entry is at the start of the section. + const char *p = sec_start; + for (unsigned i = 0; i < vd_count; i++) { + if (p + sizeof(Elf_Verdef) > sec_end) + report_fatal_error("Section ended unexpectedly while scanning " + "version definitions."); + const Elf_Verdef *vd = reinterpret_cast(p); + if (vd->vd_version != ELF::VER_DEF_CURRENT) + report_fatal_error("Unexpected verdef version"); + size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; + if (index >= VersionMap.size()) + VersionMap.resize(index + 1); + VersionMap[index] = VersionMapEntry(vd); + p += vd->vd_next; + } +} + +template void ELFDumper::LoadVersionMap() { + // If there is no dynamic symtab or version table, there is nothing to do. + if (!DynSymStart || !dot_gnu_version_sec) + return; + + // Has the VersionMap already been loaded? + if (VersionMap.size() > 0) + return; + + // The first two version indexes are reserved. + // Index 0 is LOCAL, index 1 is GLOBAL. + VersionMap.push_back(VersionMapEntry()); + VersionMap.push_back(VersionMapEntry()); + + if (dot_gnu_version_d_sec) + LoadVersionDefs(dot_gnu_version_d_sec); + + if (dot_gnu_version_r_sec) + LoadVersionNeeds(dot_gnu_version_r_sec); +} + +template +StringRef ELFDumper::getSymbolVersion(StringRef StrTab, + const Elf_Sym *symb, + bool &IsDefault) { + // This is a dynamic symbol. Look in the GNU symbol version table. + if (!dot_gnu_version_sec) { + // No version table. + IsDefault = false; + return StringRef(""); + } + + // Determine the position in the symbol table of this entry. + size_t entry_index = (reinterpret_cast(symb) - + reinterpret_cast(DynSymStart)) / + sizeof(Elf_Sym); + + // Get the corresponding version index entry + const Elf_Versym *vs = + Obj->template getEntry(dot_gnu_version_sec, entry_index); + size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; + + // Special markers for unversioned symbols. + if (version_index == ELF::VER_NDX_LOCAL || + version_index == ELF::VER_NDX_GLOBAL) { + IsDefault = false; + return StringRef(""); + } + + // Lookup this symbol in the version table + LoadVersionMap(); + if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) + reportError("Invalid version entry"); + const VersionMapEntry &entry = VersionMap[version_index]; + + // Get the version name string + size_t name_offset; + if (entry.isVerdef()) { + // The first Verdaux entry holds the name. + name_offset = entry.getVerdef()->getAux()->vda_name; + } else { + name_offset = entry.getVernaux()->vna_name; + } + + // Set IsDefault + if (entry.isVerdef()) { + IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); + } else { + IsDefault = false; + } + + if (name_offset >= StrTab.size()) + reportError("Invalid string offset"); + return StringRef(StrTab.data() + name_offset); +} + +template +std::string ELFDumper::getFullSymbolName(const Elf_Sym *Symbol, + StringRef StrTable, + bool IsDynamic) { StringRef SymbolName = errorOrDefault(Symbol->getName(StrTable)); if (!IsDynamic) return SymbolName; @@ -134,19 +368,17 @@ static std::string getFullSymbolName(const ELFO &Obj, std::string FullSymbolName(SymbolName); bool IsDefault; - ErrorOr Version = - Obj.getSymbolVersion(nullptr, &*Symbol, IsDefault); - if (Version) { - FullSymbolName += (IsDefault ? "@@" : "@"); - FullSymbolName += *Version; - } else - error(Version.getError()); + StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault); + FullSymbolName += (IsDefault ? "@@" : "@"); + FullSymbolName += Version; return FullSymbolName; } template static void getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, + const typename ELFO::Elf_Shdr *SymTab, + ArrayRef ShndxTable, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; if (Symbol->isUndefined()) @@ -163,25 +395,26 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, SectionName = "Reserved"; else { if (SectionIndex == SHN_XINDEX) - SectionIndex = Obj.getExtendedSymbolTableIndex(&*Symbol); + SectionIndex = + Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable); ErrorOr Sec = Obj.getSection(SectionIndex); error(Sec.getError()); SectionName = errorOrDefault(Obj.getSectionName(*Sec)); } } -template -static const typename ELFFile::Elf_Shdr * -findSectionByAddress(const ELFFile *Obj, uint64_t Addr) { +template +static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj, + uint64_t Addr) { for (const auto &Shdr : Obj->sections()) if (Shdr.sh_addr == Addr) return &Shdr; return nullptr; } -template -static const typename ELFFile::Elf_Shdr * -findSectionByName(const ELFFile &Obj, StringRef Name) { +template +static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, + StringRef Name) { for (const auto &Shdr : Obj.sections()) { if (Name == errorOrDefault(Obj.getSectionName(&Shdr))) return &Shdr; @@ -410,6 +643,12 @@ static const EnumEntry ElfSymbolTypes[] = { { "GNU_IFunc", ELF::STT_GNU_IFUNC } }; +static const EnumEntry AMDGPUSymbolTypes[] = { + { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }, + { "AMDGPU_HSA_INDIRECT_FUNCTION", ELF::STT_AMDGPU_HSA_INDIRECT_FUNCTION }, + { "AMDGPU_HSA_METADATA", ELF::STT_AMDGPU_HSA_METADATA } +}; + static const char *getElfSectionType(unsigned Arch, unsigned Type) { switch (Arch) { case ELF::EM_ARM: @@ -474,13 +713,24 @@ static const EnumEntry ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_TLS ), LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION), LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ) + LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ), + LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_GLOBAL), + LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_READONLY), + LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_CODE), + LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT) }; static const char *getElfSegmentType(unsigned Arch, unsigned Type) { // Check potentially overlapped processor-specific // program header type. switch (Arch) { + case ELF::EM_AMDGPU: + switch (Type) { + LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM); + LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT); + LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT); + LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT); + } case ELF::EM_ARM: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); @@ -566,9 +816,138 @@ static const EnumEntry ElfHeaderMipsFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6) }; +template +ELFDumper::ELFDumper(const ELFFile *Obj, StreamWriter &Writer) + : ObjDumper(Writer), Obj(Obj) { + + SmallVector LoadSegments; + for (const Elf_Phdr &Phdr : Obj->program_headers()) { + if (Phdr.p_type == ELF::PT_DYNAMIC) { + DynamicProgHeader = &Phdr; + continue; + } + if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) + continue; + LoadSegments.push_back(&Phdr); + } + + auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { + const Elf_Phdr **I = std::upper_bound( + LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr); + if (I == LoadSegments.begin()) + report_fatal_error("Virtual address is not in any segment"); + --I; + const Elf_Phdr &Phdr = **I; + uint64_t Delta = VAddr - Phdr.p_vaddr; + if (Delta >= Phdr.p_filesz) + report_fatal_error("Virtual address is not in any segment"); + return Obj->base() + Phdr.p_offset + Delta; + }; + + uint64_t SONameOffset = 0; + const char *StringTableBegin = nullptr; + uint64_t StringTableSize = 0; + for (const Elf_Dyn &Dyn : dynamic_table()) { + switch (Dyn.d_tag) { + case ELF::DT_HASH: + HashTable = + reinterpret_cast(toMappedAddr(Dyn.getPtr())); + break; + case ELF::DT_GNU_HASH: + GnuHashTable = + reinterpret_cast(toMappedAddr(Dyn.getPtr())); + break; + case ELF::DT_RELA: + DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); + break; + case ELF::DT_RELASZ: + DynRelaRegion.Size = Dyn.getVal(); + break; + case ELF::DT_RELAENT: + DynRelaRegion.EntSize = Dyn.getVal(); + break; + case ELF::DT_SONAME: + SONameOffset = Dyn.getVal(); + break; + case ELF::DT_STRTAB: + StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr()); + break; + case ELF::DT_STRSZ: + StringTableSize = Dyn.getVal(); + break; + case ELF::DT_SYMTAB: + DynSymStart = + reinterpret_cast(toMappedAddr(Dyn.getPtr())); + break; + } + } + if (StringTableBegin) + DynamicStringTable = StringRef(StringTableBegin, StringTableSize); + if (SONameOffset) + SOName = getDynamicString(SONameOffset); + + for (const Elf_Shdr &Sec : Obj->sections()) { + switch (Sec.sh_type) { + case ELF::SHT_GNU_versym: + if (dot_gnu_version_sec != nullptr) + reportError("Multiple SHT_GNU_versym"); + dot_gnu_version_sec = &Sec; + break; + case ELF::SHT_GNU_verdef: + if (dot_gnu_version_d_sec != nullptr) + reportError("Multiple SHT_GNU_verdef"); + dot_gnu_version_d_sec = &Sec; + break; + case ELF::SHT_GNU_verneed: + if (dot_gnu_version_r_sec != nullptr) + reportError("Multilpe SHT_GNU_verneed"); + dot_gnu_version_r_sec = &Sec; + break; + case ELF::SHT_DYNSYM: + if (DotDynSymSec != nullptr) + reportError("Multilpe SHT_DYNSYM"); + DotDynSymSec = &Sec; + break; + case ELF::SHT_SYMTAB: + if (DotSymtabSec != nullptr) + reportError("Multilpe SHT_SYMTAB"); + DotSymtabSec = &Sec; + break; + case ELF::SHT_SYMTAB_SHNDX: { + ErrorOr> TableOrErr = Obj->getSHNDXTable(Sec); + error(TableOrErr.getError()); + ShndxTable = *TableOrErr; + break; + } + } + } +} + +template +const typename ELFDumper::Elf_Rela * +ELFDumper::dyn_rela_begin() const { + if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela)) + report_fatal_error("Invalid relocation entry size"); + return reinterpret_cast(DynRelaRegion.Addr); +} + +template +const typename ELFDumper::Elf_Rela * +ELFDumper::dyn_rela_end() const { + uint64_t Size = DynRelaRegion.Size; + if (Size % sizeof(Elf_Rela)) + report_fatal_error("Invalid relocation table size"); + return dyn_rela_begin() + Size / sizeof(Elf_Rela); +} + +template +typename ELFDumper::Elf_Rela_Range ELFDumper::dyn_relas() const { + return make_range(dyn_rela_begin(), dyn_rela_end()); +} + template void ELFDumper::printFileHeaders() { - const typename ELFO::Elf_Ehdr *Header = Obj->getHeader(); + const Elf_Ehdr *Header = Obj->getHeader(); { DictScope D(W, "ElfHeader"); @@ -619,7 +998,7 @@ void ELFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionIndex = -1; - for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : Obj->sections()) { ++SectionIndex; StringRef Name = errorOrDefault(Obj->getSectionName(&Sec)); @@ -646,17 +1025,18 @@ void ELFDumper::printSections() { if (opts::SectionSymbols) { ListScope D(W, "Symbols"); - const Elf_Shdr *Symtab = Obj->getDotSymtabSec(); + const Elf_Shdr *Symtab = DotSymtabSec; ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); error(StrTableOrErr.getError()); StringRef StrTable = *StrTableOrErr; - for (const typename ELFO::Elf_Sym &Sym : Obj->symbols()) { - ErrorOr SymSec = Obj->getSection(&Sym); + for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { + ErrorOr SymSec = + Obj->getSection(&Sym, Symtab, ShndxTable); if (!SymSec) continue; if (*SymSec == &Sec) - printSymbol(&Sym, StrTable, false); + printSymbol(&Sym, Symtab, StrTable, false); } } @@ -673,7 +1053,7 @@ void ELFDumper::printRelocations() { ListScope D(W, "Relocations"); int SectionNumber = -1; - for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : Obj->sections()) { ++SectionNumber; if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) @@ -695,13 +1075,13 @@ template void ELFDumper::printDynamicRelocations() { W.startLine() << "Dynamic Relocations {\n"; W.indent(); - for (const typename ELFO::Elf_Rela &Rel : Obj->dyn_relas()) { + for (const Elf_Rela &Rel : dyn_relas()) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef SymbolName; uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); - const typename ELFO::Elf_Sym *Sym = Obj->dynamic_symbol_begin() + SymIndex; - SymbolName = errorOrDefault(Obj->getSymbolName(Sym, true)); + const Elf_Sym *Sym = DynSymStart + SymIndex; + SymbolName = errorOrDefault(Sym->getName(DynamicStringTable)); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); @@ -722,42 +1102,43 @@ void ELFDumper::printDynamicRelocations() { template void ELFDumper::printRelocations(const Elf_Shdr *Sec) { + ErrorOr SymTabOrErr = Obj->getSection(Sec->sh_link); + error(SymTabOrErr.getError()); + const Elf_Shdr *SymTab = *SymTabOrErr; + switch (Sec->sh_type) { case ELF::SHT_REL: - for (const typename ELFO::Elf_Rel &R : Obj->rels(Sec)) { - typename ELFO::Elf_Rela Rela; + for (const Elf_Rel &R : Obj->rels(Sec)) { + Elf_Rela Rela; Rela.r_offset = R.r_offset; Rela.r_info = R.r_info; Rela.r_addend = 0; - printRelocation(Sec, Rela); + printRelocation(Rela, SymTab); } break; case ELF::SHT_RELA: - for (const typename ELFO::Elf_Rela &R : Obj->relas(Sec)) - printRelocation(Sec, R); + for (const Elf_Rela &R : Obj->relas(Sec)) + printRelocation(R, SymTab); break; } } template -void ELFDumper::printRelocation(const Elf_Shdr *Sec, - typename ELFO::Elf_Rela Rel) { +void ELFDumper::printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef TargetName; - std::pair Sym = - Obj->getRelocationSymbol(Sec, &Rel); - if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { - ErrorOr Sec = Obj->getSection(Sym.second); + const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab); + if (Sym && Sym->getType() == ELF::STT_SECTION) { + ErrorOr Sec = Obj->getSection(Sym, SymTab, ShndxTable); error(Sec.getError()); ErrorOr SecName = Obj->getSectionName(*Sec); if (SecName) TargetName = SecName.get(); - } else if (Sym.first) { - const Elf_Shdr *SymTable = Sym.first; - ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(*SymTable); + } else if (Sym) { + ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(*SymTab); error(StrTableOrErr.getError()); - TargetName = errorOrDefault(Sym.second->getName(*StrTableOrErr)); + TargetName = errorOrDefault(Sym->getName(*StrTableOrErr)); } if (opts::ExpandRelocs) { @@ -776,37 +1157,38 @@ void ELFDumper::printRelocation(const Elf_Shdr *Sec, } template -void ELFDumper::printSymbols() { - ListScope Group(W, "Symbols"); - - const Elf_Shdr *Symtab = Obj->getDotSymtabSec(); +void ELFDumper::printSymbolsHelper(bool IsDynamic) { + const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec; + if (!Symtab) + return; ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); error(StrTableOrErr.getError()); StringRef StrTable = *StrTableOrErr; - for (const typename ELFO::Elf_Sym &Sym : Obj->symbols()) - printSymbol(&Sym, StrTable, false); + for (const Elf_Sym &Sym : Obj->symbols(Symtab)) + printSymbol(&Sym, Symtab, StrTable, IsDynamic); +} + +template +void ELFDumper::printSymbols() { + ListScope Group(W, "Symbols"); + printSymbolsHelper(false); } template void ELFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); - - const Elf_Shdr *Symtab = Obj->getDotDynSymSec(); - ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(*Symtab); - error(StrTableOrErr.getError()); - StringRef StrTable = *StrTableOrErr; - for (const typename ELFO::Elf_Sym &Sym : Obj->dynamic_symbols()) - printSymbol(&Sym, StrTable, true); + printSymbolsHelper(true); } template -void ELFDumper::printSymbol(const typename ELFO::Elf_Sym *Symbol, +void ELFDumper::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab, StringRef StrTable, bool IsDynamic) { unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex); - std::string FullSymbolName = - getFullSymbolName(*Obj, Symbol, StrTable, IsDynamic); + getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName, + SectionIndex); + std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic); + unsigned char SymbolType = Symbol->getType(); DictScope D(W, "Symbol"); W.printNumber("Name", FullSymbolName, Symbol->st_name); @@ -814,7 +1196,11 @@ void ELFDumper::printSymbol(const typename ELFO::Elf_Sym *Symbol, W.printNumber("Size", Symbol->st_size); W.printEnum ("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); - W.printEnum ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes)); + if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && + SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) + W.printEnum ("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); + else + W.printEnum ("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); W.printNumber("Other", Symbol->st_other); W.printHex("Section", SectionName, SectionIndex); } @@ -858,12 +1244,15 @@ static const char *getTypeString(uint64_t Type) { LLVM_READOBJ_TYPE_CASE(SYMENT); LLVM_READOBJ_TYPE_CASE(SYMTAB); LLVM_READOBJ_TYPE_CASE(TEXTREL); + LLVM_READOBJ_TYPE_CASE(VERDEF); + LLVM_READOBJ_TYPE_CASE(VERDEFNUM); LLVM_READOBJ_TYPE_CASE(VERNEED); LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); LLVM_READOBJ_TYPE_CASE(VERSYM); LLVM_READOBJ_TYPE_CASE(RELCOUNT); LLVM_READOBJ_TYPE_CASE(GNU_HASH); LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL); LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); @@ -959,16 +1348,15 @@ void printFlags(T Value, ArrayRef> Flags, raw_ostream &OS) { } template -static const char *getDynamicString(const ELFFile &O, uint64_t Value) { - const char *Ret = O.getDynamicString(Value); - if (!Ret) +StringRef ELFDumper::getDynamicString(uint64_t Value) const { + if (Value >= DynamicStringTable.size()) reportError("Invalid dynamic string table reference"); - return Ret; + return StringRef(DynamicStringTable.data() + Value); } template -static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, - bool Is64, raw_ostream &OS) { +void ELFDumper::printValue(uint64_t Type, uint64_t Value) { + raw_ostream &OS = W.getOStream(); switch (Type) { case DT_PLTREL: if (Value == DT_REL) { @@ -992,6 +1380,7 @@ static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: case DT_DEBUG: + case DT_VERDEF: case DT_VERNEED: case DT_VERSYM: case DT_GNU_HASH: @@ -999,11 +1388,13 @@ static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, case DT_MIPS_BASE_ADDRESS: case DT_MIPS_GOTSYM: case DT_MIPS_RLD_MAP: + case DT_MIPS_RLD_MAP_REL: case DT_MIPS_PLTGOT: case DT_MIPS_OPTIONS: OS << format("0x%" PRIX64, Value); break; case DT_RELCOUNT: + case DT_VERDEFNUM: case DT_VERNEEDNUM: case DT_MIPS_RLD_VERSION: case DT_MIPS_LOCAL_GOTNO: @@ -1024,14 +1415,14 @@ static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, OS << Value << " (bytes)"; break; case DT_NEEDED: - OS << "SharedLibrary (" << getDynamicString(*O, Value) << ")"; + OS << "SharedLibrary (" << getDynamicString(Value) << ")"; break; case DT_SONAME: - OS << "LibrarySoname (" << getDynamicString(*O, Value) << ")"; + OS << "LibrarySoname (" << getDynamicString(Value) << ")"; break; case DT_RPATH: case DT_RUNPATH: - OS << getDynamicString(*O, Value); + OS << getDynamicString(Value); break; case DT_MIPS_FLAGS: printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); @@ -1057,7 +1448,8 @@ namespace { template <> void ELFDumper>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { - ARM::EHABI::PrinterContext> Ctx(W, Obj); + ARM::EHABI::PrinterContext> Ctx( + W, Obj, DotSymtabSec); return Ctx.PrintUnwindInformation(); } W.startLine() << "UnwindInfo not implemented.\n"; @@ -1066,8 +1458,8 @@ template <> void ELFDumper>::printUnwindInfo() { template void ELFDumper::printDynamicTable() { - auto I = Obj->dynamic_table_begin(); - auto E = Obj->dynamic_table_end(); + auto I = dynamic_table_begin(); + auto E = dynamic_table_end(); if (I == E) return; @@ -1092,13 +1484,12 @@ void ELFDumper::printDynamicTable() { << " Tag" << (Is64 ? " " : " ") << "Type" << " " << "Name/Value\n"; while (I != E) { - const typename ELFO::Elf_Dyn &Entry = *I; + const Elf_Dyn &Entry = *I; + uintX_t Tag = Entry.getTag(); ++I; - W.startLine() - << " " - << format(Is64 ? "0x%016" PRIX64 : "0x%08" PRIX64, Entry.getTag()) - << " " << format("%-21s", getTypeString(Entry.getTag())); - printValue(Obj, Entry.getTag(), Entry.getVal(), Is64, OS); + W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, true) << " " + << format("%-21s", getTypeString(Tag)); + printValue(Tag, Entry.getVal()); OS << "\n"; } @@ -1112,14 +1503,14 @@ void ELFDumper::printNeededLibraries() { typedef std::vector LibsTy; LibsTy Libs; - for (const auto &Entry : Obj->dynamic_table()) + for (const auto &Entry : dynamic_table()) if (Entry.d_tag == ELF::DT_NEEDED) - Libs.push_back(getDynamicString(*Obj, Entry.d_un.d_val)); + Libs.push_back(getDynamicString(Entry.d_un.d_val)); std::stable_sort(Libs.begin(), Libs.end()); - for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); I != E; ++I) { - outs() << " " << *I << "\n"; + for (const auto &L : Libs) { + outs() << " " << L << "\n"; } } @@ -1127,7 +1518,7 @@ template void ELFDumper::printProgramHeaders() { ListScope L(W, "ProgramHeaders"); - for (const typename ELFO::Elf_Phdr &Phdr : Obj->program_headers()) { + for (const Elf_Phdr &Phdr : Obj->program_headers()) { DictScope P(W, "ProgramHeader"); W.printHex("Type", getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), @@ -1145,17 +1536,33 @@ void ELFDumper::printProgramHeaders() { template void ELFDumper::printHashTable() { DictScope D(W, "HashTable"); - auto HT = Obj->getHashTable(); - if (!HT) + if (!HashTable) return; - W.printNumber("Num Buckets", HT->nbucket); - W.printNumber("Num Chains", HT->nchain); - W.printList("Buckets", HT->buckets()); - W.printList("Chains", HT->chains()); + W.printNumber("Num Buckets", HashTable->nbucket); + W.printNumber("Num Chains", HashTable->nchain); + W.printList("Buckets", HashTable->buckets()); + W.printList("Chains", HashTable->chains()); +} + +template +void ELFDumper::printGnuHashTable() { + DictScope D(W, "GnuHashTable"); + if (!GnuHashTable) + return; + W.printNumber("Num Buckets", GnuHashTable->nbuckets); + W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx); + W.printNumber("Num Mask Words", GnuHashTable->maskwords); + W.printNumber("Shift Count", GnuHashTable->shift2); + W.printHexList("Bloom Filter", GnuHashTable->filter()); + W.printList("Buckets", GnuHashTable->buckets()); + if (!DotDynSymSec) + reportError("No dynamic symbol section"); + W.printHexList("Values", + GnuHashTable->values(DotDynSymSec->getEntityCount())); } template void ELFDumper::printLoadName() { - outs() << "LoadName: " << Obj->getLoadName() << '\n'; + outs() << "LoadName: " << SOName << '\n'; } template @@ -1197,21 +1604,23 @@ template <> void ELFDumper>::printAttributes() { namespace { template class MipsGOTParser { public: - typedef object::ELFFile ObjectFile; - typedef typename ObjectFile::Elf_Shdr Elf_Shdr; - typedef typename ObjectFile::Elf_Sym Elf_Sym; + typedef object::ELFFile ELFO; + typedef typename ELFO::Elf_Shdr Elf_Shdr; + typedef typename ELFO::Elf_Sym Elf_Sym; + typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; + typedef typename ELFO::Elf_Addr GOTEntry; + typedef typename ELFO::Elf_Rel Elf_Rel; + typedef typename ELFO::Elf_Rela Elf_Rela; - MipsGOTParser(const ObjectFile *Obj, StreamWriter &W); + MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, + Elf_Dyn_Range DynTable, StreamWriter &W); void parseGOT(); void parsePLT(); private: - typedef typename ObjectFile::Elf_Addr GOTEntry; - typedef typename ObjectFile::template ELFEntityIterator - GOTIter; - - const ObjectFile *Obj; + ELFDumper *Dumper; + const ELFO *Obj; StreamWriter &W; llvm::Optional DtPltGot; llvm::Optional DtLocalGotNum; @@ -1220,23 +1629,26 @@ private: llvm::Optional DtJmpRel; std::size_t getGOTTotal(ArrayRef GOT) const; - GOTIter makeGOTIter(ArrayRef GOT, std::size_t EntryNum); - - void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It); - void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It, - const Elf_Sym *Sym, StringRef StrTable, - bool IsDynamic); - void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, - StringRef Purpose); - void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, - StringRef StrTable, const Elf_Sym *Sym); + const GOTEntry *makeGOTIter(ArrayRef GOT, std::size_t EntryNum); + + void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, + const GOTEntry *It); + void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt, + const GOTEntry *It, const Elf_Sym *Sym, + StringRef StrTable, bool IsDynamic); + void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, + const GOTEntry *It, StringRef Purpose); + void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt, + const GOTEntry *It, StringRef StrTable, + const Elf_Sym *Sym); }; } template -MipsGOTParser::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) - : Obj(Obj), W(W) { - for (const auto &Entry : Obj->dynamic_table()) { +MipsGOTParser::MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, + Elf_Dyn_Range DynTable, StreamWriter &W) + : Dumper(Dumper), Obj(Obj), W(W) { + for (const auto &Entry : DynTable) { switch (Entry.getTag()) { case ELF::DT_PLTGOT: DtPltGot = Entry.getVal(); @@ -1291,11 +1703,11 @@ template void MipsGOTParser::parseGOT() { return; } - const Elf_Shdr *DynSymSec = Obj->getDotDynSymSec(); + const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec(); ErrorOr StrTable = Obj->getStringTableForSymtab(*DynSymSec); error(StrTable.getError()); - const Elf_Sym *DynSymBegin = Obj->dynamic_symbol_begin(); - const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end(); + const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec); + const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec); std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); if (*DtGotSym > DynSymTotal) { @@ -1310,9 +1722,9 @@ template void MipsGOTParser::parseGOT() { return; } - GOTIter GotBegin = makeGOTIter(*GOT, 0); - GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); - GOTIter It = GotBegin; + const GOTEntry *GotBegin = makeGOTIter(*GOT, 0); + const GOTEntry *GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); + const GOTEntry *It = GotBegin; DictScope GS(W, "Primary GOT"); @@ -1342,7 +1754,8 @@ template void MipsGOTParser::parseGOT() { { ListScope GS(W, "Global entries"); - GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum); + const GOTEntry *GotGlobalEnd = + makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum); const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; for (; It != GotGlobalEnd; ++It) { DictScope D(W, "Entry"); @@ -1384,12 +1797,13 @@ template void MipsGOTParser::parsePLT() { ErrorOr SymTableOrErr = Obj->getSection(PLTRelShdr->sh_link); error(SymTableOrErr.getError()); - ErrorOr StrTable = Obj->getStringTableForSymtab(**SymTableOrErr); + const Elf_Shdr *SymTable = *SymTableOrErr; + ErrorOr StrTable = Obj->getStringTableForSymtab(*SymTable); error(StrTable.getError()); - GOTIter PLTBegin = makeGOTIter(*PLT, 0); - GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT)); - GOTIter It = PLTBegin; + const GOTEntry *PLTBegin = makeGOTIter(*PLT, 0); + const GOTEntry *PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT)); + const GOTEntry *It = PLTBegin; DictScope GS(W, "PLT GOT"); { @@ -1403,21 +1817,18 @@ template void MipsGOTParser::parsePLT() { switch (PLTRelShdr->sh_type) { case ELF::SHT_REL: - for (const typename ObjectFile::Elf_Rel *RI = Obj->rel_begin(PLTRelShdr), - *RE = Obj->rel_end(PLTRelShdr); + for (const Elf_Rel *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; + const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable); printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym); } break; case ELF::SHT_RELA: - for (const typename ObjectFile::Elf_Rela - *RI = Obj->rela_begin(PLTRelShdr), - *RE = Obj->rela_end(PLTRelShdr); + for (const Elf_Rela *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; + const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable); printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym); } break; @@ -1431,15 +1842,16 @@ std::size_t MipsGOTParser::getGOTTotal(ArrayRef GOT) const { } template -typename MipsGOTParser::GOTIter +const typename MipsGOTParser::GOTEntry * MipsGOTParser::makeGOTIter(ArrayRef GOT, std::size_t EntryNum) { const char *Data = reinterpret_cast(GOT.data()); - return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry)); + return reinterpret_cast(Data + EntryNum * sizeof(GOTEntry)); } template -void MipsGOTParser::printGotEntry(uint64_t GotAddr, GOTIter BeginIt, - GOTIter It) { +void MipsGOTParser::printGotEntry(uint64_t GotAddr, + const GOTEntry *BeginIt, + const GOTEntry *It) { int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); W.printHex("Address", GotAddr + Offset); W.printNumber("Access", Offset - 0x7ff0); @@ -1447,10 +1859,9 @@ void MipsGOTParser::printGotEntry(uint64_t GotAddr, GOTIter BeginIt, } template -void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, - GOTIter It, const Elf_Sym *Sym, - StringRef StrTable, - bool IsDynamic) { +void MipsGOTParser::printGlobalGotEntry( + uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It, + const Elf_Sym *Sym, StringRef StrTable, bool IsDynamic) { printGotEntry(GotAddr, BeginIt, It); W.printHex("Value", Sym->st_value); @@ -1458,17 +1869,19 @@ void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex); + getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), + Dumper->getShndxTable(), SectionName, SectionIndex); W.printHex("Section", SectionName, SectionIndex); std::string FullSymbolName = - getFullSymbolName(*Obj, Sym, StrTable, IsDynamic); + Dumper->getFullSymbolName(Sym, StrTable, IsDynamic); W.printNumber("Name", FullSymbolName, Sym->st_name); } template -void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, - GOTIter It, StringRef Purpose) { +void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, + const GOTEntry *BeginIt, + const GOTEntry *It, StringRef Purpose) { DictScope D(W, "Entry"); int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); W.printHex("Address", PLTAddr + Offset); @@ -1477,8 +1890,9 @@ void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, } template -void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, - GOTIter It, StringRef StrTable, +void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, + const GOTEntry *BeginIt, + const GOTEntry *It, StringRef StrTable, const Elf_Sym *Sym) { DictScope D(W, "Entry"); int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); @@ -1489,10 +1903,11 @@ void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, unsigned SectionIndex = 0; StringRef SectionName; - getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex); + getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(), + Dumper->getShndxTable(), SectionName, SectionIndex); W.printHex("Section", SectionName, SectionIndex); - std::string FullSymbolName = getFullSymbolName(*Obj, Sym, StrTable, true); + std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true); W.printNumber("Name", FullSymbolName, Sym->st_name); } @@ -1502,7 +1917,7 @@ template void ELFDumper::printMipsPLTGOT() { return; } - MipsGOTParser GOTParser(Obj, W); + MipsGOTParser GOTParser(this, Obj, dynamic_table(), W); GOTParser.parseGOT(); GOTParser.parsePLT(); } @@ -1644,7 +2059,7 @@ template void ELFDumper::printMipsReginfo() { } template void ELFDumper::printStackMap() const { - const typename ELFFile::Elf_Shdr *StackMapSection = nullptr; + const Elf_Shdr *StackMapSection = nullptr; for (const auto &Sec : Obj->sections()) { ErrorOr Name = Obj->getSectionName(&Sec); if (*Name == ".llvm_stackmaps") {