From 56500c79d3316da7c91af80b246408542cc705b6 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 2 Jun 2018 16:33:01 +0000 Subject: [MC] Add assembler support for .cg_profile. Object FIle Representation At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like: .cg_profile a, b, 32 .cg_profile freq, a, 11 .cg_profile freq, b, 20 When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight). Differential Revision: https://reviews.llvm.org/D44965 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333823 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-readobj/ELFDumper.cpp | 52 +++++++++++++++++++++++++++++++++++++ tools/llvm-readobj/ObjDumper.h | 1 + tools/llvm-readobj/llvm-readobj.cpp | 4 +++ 3 files changed, 57 insertions(+) (limited to 'tools/llvm-readobj') diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 6ca28e273cc..993d4aaa81e 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -100,6 +100,7 @@ using namespace ELF; using Elf_Vernaux = typename ELFT::Vernaux; \ using Elf_Verdef = typename ELFT::Verdef; \ using Elf_Verdaux = typename ELFT::Verdaux; \ + using Elf_CGProfile = typename ELFT::CGProfile; \ using uintX_t = typename ELFT::uint; namespace { @@ -164,6 +165,8 @@ public: void printHashHistogram() override; + void printCGProfile() override; + void printNotes() override; void printELFLinkerOptions() override; @@ -210,6 +213,7 @@ private: const Elf_Hash *HashTable = nullptr; const Elf_GnuHash *GnuHashTable = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; + const Elf_Shdr *DotCGProfileSec = nullptr; StringRef DynSymtabName; ArrayRef ShndxTable; @@ -257,9 +261,11 @@ public: void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, StringRef &SectionName, unsigned &SectionIndex) const; + StringRef getStaticSymbolName(uint32_t Index) const; void printSymbolsHelper(bool IsDynamic) const; const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } + const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } ArrayRef getShndxTable() const { return ShndxTable; } StringRef getDynamicStringTable() const { return DynamicStringTable; } const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } @@ -319,6 +325,7 @@ public: bool IsDynamic) = 0; virtual void printProgramHeaders(const ELFFile *Obj) = 0; virtual void printHashHistogram(const ELFFile *Obj) = 0; + virtual void printCGProfile(const ELFFile *Obj) = 0; virtual void printNotes(const ELFFile *Obj) = 0; virtual void printELFLinkerOptions(const ELFFile *Obj) = 0; virtual void printMipsGOT(const MipsGOTParser &Parser) = 0; @@ -349,6 +356,7 @@ public: size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile *Obj) override; + void printCGProfile(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; void printELFLinkerOptions(const ELFFile *Obj) override; void printMipsGOT(const MipsGOTParser &Parser) override; @@ -410,6 +418,7 @@ public: void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile *Obj) override; + void printCGProfile(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; void printELFLinkerOptions(const ELFFile *Obj) override; void printMipsGOT(const MipsGOTParser &Parser) override; @@ -736,6 +745,16 @@ StringRef ELFDumper::getSymbolVersion(StringRef StrTab, return StringRef(StrTab.data() + name_offset); } +template +StringRef ELFDumper::getStaticSymbolName(uint32_t Index) const { + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); + Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); + if (Index >= Syms.size()) + reportError("Invalid symbol index"); + const Elf_Sym *Sym = &Syms[Index]; + return unwrapOrError(Sym->getName(StrTable)); +} + template std::string ELFDumper::getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, @@ -1390,6 +1409,10 @@ ELFDumper::ELFDumper(const ELFFile *Obj, ScopedPrinter &Writer) reportError("Multiple SHT_GNU_verneed"); dot_gnu_version_r_sec = &Sec; break; + case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + if (DotCGProfileSec != nullptr) + reportError("Multiple .note.llvm.cgprofile"); + DotCGProfileSec = &Sec; } } @@ -1534,6 +1557,10 @@ template void ELFDumper::printHashHistogram() { ELFDumperStyle->printHashHistogram(Obj); } +template void ELFDumper::printCGProfile() { + ELFDumperStyle->printCGProfile(Obj); +} + template void ELFDumper::printNotes() { ELFDumperStyle->printNotes(Obj); } @@ -2721,6 +2748,8 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) { return "LLVM_ODRTAB"; case SHT_LLVM_LINKER_OPTIONS: return "LLVM_LINKER_OPTIONS"; + case SHT_LLVM_CALL_GRAPH_PROFILE: + return "LLVM_CALL_GRAPH_PROFILE"; // FIXME: Parse processor specific GNU attributes case SHT_GNU_ATTRIBUTES: return "ATTRIBUTES"; @@ -3374,6 +3403,11 @@ void GNUStyle::printHashHistogram(const ELFFile *Obj) { } } +template +void GNUStyle::printCGProfile(const ELFFile *Obj) { + OS << "GNUStyle::printCGProfile not implemented\n"; +} + static std::string getGNUNoteTypeName(const uint32_t NT) { static const struct { uint32_t ID; @@ -4137,6 +4171,24 @@ void LLVMStyle::printHashHistogram(const ELFFile *Obj) { W.startLine() << "Hash Histogram not implemented!\n"; } +template +void LLVMStyle::printCGProfile(const ELFFile *Obj) { + ListScope L(W, "CGProfile"); + if (!this->dumper()->getDotCGProfileSec()) + return; + auto CGProfile = + unwrapOrError(Obj->template getSectionContentsAsArray( + this->dumper()->getDotCGProfileSec())); + for (const Elf_CGProfile &CGPE : CGProfile) { + DictScope D(W, "CGProfileEntry"); + W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from), + CGPE.cgp_from); + W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to), + CGPE.cgp_to); + W.printNumber("Weight", CGPE.cgp_weight); + } +} + template void LLVMStyle::printNotes(const ELFFile *Obj) { W.startLine() << "printNotes not implemented!\n"; diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 2bf4dfe5a40..e13646588e7 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -47,6 +47,7 @@ public: virtual void printVersionInfo() {} virtual void printGroupSections() {} virtual void printHashHistogram() {} + virtual void printCGProfile() {} virtual void printNotes() {} virtual void printELFLinkerOptions() {} diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 4b8a1b32471..f871dc90950 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -284,6 +284,8 @@ namespace opts { cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"), cl::aliasopt(HashHistogram)); + cl::opt CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section")); + cl::opt Output("elf-output-style", cl::desc("Specify ELF dump style"), cl::values(clEnumVal(LLVM, "LLVM default style"), @@ -441,6 +443,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) { Dumper->printGroupSections(); if (opts::HashHistogram) Dumper->printHashHistogram(); + if (opts::CGProfile) + Dumper->printCGProfile(); if (opts::Notes) Dumper->printNotes(); } -- cgit v1.2.3