[llvm-branch-commits] [llvm] [llvm-readobj][ELF] Print call graph callees in section order (PR #230649)
Paul Kirth via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 12 10:49:32 PDT 2026
================
@@ -8410,34 +8419,39 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCallGraphInfo() {
W.printString("Name", RelSymOrErr->Name);
};
- auto PrintFunc = [&](uint64_t FuncPC) {
- // In a relocatable object file, FuncPC is the offset of the address
- // field, which is used to look up the relocation that applies to it.
- if (this->Obj.getHeader().e_type == ELF::ET_REL) {
- PrintRelocatableFuncSymbol(FuncPC);
+ auto PrintFunc = [&](const CallGraphFunc &Func) {
+ // In a relocatable object file, the address field holds a placeholder.
+ // Its offset is used to look up the relocation that applies to it.
+ if (IsRelocatable) {
+ PrintRelocatableFuncSymbol(Func.FieldOffset);
return;
}
- uint64_t FuncEntryPC = FuncPC;
+ uint64_t FuncEntryPC = Func.FieldValue;
// In ARM thumb mode the LSB of the function pointer is set to 1. Since
// this detail is unnecessary in call graph reconstruction, we are
// clearing this bit to facilitate tooling.
if (this->Obj.getHeader().e_machine == ELF::EM_ARM)
- FuncEntryPC = FuncPC & ~1;
+ FuncEntryPC &= ~1;
PrintNonRelocatableFuncSymbol(FuncEntryPC);
};
if (!CGI)
CGI = std::make_unique<ListScope>(W, "CallGraph");
for (const FunctionCallGraphInfo &CGInfo : FuncCGInfos) {
DictScope D(W, "Function");
- PrintFunc(CGInfo.FunctionAddress);
+ PrintFunc(CGInfo.Entry);
W.printNumber("Version", CGInfo.FormatVersionNumber);
W.printBoolean("IsIndirectTarget", CGInfo.IsIndirectTarget);
W.printHex("TypeID", CGInfo.FunctionTypeID);
{
ListScope DCs(W, "DirectCallees");
- for (uint64_t CalleePC : CGInfo.DirectCallees) {
+ // In a linked file, different callees can end up at the same address,
+ // e.g. after identical code folding. List each address once.
+ SmallSet<uint64_t, 4> SeenCallees;
+ for (const CallGraphFunc &Callee : CGInfo.DirectCallees) {
+ if (!IsRelocatable && !SeenCallees.insert(Callee.FieldValue).second)
+ continue;
----------------
ilovepi wrote:
`sort` and then `unique + erase` is also an option. Not sure if one is particularly better than the other. I guess it depends on if you want to minimize allocations or iteration. typically I try to minimize allocation, since it also requires copying, but YMMV.
https://github.com/llvm/llvm-project/pull/230649
More information about the llvm-branch-commits
mailing list