summaryrefslogtreecommitdiff
path: root/tools/llvm-readobj
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2018-06-02 16:33:01 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2018-06-02 16:33:01 +0000
commit56500c79d3316da7c91af80b246408542cc705b6 (patch)
treef8a5032b37b8db5f336aa34ba93ce147088dd437 /tools/llvm-readobj
parentd1bfb4c41d35da2029a53efc84799a3810f30f68 (diff)
[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
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp52
-rw-r--r--tools/llvm-readobj/ObjDumper.h1
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp4
3 files changed, 57 insertions, 0 deletions
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<Elf_Word> 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<Elf_Word> 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<ELFT> *Obj) = 0;
virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0;
virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0;
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
@@ -349,6 +356,7 @@ public:
size_t Offset) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
@@ -410,6 +418,7 @@ public:
void printDynamicRelocations(const ELFO *Obj) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
@@ -737,6 +746,16 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
}
template <typename ELFT>
+StringRef ELFDumper<ELFT>::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 <typename ELFT>
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
StringRef StrTable,
bool IsDynamic) const {
@@ -1390,6 +1409,10 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *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 <class ELFT> void ELFDumper<ELFT>::printHashHistogram() {
ELFDumperStyle->printHashHistogram(Obj);
}
+template <class ELFT> void ELFDumper<ELFT>::printCGProfile() {
+ ELFDumperStyle->printCGProfile(Obj);
+}
+
template <class ELFT> void ELFDumper<ELFT>::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<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
}
}
+template <class ELFT>
+void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ OS << "GNUStyle::printCGProfile not implemented\n";
+}
+
static std::string getGNUNoteTypeName(const uint32_t NT) {
static const struct {
uint32_t ID;
@@ -4138,6 +4172,24 @@ void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
}
template <class ELFT>
+void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ ListScope L(W, "CGProfile");
+ if (!this->dumper()->getDotCGProfileSec())
+ return;
+ auto CGProfile =
+ unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>(
+ 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 <class ELFT>
void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *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<bool> CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section"));
+
cl::opt<OutputStyleTy>
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();
}