From d6d1ca80abd486b6bcdf70e1cd9331972406e258 Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Fri, 19 Apr 2024 11:31:29 +0300 Subject: [PATCH] [ADLT][readelf] add --adlt-section option for pretty .adlt section dump - added --adlt-section for readobj tool (readelf with LLVM style output) - ADLTSection header moved to the common space as a part of binary interface - looking and extracting .adlt and .adlt.strtab sections - parsing .adlt binary format, dumping it in a pretty way Signed-off-by: Khomutov Nikita Change-Id: I816f02f17a3d983e3b737494c79d2c006874d337 --- lld/ELF/SyntheticSections.h | 5 +- .../include/llvm/BinaryFormat}/ADLTSection.h | 13 +- llvm/tools/llvm-readobj/ELFDumper.cpp | 231 +++++++++++++++++- llvm/tools/llvm-readobj/ObjDumper.h | 1 + llvm/tools/llvm-readobj/Opts.td | 1 + llvm/tools/llvm-readobj/llvm-readobj.cpp | 4 + 6 files changed, 245 insertions(+), 10 deletions(-) rename {lld/ELF => llvm/include/llvm/BinaryFormat}/ADLTSection.h (96%) diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index a93ff052cfe3..8832ca87bc2d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -22,10 +22,10 @@ #include "Config.h" #include "EhFrame.h" // OHOS_LOCAL -#include "ADLTSection.h" // OHOS_LOCAL #include "InputSection.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/BinaryFormat/ADLTSection.h" // OHOS_LOCAL #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Threading.h" @@ -1225,6 +1225,8 @@ public: namespace adlt { +using namespace llvm::adlt; + template class AdltSection final : public SyntheticSection { public: @@ -1313,7 +1315,6 @@ private: } // namespace adlt - InputSection *createInterpSection(); MergeInputSection *createCommentSection(); template void splitSections(); diff --git a/lld/ELF/ADLTSection.h b/llvm/include/llvm/BinaryFormat/ADLTSection.h similarity index 96% rename from lld/ELF/ADLTSection.h rename to llvm/include/llvm/BinaryFormat/ADLTSection.h index 1327de5950ec..37656b486b77 100644 --- a/lld/ELF/ADLTSection.h +++ b/llvm/include/llvm/BinaryFormat/ADLTSection.h @@ -16,13 +16,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_ELF_ADLT_SECTION_H -#define LLD_ELF_ADLT_SECTION_H +#ifndef LLVM_BINARYFORMAT_ADLTSECTION_H +#define LLVM_BINARYFORMAT_ADLTSECTION_H #ifdef __cplusplus #include -namespace lld { -namespace elf { + +namespace llvm { namespace adlt { #else // __cplusplus @@ -123,8 +123,7 @@ static const adlt_semver_t adltSchemaVersion = {1, 0, 0}; #ifdef __cplusplus } // namespace adlt -} // namespace elf -} // namespace lld +} // namespace llvm #endif // __cplusplus -#endif // LLD_ELF_ADLT_SECTION_H +#endif // LLVM_BINARYFORMAT_ADLTSECTION_H diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 81aa58205eb0..26d30094f28b 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -29,6 +29,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/ADLTSection.h" #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MsgPackDocument.h" @@ -353,6 +354,8 @@ protected: void loadDynamicTable(); void parseDynamicTable(); + Expected> findAdlt(); + Expected getSymbolVersion(const Elf_Sym &Sym, bool &IsDefault) const; Expected, 0> *> getVersionMap() const; @@ -365,11 +368,14 @@ protected: DynRegionInfo DynSymTabShndxRegion; DynRegionInfo DynamicTable; StringRef DynamicStringTable; + StringRef AdltStringTable; const Elf_Hash *HashTable = nullptr; const Elf_GnuHash *GnuHashTable = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; const Elf_Shdr *DotDynsymSec = nullptr; const Elf_Shdr *DotAddrsigSec = nullptr; + const Elf_Shdr *DotAdlt = nullptr; + const Elf_Shdr *DotAdltStrtab = nullptr; DenseMap> ShndxTables; Optional SONameOffset; Optional>> AddressToIndexMap; @@ -388,7 +394,9 @@ protected: Expected getSymbolSectionName(const Elf_Sym &Symbol, unsigned SectionIndex) const; std::string getStaticSymbolName(uint32_t Index) const; + StringRef getDynamicString(uint64_t Value, StringRef StringTable) const; StringRef getDynamicString(uint64_t Value) const; + StringRef getAdltDynamicString(uint64_t Value) const; void printSymbolsHelper(bool IsDynamic) const; std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; @@ -572,6 +580,7 @@ public: void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printHashHistograms() override; + void printAdltSection() override; void printCGProfile() override; void printBBAddrMaps() override; void printAddrsig() override; @@ -676,6 +685,7 @@ public: void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printHashHistograms() override; + void printAdltSection() override; void printCGProfile() override; void printBBAddrMaps() override; void printAddrsig() override; @@ -1706,6 +1716,45 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { } } +const EnumEntry AdltHashTypes[] = { + {"None", "NONE", llvm::adlt::ADLT_HASH_TYPE_NONE}, + {"GnuHash", "GNU_HASH", llvm::adlt::ADLT_HASH_TYPE_GNU_HASH}, + {"SysvHash", "SYSV_HASH", llvm::adlt::ADLT_HASH_TYPE_SYSV_HASH}, + {"Debug", "DEBUG", llvm::adlt::ADLT_HASH_TYPE_DEBUG_CONST}, +}; + +template +Expected> ELFDumper::findAdlt() { + // Try to locate .adlt section in the sections table + typename ELFT::ShdrRange Sections = cantFail(Obj.sections()); + for (const Elf_Shdr &Sec : Sections) { + if (DotAdlt && DotAdltStrtab) break; + + switch (Sec.sh_type) { + case ELF::SHT_STRTAB: + if (!DotAdltStrtab && getPrintableSectionName(Sec) == ".adlt.strtab") + DotAdltStrtab = &Sec; + break; + case ELF::SHT_PROGBITS: + if (!DotAdlt && getPrintableSectionName(Sec) == ".adlt") + DotAdlt = &Sec; + break; + } + } + + if (!DotAdlt) + return createError(".adlt section not found"); + if (!DotAdltStrtab) + return createError("has .adlt but .adlt.strtab section not found"); + + Expected StrTabOrErr = Obj.getStringTable(*DotAdltStrtab); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + AdltStringTable = *StrTabOrErr; + + return Obj.getSectionContents(*DotAdlt); +} + template std::pair ELFDumper::findDynamic() { @@ -2399,7 +2448,18 @@ std::string ELFDumper::getDynamicEntry(uint64_t Type, } template -StringRef ELFDumper::getDynamicString(uint64_t Value) const { +StringRef ELFDumper::getDynamicString(uint64_t Value) const { + return this->getDynamicString(Value, DynamicStringTable); +} + +template +StringRef ELFDumper::getAdltDynamicString(uint64_t Value) const { + return this->getDynamicString(Value, AdltStringTable); +} + +template +StringRef ELFDumper::getDynamicString( + uint64_t Value, StringRef DynamicStringTable) const { if (DynamicStringTable.empty() && !DynamicStringTable.data()) { reportUniqueWarning("string table was not found"); return ""; @@ -4823,6 +4883,10 @@ template void GNUELFDumper::printHashHistograms() { } } +template void GNUELFDumper::printAdltSection() { + OS << "GNUStyle::printAdltSection not implemented\n"; +} + template void GNUELFDumper::printCGProfile() { OS << "GNUStyle::printCGProfile not implemented\n"; } @@ -6955,6 +7019,171 @@ template void LLVMELFDumper::printHashHistograms() { W.startLine() << "Hash Histogram not implemented!\n"; } + +template void LLVMELFDumper::printAdltSection() { + using namespace llvm::adlt; + + Expected> ContentsOrErr = this->findAdlt(); + if (!ContentsOrErr) { + return this->reportUniqueWarning(ContentsOrErr.takeError()); + } + + ArrayRef adltRaw = ContentsOrErr.get(); + auto* header = reinterpret_cast(adltRaw.data()); + const auto& ver = header->schemaVersion; + + DictScope DSec(W, "ADLT"); + + do { + DictScope DHeader(W, "Header"); + W.printVersion("schema-version", ver.major, ver.minor, ver.patch); + + if (ver.major > 1) { + this->reportUniqueWarning(Twine("schema version not supported yet") ); + return; + } + + W.printHex("schema-header-size", header->schemaHeaderSize); + W.printHex("schema-psod-size", header->schemaPSODSize); + W.printNumber("shared-objects-num", header->sharedObjectsNum); + W.printEnum("string-hash-type", header->stringHashType, makeArrayRef(AdltHashTypes)); + W.printHex("blob-start", header->blobStart); + W.printHex("blob-size", header->blobSize); + W.printHex("overall-mapped-size", header->overallMappedSize); + + if (ver.minor < 1) break; + + { + DictScope RDEntry(W, "rela-dyn-segs"); + const auto& arr = header->relaDynSegs; + W.printHex("offset", arr.offset); + W.printHex("size", arr.size); + } + { + DictScope RPEntry(W, "rela-plt-segs"); + const auto& arr = header->relaPltSegs; + W.printHex("offset", arr.offset); + W.printHex("size", arr.size); + } + } while(0); + + ArrayRef psodsRaw = adltRaw.slice( + header->schemaHeaderSize, + header->sharedObjectsNum * header->schemaPSODSize); + ArrayRef blob = adltRaw.slice(header->blobStart, header->blobSize); + + if (psodsRaw.data() + psodsRaw.size() > blob.data()) + return this->reportUniqueWarning("invalid .adlt section: " + "PSOD and blob entries are overlapped"); + if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) + return this->reportUniqueWarning("invalid .adlt section: " + "blob is out section range"); + + { + ListScope LPsods(W, "PSODs"); + + for (size_t psodIdx = 0; psodIdx < header->sharedObjectsNum; ++psodIdx) { + const adlt_psod_t& psod = *reinterpret_cast + (psodsRaw.data() + psodIdx * header->schemaPSODSize); + + DictScope LEntry(W, ("#" + Twine(psodIdx)).str()); + W.printString("soname", this->getAdltDynamicString(psod.soName)); + W.printHex("soname-hash", psod.soNameHash); + { + DictScope IAEntry(W, "init-array"); + W.printHex("size", psod.initArray.size); + W.printNumber("sec-index", psod.initArray.secIndex); + W.printHex("offset", psod.initArray.offset); + } + { + DictScope IAEntry(W, "fini-array"); + W.printHex("size", psod.finiArray.size); + W.printNumber("sec-index", psod.finiArray.secIndex); + W.printHex("offset", psod.finiArray.offset); + } + { + DictScope DNEntry(W, "dt-needed"); + W.printHex("size", psod.dtNeeded.size); + W.printHex("offset", psod.dtNeeded.offset); + + const auto chunk = blob.slice(psod.dtNeeded.offset, psod.dtNeeded.size); + if (!chunk.empty()) { + W.printBinary("raw", chunk); + + ArrayRef deps( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(adlt_dt_needed_index_t)); + + ListScope NeedList(W, "needed-libs"); + for (const auto& need : deps) { + DictScope DepEntry(W, this->getAdltDynamicString(need.sonameOffset)); + W.printBoolean("is-internal", need.hasInternalPSOD); + if (need.hasInternalPSOD) + W.printNumber("psod-id", need.PSODindex); + } + } + } + { + DictScope SLEntry(W, "shared-local-symbol"); + const auto& csref = psod.sharedLocalSymbolIndex; + W.printNumber("sec-index", csref.secIndex); + W.printHex("offset", csref.offset); + } + { + DictScope SGEntry(W, "shared-global-symbol"); + const auto& csref = psod.sharedGlobalSymbolIndex; + W.printNumber("sec-index", csref.secIndex); + W.printHex("offset", csref.offset); + } + { + DictScope PHEntry(W, "ph-index"); + const auto& arr = psod.phIndexes; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + ArrayRef phIdxs( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(uint16_t)); + W.printBinary("raw", chunk); + W.printList("values", phIdxs); + } + } + + if (ver.minor < 1) continue; + + { + DictScope RDSEntry(W, "rela-dyn-segs"); + const auto& arr = psod.relaDynSegs; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) + W.printBinary("raw", chunk); + } + { + DictScope RPSEntry(W, "rela-plt-segs"); + const auto& arr = psod.relaPltSegs; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) + W.printBinary("raw", chunk); + } + } + } + + { + DictScope DBlob (W, "Blob"); + W.printHex("start", header->blobStart); + W.printHex("size", header->blobSize); + W.printBinaryBlock("raw", blob); + } +} + // Returns true if rel/rela section exists, and populates SymbolIndices. // Otherwise returns false. template diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 292efd2ae350..320e5972d479 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -129,6 +129,7 @@ public: virtual void printVersionInfo() {} virtual void printGroupSections() {} virtual void printHashHistograms() {} + virtual void printAdltSection() {} virtual void printCGProfile() {} virtual void printBBAddrMaps() {} virtual void printAddrsig() {} diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 4687fc71245f..012a16bb99ff 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -55,6 +55,7 @@ def section_groups : FF<"section-groups", "Display section groups">, Group, Group; def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group; def hash_table : FF<"hash-table", "Display .hash section">, Group; +def adlt_section: FF<"adlt-section", "Display .adlt section in a pretty format">, Group; def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group; def notes : FF<"notes", "Display notes">, Group; def program_headers : FF<"program-headers", "Display program headers">, Group; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index e1ebbeb41f28..8c470a60ff9a 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -125,6 +125,7 @@ static cl::boolOrDefault SectionMapping; static SmallVector SortKeys; // ELF specific options. +static bool AdltSection; static bool DynamicTable; static bool ELFLinkerOptions; static bool GnuHashTable; @@ -253,6 +254,7 @@ static void parseOptions(const opt::InputArgList &Args) { OutputStyleChoice + "'"); } } + opts::AdltSection = Args.hasArg(OPT_adlt_section); opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table); opts::HashSymbols = Args.hasArg(OPT_hash_symbols); opts::HashTable = Args.hasArg(OPT_hash_table); @@ -449,6 +451,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, Dumper->printGroupSections(); if (opts::HashHistogram) Dumper->printHashHistograms(); + if (opts::AdltSection) + Dumper->printAdltSection(); if (opts::CGProfile) Dumper->printCGProfile(); if (opts::BBAddrMap) -- Gitee