[llvm] Reland "[llvm-readobj] Dump callgraph section info for ELF" (PR #176260)
James Henderson via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 29 01:40:55 PST 2026
================
@@ -8148,6 +8307,112 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
}
}
+template <class ELFT> void LLVMELFDumper<ELFT>::printCallGraphInfo() {
+ // Call graph section is of type SHT_LLVM_CALL_GRAPH. Typically named
+ // ".llvm.callgraph". First fetch the section by its type.
+ using Elf_Shdr = typename ELFT::Shdr;
+ Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> MapOrErr =
+ this->Obj.getSectionAndRelocations([](const Elf_Shdr &Sec) {
+ return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH;
+ });
+ if (!MapOrErr || MapOrErr->empty()) {
+ reportWarning(createError("no SHT_LLVM_CALL_GRAPH section found: " +
+ toString(MapOrErr.takeError())),
+ this->FileName);
+ return;
+ }
+ if (!this->processCallGraphSection(MapOrErr->begin()->first) ||
+ this->FuncCGInfos.empty())
+ return;
+
+ std::vector<Relocation<ELFT>> Relocations;
+ const Elf_Shdr *RelocSymTab = nullptr;
+ if (this->Obj.getHeader().e_type == ELF::ET_REL) {
+ const Elf_Shdr *CGRelSection = MapOrErr->front().second;
+ if (CGRelSection) {
+ this->forEachRelocationDo(
+ *CGRelSection, [&](const Relocation<ELFT> &R, unsigned Ndx,
+ const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {
+ RelocSymTab = SymTab;
+ Relocations.push_back(R);
+ });
+ llvm::stable_sort(Relocations, [](const auto &LHS, const auto &RHS) {
+ return LHS.Offset < RHS.Offset;
+ });
+ }
+ }
+
+ auto GetFunctionNames = [&](uint64_t FuncAddr) {
+ SmallVector<uint32_t> FuncSymIndexes =
+ this->getSymbolIndexesForFunctionAddress(FuncAddr, std::nullopt);
+ SmallVector<std::string> FuncSymNames;
+ FuncSymNames.reserve(FuncSymIndexes.size());
+ for (uint32_t Index : FuncSymIndexes)
+ FuncSymNames.push_back(this->getStaticSymbolName(Index));
+ return FuncSymNames;
+ };
+
+ auto PrintNonRelocatableFuncSymbol = [&](uint64_t FuncEntryPC) {
+ SmallVector<std::string> FuncSymNames = GetFunctionNames(FuncEntryPC);
+ if (!FuncSymNames.empty())
+ W.printList("Names", FuncSymNames);
+ W.printHex("Address", FuncEntryPC);
+ };
+
+ auto PrintRelocatableFuncSymbol = [&](uint64_t RelocOffset) {
+ auto R = llvm::find_if(Relocations, [&](const Relocation<ELFT> &R) {
+ return R.Offset == RelocOffset;
+ });
+ if (R == Relocations.end()) {
+ this->reportUniqueWarning("unknown relocation at offset " +
+ Twine(RelocOffset));
+ return;
+ }
+ Expected<RelSymbol<ELFT>> RelSymOrErr =
+ this->getRelocationTarget(*R, RelocSymTab);
+ if (!RelSymOrErr) {
+ this->reportUniqueWarning(RelSymOrErr.takeError());
+ return;
+ }
+ if (!RelSymOrErr->Name.empty())
+ W.printString("Name", RelSymOrErr->Name);
+ };
+
+ auto PrintFunc = [&](uint64_t FuncPC) {
+ uint64_t FuncEntryPC = FuncPC;
+ // In ARM thumb mode the LSB of the function pointer is set to 1. Since this
+ // detail is unncessary in call graph reconstruction, we are clearing this
+ // bit to facilate tooling.
+ if (this->Obj.getHeader().e_machine == ELF::EM_ARM)
+ FuncEntryPC = FuncPC & ~1;
+ if (this->Obj.getHeader().e_type == ELF::ET_REL)
+ PrintRelocatableFuncSymbol(FuncEntryPC);
+ else
+ PrintNonRelocatableFuncSymbol(FuncEntryPC);
+ };
+
+ ListScope CGI(W, "CallGraph");
+ for (const auto &CGInfo : this->FuncCGInfos) {
+ DictScope D(W, "Function");
+ PrintFunc(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);
+ PrintFunc(CalleePC);
+ }
+ }
+ W.printNumber("NumIndirectTargetTypeIDs", CGInfo.IndirectTypeIDs.size());
+ SmallVector<uint64_t, 4> IndirectTypeIdsList(CGInfo.IndirectTypeIDs.begin(),
----------------
jh7370 wrote:
Nit: I think `IndirectTypeIDsList` would be more in keeping with how "IDs" is written elsewhere (e.g. see the CGInfo member).
https://github.com/llvm/llvm-project/pull/176260
More information about the llvm-commits
mailing list