diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index b1b428a0de58..8c1c6fef89ec 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -342,12 +342,6 @@ public: virtual void printProgramHeaders(const ELFFile *Obj, bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) = 0; - virtual void printVersionSymbolSection(const ELFFile *Obj, - const Elf_Shdr *Sec) = 0; - virtual void printVersionDefinitionSection(const ELFFile *Obj, - const Elf_Shdr *Sec) = 0; - virtual void printVersionDependencySection(const ELFFile *Obj, - const Elf_Shdr *Sec) = 0; virtual void printHashHistogram(const ELFFile *Obj) = 0; virtual void printCGProfile(const ELFFile *Obj) = 0; virtual void printAddrsig(const ELFFile *Obj) = 0; @@ -382,12 +376,6 @@ public: size_t Offset) override; void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) override; - void printVersionSymbolSection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; - void printVersionDefinitionSection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; - void printVersionDependencySection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; void printAddrsig(const ELFFile *Obj) override; @@ -482,12 +470,6 @@ public: void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) override; - void printVersionSymbolSection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; - void printVersionDefinitionSection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; - void printVersionDependencySection(const ELFFile *Obj, - const Elf_Shdr *Sec) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; void printAddrsig(const ELFFile *Obj) override; @@ -653,18 +635,113 @@ static void printVersionSymbolSection(ELFDumper *Dumper, const ELFO *Obj, } } +static const EnumEntry SymVersionFlags[] = { + {"Base", "BASE", VER_FLG_BASE}, + {"Weak", "WEAK", VER_FLG_WEAK}, + {"Info", "INFO", VER_FLG_INFO}}; + +template +static void printVersionDefinitionSection(ELFDumper *Dumper, + const ELFO *Obj, + const typename ELFO::Elf_Shdr *Sec, + ScopedPrinter &W) { + using VerDef = typename ELFO::Elf_Verdef; + using VerdAux = typename ELFO::Elf_Verdaux; + + DictScope SD(W, "SHT_GNU_verdef"); + if (!Sec) + return; + + const uint8_t *SecStartAddress = + (const uint8_t *)Obj->base() + Sec->sh_offset; + const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size; + const uint8_t *P = SecStartAddress; + const typename ELFO::Elf_Shdr *StrTab = + unwrapOrError(Obj->getSection(Sec->sh_link)); + + unsigned VerDefsNum = Sec->sh_info; + while (VerDefsNum--) { + if (P + sizeof(VerDef) > SecEndAddress) + report_fatal_error("invalid offset in the section"); + + auto *VD = reinterpret_cast(P); + DictScope Def(W, "Definition"); + W.printNumber("Version", VD->vd_version); + W.printEnum("Flags", VD->vd_flags, makeArrayRef(SymVersionFlags)); + W.printNumber("Index", VD->vd_ndx); + W.printNumber("Hash", VD->vd_hash); + W.printString("Name", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + VD->getAux()->vda_name))); + if (!VD->vd_cnt) + report_fatal_error("at least one definition string must exist"); + if (VD->vd_cnt > 2) + report_fatal_error("more than one predecessor is not expected"); + + if (VD->vd_cnt == 2) { + const uint8_t *PAux = P + VD->vd_aux + VD->getAux()->vda_next; + const VerdAux *Aux = reinterpret_cast(PAux); + W.printString("Predecessor", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Aux->vda_name))); + } + + P += VD->vd_next; + } +} + +template +static void printVersionDependencySection(ELFDumper *Dumper, + const ELFO *Obj, + const typename ELFO::Elf_Shdr *Sec, + ScopedPrinter &W) { + using VerNeed = typename ELFO::Elf_Verneed; + using VernAux = typename ELFO::Elf_Vernaux; + + DictScope SD(W, "SHT_GNU_verneed"); + if (!Sec) + return; + + const uint8_t *SecData = (const uint8_t *)Obj->base() + Sec->sh_offset; + const typename ELFO::Elf_Shdr *StrTab = + unwrapOrError(Obj->getSection(Sec->sh_link)); + + const uint8_t *P = SecData; + unsigned VerNeedNum = Sec->sh_info; + for (unsigned I = 0; I < VerNeedNum; ++I) { + const VerNeed *Need = reinterpret_cast(P); + DictScope Entry(W, "Dependency"); + W.printNumber("Version", Need->vn_version); + W.printNumber("Count", Need->vn_cnt); + W.printString("FileName", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Need->vn_file))); + + const uint8_t *PAux = P + Need->vn_aux; + for (unsigned J = 0; J < Need->vn_cnt; ++J) { + const VernAux *Aux = reinterpret_cast(PAux); + DictScope Entry(W, "Entry"); + W.printNumber("Hash", Aux->vna_hash); + W.printEnum("Flags", Aux->vna_flags, makeArrayRef(SymVersionFlags)); + W.printNumber("Index", Aux->vna_other); + W.printString("Name", + StringRef((const char *)(Obj->base() + StrTab->sh_offset + + Aux->vna_name))); + PAux += Aux->vna_next; + } + P += Need->vn_next; + } +} + template void ELFDumper::printVersionInfo() { // Dump version symbol section. - ELFDumperStyle->printVersionSymbolSection(ObjF->getELFFile(), - dot_gnu_version_sec); + printVersionSymbolSection(this, ObjF->getELFFile(), dot_gnu_version_sec, W); // Dump version definition section. - ELFDumperStyle->printVersionDefinitionSection(ObjF->getELFFile(), - dot_gnu_version_d_sec); + printVersionDefinitionSection(this, ObjF->getELFFile(), dot_gnu_version_d_sec, W); // Dump version dependency section. - ELFDumperStyle->printVersionDependencySection(ObjF->getELFFile(), - dot_gnu_version_r_sec); + printVersionDependencySection(this, ObjF->getELFFile(), dot_gnu_version_r_sec, W); } template @@ -848,11 +925,6 @@ static const EnumEntry ElfOSABI[] = { {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} }; -static const EnumEntry SymVersionFlags[] = { - {"Base", "BASE", VER_FLG_BASE}, - {"Weak", "WEAK", VER_FLG_WEAK}, - {"Info", "INFO", VER_FLG_INFO}}; - static const EnumEntry AMDGPUElfOSABI[] = { {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL}, @@ -3388,36 +3460,6 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { } } -template -void GNUStyle::printVersionSymbolSection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - if (!Sec) - return; - - StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - OS << "Dumper for " << SecName << " is not implemented\n"; -} - -template -void GNUStyle::printVersionDefinitionSection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - if (!Sec) - return; - - StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - OS << "Dumper for " << SecName << " is not implemented\n"; -} - -template -void GNUStyle::printVersionDependencySection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - if (!Sec) - return; - - StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - OS << "Dumper for " << SecName << " is not implemented\n"; -} - // Hash histogram shows statistics of how efficient the hash was for the // dynamic symbol table. The table shows number of hash buckets for different // lengths of chains as absolute number and percentage of the total buckets. @@ -4496,122 +4538,6 @@ void LLVMStyle::printProgramHeaders(const ELFO *Obj) { } } -template -void LLVMStyle::printVersionSymbolSection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - DictScope SS(W, "Version symbols"); - if (!Sec) - return; - - StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); - W.printNumber("Section Name", SecName, Sec->sh_name); - W.printHex("Address", Sec->sh_addr); - W.printHex("Offset", Sec->sh_offset); - W.printNumber("Link", Sec->sh_link); - - const uint8_t *VersymBuf = (const uint8_t *)Obj->base() + Sec->sh_offset; - const ELFDumper *Dumper = this->dumper(); - StringRef StrTable = Dumper->getDynamicStringTable(); - - // Same number of entries in the dynamic symbol table (DT_SYMTAB). - ListScope Syms(W, "Symbols"); - for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) { - DictScope S(W, "Symbol"); - const Elf_Versym *Versym = reinterpret_cast(VersymBuf); - std::string FullSymbolName = - Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */); - W.printNumber("Version", Versym->vs_index); - W.printString("Name", FullSymbolName); - VersymBuf += sizeof(Elf_Versym); - } -} - -template -void LLVMStyle::printVersionDefinitionSection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - DictScope SD(W, "SHT_GNU_verdef"); - if (!Sec) - return; - - const uint8_t *SecStartAddress = - (const uint8_t *)Obj->base() + Sec->sh_offset; - const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size; - const uint8_t *VerdefBuf = SecStartAddress; - const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link)); - - unsigned VerDefsNum = Sec->sh_info; - while (VerDefsNum--) { - if (VerdefBuf + sizeof(Elf_Verdef) > SecEndAddress) - // FIXME: report_fatal_error is not a good way to report error. We should - // emit a parsing error here and below. - report_fatal_error("invalid offset in the section"); - - const Elf_Verdef *Verdef = reinterpret_cast(VerdefBuf); - DictScope Def(W, "Definition"); - W.printNumber("Version", Verdef->vd_version); - W.printEnum("Flags", Verdef->vd_flags, makeArrayRef(SymVersionFlags)); - W.printNumber("Index", Verdef->vd_ndx); - W.printNumber("Hash", Verdef->vd_hash); - W.printString("Name", - StringRef((const char *)(Obj->base() + StrTab->sh_offset + - Verdef->getAux()->vda_name))); - if (!Verdef->vd_cnt) - report_fatal_error("at least one definition string must exist"); - if (Verdef->vd_cnt > 2) - report_fatal_error("more than one predecessor is not expected"); - - if (Verdef->vd_cnt == 2) { - const uint8_t *VerdauxBuf = - VerdefBuf + Verdef->vd_aux + Verdef->getAux()->vda_next; - const Elf_Verdaux *Verdaux = - reinterpret_cast(VerdauxBuf); - W.printString("Predecessor", - StringRef((const char *)(Obj->base() + StrTab->sh_offset + - Verdaux->vda_name))); - } - VerdefBuf += Verdef->vd_next; - } -} - -template -void LLVMStyle::printVersionDependencySection(const ELFFile *Obj, - const Elf_Shdr *Sec) { - DictScope SD(W, "SHT_GNU_verneed"); - if (!Sec) - return; - - const uint8_t *SecData = (const uint8_t *)Obj->base() + Sec->sh_offset; - const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link)); - - const uint8_t *VerneedBuf = SecData; - unsigned VerneedNum = Sec->sh_info; - for (unsigned I = 0; I < VerneedNum; ++I) { - const Elf_Verneed *Verneed = - reinterpret_cast(VerneedBuf); - DictScope Entry(W, "Dependency"); - W.printNumber("Version", Verneed->vn_version); - W.printNumber("Count", Verneed->vn_cnt); - W.printString("FileName", - StringRef((const char *)(Obj->base() + StrTab->sh_offset + - Verneed->vn_file))); - - const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux; - for (unsigned J = 0; J < Verneed->vn_cnt; ++J) { - const Elf_Vernaux *Vernaux = - reinterpret_cast(VernauxBuf); - DictScope Entry(W, "Entry"); - W.printNumber("Hash", Vernaux->vna_hash); - W.printEnum("Flags", Vernaux->vna_flags, makeArrayRef(SymVersionFlags)); - W.printNumber("Index", Vernaux->vna_other); - W.printString("Name", - StringRef((const char *)(Obj->base() + StrTab->sh_offset + - Vernaux->vna_name))); - VernauxBuf += Vernaux->vna_next; - } - VerneedBuf += Verneed->vn_next; - } -} - template void LLVMStyle::printHashHistogram(const ELFFile *Obj) { W.startLine() << "Hash Histogram not implemented!\n";