[llvm] [llvm-readobj] Dump callgraph section info for ELF (PR #157499)
Prabhu Rajasekaran via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 31 13:30:27 PDT 2025
================
@@ -8094,6 +8413,82 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
}
}
+template <class ELFT> void LLVMELFDumper<ELFT>::printCallGraphInfo() {
+ if (!this->processCallGraphSection() || this->FuncCGInfos.empty())
+ return;
+
+ std::vector<Relocation<ELFT>> Relocations;
+ const Elf_Shdr *RelocSymTab = nullptr;
+ this->getCallGraphRelocations(Relocations, RelocSymTab);
+
+ auto PrintFunc = [](uint64_t FuncEntryPC, std::string FuncSymName,
+ ScopedPrinter &W) {
+ if (!FuncSymName.empty())
+ W.printString("Name", FuncSymName);
+ W.printHex("Address", FuncEntryPC);
+ };
+
+ auto PrintReloc =
+ [&](uint64_t FuncEntryPC,
+ typename std::vector<Relocation<ELFT>>::iterator &Reloc) {
+ if (Reloc == Relocations.end()) {
+ W.printHex("Offset", FuncEntryPC);
+ return;
+ }
+ Expected<RelSymbol<ELFT>> RelSym =
+ this->getRelocationTarget(*Reloc, RelocSymTab);
+ if (!RelSym) {
+ this->reportUniqueWarning(RelSym.takeError());
+ W.printHex("Offset", FuncEntryPC);
+ return;
+ }
+ DictScope DCs(W, "Entry");
+ SmallString<32> RelocName;
+ this->Obj.getRelocationTypeName(Reloc->Type, RelocName);
+ W.printString("Relocation", RelocName);
+ W.printString("Symbol", RelSym->Name);
+ if (Reloc->Addend)
+ W.printHex("Addend", (uintX_t)*Reloc->Addend);
+ };
+
+ auto PrintFunctionInfo = [&](uint64_t FuncEntryPC) {
+ if (this->Obj.getHeader().e_type != ELF::ET_REL) {
+ std::string FuncSymName = this->getFunctionNames(FuncEntryPC);
+ PrintFunc(FuncEntryPC, FuncSymName, W);
+ return;
+ }
+ auto Reloc = llvm::lower_bound(
+ Relocations, FuncEntryPC,
+ [](const Relocation<ELFT> &R, uint64_t O) { return R.Offset < O; });
+ PrintReloc(FuncEntryPC, Reloc);
+ };
+
+ ListScope CGI(W, "callgraph_info");
+ for (const auto &CGInfo : this->FuncCGInfos) {
+ DictScope D(W, "Function");
+ PrintFunctionInfo(CGInfo.FunctionAddress);
+ W.printNumber("Version", CGInfo.FormatVersionNumber);
+ W.printBoolean("IsIndirectTarget", CGInfo.IsIndirectTarget);
+ W.printHex("TypeId", CGInfo.FunctionTypeId);
+ W.printNumber("NumDirectCallees", CGInfo.DirectCallees.size());
+ {
+ ListScope DCs(W, "DirectCallees");
+ for (auto CalleePC : CGInfo.DirectCallees) {
+ DictScope D(W, "Entry");
----------------
Prabhuk wrote:
Each "Entry" here has a name field and an offset/address field.
```
DirectCallees [
Entry {
Name: foo
Address: 0x1790
}
Entry {
Name: bar
Address: 0x17A0
}
Entry {
Name: baz
Address: 0x17B0
}
]
```
Without "Entry" DictScope, it will become hard to parse this as a list of objects for any scripting that will consume this info:
```
DirectCallees [
Name: foo
Address: 0x1790
Name: bar
Address: 0x17A0
Name: baz
Address: 0x17B0
]
```
https://github.com/llvm/llvm-project/pull/157499
More information about the llvm-commits
mailing list