Skip to content

Commit 5b6bb00

Browse files
committed
Simplify readelf output.
1 parent 5b504fc commit 5b6bb00

File tree

1 file changed

+81
-148
lines changed

1 file changed

+81
-148
lines changed

llvm/tools/llvm-readobj/ELFDumper.cpp

Lines changed: 81 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,11 @@ enum class FunctionKind : uint64_t {
203203

204204
// Per-function call graph information.
205205
template <typename AddrType> struct FunctionCallgraphInfoImpl {
206+
uint64_t FormatVersionNumber;
206207
FunctionKind Kind;
208+
uint64_t FunctionTypeId; // Only if Kind == FunctionKind::INDIRECT_TARGET_KNOWN_TID
209+
DenseMap<AddrType, uint64_t> IndirectCallsites;
207210
SmallSet<AddrType, 4> DirectCallees;
208-
SmallVector<AddrType> IndirectCallsites;
209211
};
210212

211213
namespace {
@@ -464,12 +466,11 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
464466
// Callgraph - Main data structure to maintain per function callgraph
465467
// information.
466468
MapVector<typename ELFT::uint, FunctionCallgraphInfo> FuncCGInfo;
467-
// Callgraph - 64 bit type id mapped to indirect callsites whose potential
468-
// callee(s) should be of given type id.
469-
MapVector<uint64_t, SmallVector<typename ELFT::uint>> TypeIdToIndirCallSites;
470-
// Callgraph - 64 bit type id mapped to entry PC addresses of functions which
471-
// are of the given type id.
472-
MapVector<uint64_t, SmallVector<typename ELFT::uint>> TypeIdToIndirTargets;
469+
470+
// // Callgraph - 64 bit type id mapped to entry PC addresses of functions which
471+
// // are of the given type id.
472+
// MapVector<uint64_t, SmallVector<typename ELFT::uint>> TypeIdToIndirTargets;
473+
473474
// Callgraph - Read callgraph section and process its contents to populate
474475
// Callgraph related data structures which will be used to dump callgraph
475476
// info. Returns false if there is no .callgraph section in the input file.
@@ -5384,6 +5385,13 @@ template <class ELFT> bool ELFDumper<ELFT>::processCallGraphSection() {
53845385
reportError(std::move(DuplicatePcErr), "Duplicate call graph entry");
53855386
}
53865387

5388+
using FunctionCallgraphInfo =
5389+
::FunctionCallgraphInfoImpl<typename ELFT::uint>;
5390+
5391+
// Create a new entry for this function.
5392+
FunctionCallgraphInfo CGInfo;
5393+
CGInfo.FormatVersionNumber = FormatVersionNumber;
5394+
53875395
// Read function kind.
53885396
uint64_t KindVal = Data.getU64(&Offset, &CGSectionErr);
53895397
if (CGSectionErr)
@@ -5396,26 +5404,20 @@ template <class ELFT> bool ELFDumper<ELFT>::processCallGraphSection() {
53965404
}
53975405

53985406
FunctionKind Kind = static_cast<FunctionKind>(KindVal);
5407+
CGInfo.Kind = Kind;
53995408
if (Kind == FunctionKind::INDIRECT_TARGET_KNOWN_TID) {
54005409
// Read type id if this function is an indirect call target.
54015410
uint64_t TypeId = Data.getU64(&Offset, &CGSectionErr);
54025411
if (CGSectionErr)
54035412
PrintMalformedError(CGSectionErr, Twine::utohexstr(FuncAddr),
54045413
"indirect type id");
5405-
TypeIdToIndirTargets[TypeId].push_back(FuncAddr);
5414+
CGInfo.FunctionTypeId = TypeId;
54065415
}
54075416
if (Kind == FunctionKind::INDIRECT_TARGET_UNKNOWN_TID)
54085417
UnknownCount++;
54095418
if (Kind == FunctionKind::NOT_LISTED)
54105419
NotListedCount++;
54115420

5412-
using FunctionCallgraphInfo =
5413-
::FunctionCallgraphInfoImpl<typename ELFT::uint>;
5414-
5415-
// Create a new entry for this function.
5416-
FunctionCallgraphInfo CGInfo;
5417-
CGInfo.Kind = Kind;
5418-
54195421
// Read number of indirect call sites for this function.
54205422
uint64_t NumIndirectCallsites = Data.getU64(&Offset, &CGSectionErr);
54215423
if (CGSectionErr)
@@ -5431,9 +5433,8 @@ template <class ELFT> bool ELFDumper<ELFT>::processCallGraphSection() {
54315433
Data.getUnsigned(&Offset, sizeof(CallSitePc), &CGSectionErr);
54325434
if (CGSectionErr)
54335435
PrintMalformedError(CGSectionErr, Twine::utohexstr(FuncAddr),
5434-
"indirect callsite PC");
5435-
TypeIdToIndirCallSites[TypeId].push_back(CallSitePc);
5436-
CGInfo.IndirectCallsites.push_back(CallSitePc);
5436+
"indirect callsite PC");
5437+
CGInfo.IndirectCallsites.try_emplace(CallSitePc, TypeId);
54375438
}
54385439

54395440
// Read number of direct call sites for this function.
@@ -5466,74 +5467,52 @@ template <class ELFT> bool ELFDumper<ELFT>::processCallGraphSection() {
54665467
return true;
54675468
}
54685469

5470+
static StringRef GetFuntionKindString(FunctionKind Kind) {
5471+
switch(Kind) {
5472+
case FunctionKind::NOT_INDIRECT_TARGET:
5473+
return "NOT_INDIRECT_TARGET";
5474+
case FunctionKind::INDIRECT_TARGET_UNKNOWN_TID:
5475+
return "INDIRECT_TARGET_UNKNOWN_TID";
5476+
case FunctionKind::INDIRECT_TARGET_KNOWN_TID:
5477+
return "INDIRECT_TARGET_KNOWN_TID";
5478+
case FunctionKind::NOT_LISTED:
5479+
return "NOT_LISTED";
5480+
}
5481+
llvm_unreachable("Unknown FunctionKind.");
5482+
}
5483+
54695484
template <class ELFT> void GNUELFDumper<ELFT>::printCallGraphInfo() {
54705485
if (!this->processCallGraphSection())
54715486
return;
5472-
5473-
// Print indirect targets
5474-
OS << "\nINDIRECT TARGET TYPES (TYPEID [FUNC_ADDR,])";
5475-
5476-
// Print indirect targets with unknown type.
5477-
// For completeness, functions for which the call graph section does not
5478-
// provide information are included.
5479-
bool printedHeader = false;
5487+
using FunctionCallgraphInfo =
5488+
::FunctionCallgraphInfoImpl<typename ELFT::uint>;
54805489
for (const auto &El : this->FuncCGInfo) {
5481-
FunctionKind FuncKind = El.second.Kind;
5482-
if (FuncKind == FunctionKind::NOT_LISTED ||
5483-
FuncKind == FunctionKind::INDIRECT_TARGET_UNKNOWN_TID) {
5484-
if (!printedHeader) {
5485-
OS << "\nUNKNOWN";
5486-
printedHeader = true;
5490+
typename ELFT::uint FuncEntryPc = El.first;
5491+
FunctionCallgraphInfo CGInfo = El.second;
5492+
OS << "Function PC:: " << format("%lx", FuncEntryPc); // TODO: Print function name
5493+
OS << "\nFormatVersionNumber:: " << CGInfo.FormatVersionNumber;
5494+
OS << "\nFunction Kind:: " << GetFuntionKindString(CGInfo.Kind);
5495+
if (CGInfo.Kind == FunctionKind::INDIRECT_TARGET_KNOWN_TID)
5496+
OS << "\nFunction Type ID:: " << CGInfo.FunctionTypeId;
5497+
OS << "\nIndirect callee count:: " << CGInfo.IndirectCallsites.size();
5498+
if(CGInfo.IndirectCallsites.size() > 0) {
5499+
OS << "\n{";
5500+
for (auto &[IndirCallSitePc, TypeId] : CGInfo.IndirectCallsites) {
5501+
OS << "\ncallsite: " << format("%lx", IndirCallSitePc);
5502+
OS << "\ncalleeTypeId: " << format("%lx", TypeId);
5503+
}
5504+
OS << "\n}";
54875505
}
5488-
uint64_t FuncEntryPc = El.first;
5489-
OS << " " << format("%lx", FuncEntryPc);
5490-
}
5491-
}
5492-
// Print indirect targets to type id mapping.
5493-
for (const auto &El : this->TypeIdToIndirTargets) {
5494-
uint64_t TypeId = El.first;
5495-
OS << "\n" << format("%lx", TypeId);
5496-
for (uint64_t IndirTargetPc : El.second)
5497-
OS << " " << format("%lx", IndirTargetPc);
5498-
}
5499-
5500-
// Print indirect calls to type id mapping. Any indirect call without a
5501-
// type id can be deduced by comparing this list to indirect call sites
5502-
// list.
5503-
OS << "\n\nINDIRECT CALL TYPES (TYPEID [CALL_SITE_ADDR,])";
5504-
for (const auto &El : this->TypeIdToIndirCallSites) {
5505-
uint64_t TypeId = El.first;
5506-
OS << "\n" << format("%lx", TypeId);
5507-
for (uint64_t IndirCallSitePc : El.second)
5508-
OS << " " << format("%lx", IndirCallSitePc);
5509-
}
5510-
5511-
// Print function entry to indirect call site addresses mapping from disasm.
5512-
OS << "\n\nINDIRECT CALL SITES (CALLER_ADDR [CALL_SITE_ADDR,])";
5513-
for (const auto &El : this->FuncCGInfo) {
5514-
auto CallerPc = El.first;
5515-
auto FuncIndirCallSites = El.second.IndirectCallsites;
5516-
if (!FuncIndirCallSites.empty()) {
5517-
OS << "\n" << format("%lx", CallerPc);
5518-
for (auto IndirCallSitePc : FuncIndirCallSites)
5519-
OS << " " << format("%lx", IndirCallSitePc);
5520-
}
5521-
}
5522-
5523-
// Print function entry to direct call site and target function entry
5524-
// addresses mapping from disasm.
5525-
OS << "\n\nDIRECT CALL SITES (CALLER_ADDR [(CALL_SITE_ADDR, TARGET_ADDR),])";
5526-
for (const auto &El : this->FuncCGInfo) {
5527-
auto CallerPc = El.first;
5528-
auto FuncDirCallSites = El.second.DirectCallees;
5529-
if (!FuncDirCallSites.empty()) {
5530-
OS << "\n" << format("%lx", CallerPc);
5531-
for (typename ELFT::uint Callee : FuncDirCallSites) {
5532-
OS << " " << format("%lx", Callee);
5506+
OS << "\nDirect callee count:: " << CGInfo.DirectCallees.size();
5507+
if(CGInfo.DirectCallees.size() > 0) {
5508+
OS << "\n{";
5509+
for (auto CalleePC : CGInfo.DirectCallees) {
5510+
OS << "\n" << format("%lx", CalleePC);
5511+
}
5512+
OS << "\n}";
55335513
}
5534-
}
5535-
}
5536-
OS << "\n";
5514+
OS << "\n";
5515+
}
55375516
}
55385517

55395518
template <class ELFT>
@@ -8372,76 +8351,30 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCallGraphInfo() {
83728351
return;
83738352

83748353
DictScope D(this->W, "callgraph_info");
8375-
// Use llvm-symbolizer to get function name and address instead.
8376-
// stack-sizes embeds function mangled name directly in JSON.
8377-
// {
8378-
// ListScope A(this->W, "functions");
8379-
// for (auto const &F : this->FuncCGInfo) {
8380-
// DictScope D(this->W);
8381-
// this->W.printHex("function_address", F.first);
8382-
// }
8383-
// }
8384-
8385-
{
8386-
SmallVector<uint64_t, 4> Unknowns;
8387-
for (const auto &El : this->FuncCGInfo) {
8388-
FunctionKind FuncKind = El.second.Kind;
8389-
if (FuncKind == FunctionKind::NOT_LISTED ||
8390-
FuncKind == FunctionKind::INDIRECT_TARGET_UNKNOWN_TID) {
8391-
uint64_t FuncEntryPc = El.first;
8392-
Unknowns.emplace_back(FuncEntryPc);
8393-
}
8394-
}
8395-
if (!Unknowns.empty())
8396-
this->W.printHexList("unknown_target_types", Unknowns);
8397-
}
8398-
8399-
{
8400-
ListScope ITT(this->W, "indirect_target_types");
8401-
for (auto const &T : this->TypeIdToIndirTargets) {
8402-
for (auto const &Target : T.second) {
8403-
DictScope D(this->W);
8404-
this->W.printHex("function_address", Target);
8405-
this->W.printHex("type_id", T.first);
8406-
}
8407-
}
8408-
}
84098354

8410-
{
8411-
ListScope DCT(this->W, "direct_call_sites");
8412-
for (auto const &F : this->FuncCGInfo) {
8413-
if (F.second.DirectCallees.empty())
8414-
continue;
8415-
DictScope D(this->W);
8416-
this->W.printHex("caller", F.first);
8417-
ListScope CT(this->W, "call_sites");
8418-
for (auto const &CS : F.second.DirectCallees) {
8419-
DictScope D(this->W);
8420-
this->W.printHex("callee", CS);
8421-
}
8422-
}
8423-
}
8424-
8425-
{
8426-
ListScope ICT(this->W, "indirect_call_sites");
8427-
for (auto const &F : this->FuncCGInfo) {
8428-
if (F.second.IndirectCallsites.empty())
8429-
continue;
8430-
DictScope D(this->W);
8431-
this->W.printHex("caller", F.first);
8432-
this->W.printHexList("call_sites", F.second.IndirectCallsites);
8433-
}
8434-
}
8435-
8436-
{
8437-
ListScope ICT(this->W, "indirect_call_types");
8438-
for (auto const &T : this->TypeIdToIndirCallSites) {
8439-
for (auto const &CS : T.second) {
8440-
DictScope D(this->W);
8441-
this->W.printHex("call_site", CS);
8442-
this->W.printHex("type_id", T.first);
8355+
using FunctionCallgraphInfo =
8356+
::FunctionCallgraphInfoImpl<typename ELFT::uint>;
8357+
for (const auto &El : this->FuncCGInfo) {
8358+
typename ELFT::uint FuncEntryPc = El.first;
8359+
FunctionCallgraphInfo CGInfo = El.second;
8360+
std::string FuncPCStr = std::to_string(FuncEntryPc);
8361+
DictScope FuncScope(this->W, FuncPCStr); // TODO: Print function name
8362+
this->W.printNumber("FormatVersionNumber", CGInfo.FormatVersionNumber);
8363+
this->W.printNumber("Kind", (uint64_t)CGInfo.Kind); // TODO: Print Function Kind String GetFuntionKindString(El.second.Kind);
8364+
if (CGInfo.Kind == FunctionKind::INDIRECT_TARGET_KNOWN_TID)
8365+
this->W.printNumber("TypeId", CGInfo.FunctionTypeId);
8366+
this->W.printNumber("NumIndirectCallSites", CGInfo.IndirectCallsites.size());
8367+
if(CGInfo.IndirectCallsites.size() > 0) {
8368+
ListScope ICT(this->W, "indirect_call_sites");
8369+
for (auto &[IndirCallSitePc, TypeId] : CGInfo.IndirectCallsites) {
8370+
DictScope IDC(this->W);
8371+
this->W.printHex("callsite", IndirCallSitePc);
8372+
this->W.printHex("type_id", TypeId);
8373+
}
84438374
}
8444-
}
8375+
this->W.printNumber("NumDirectCallSites", CGInfo.DirectCallees.size());
8376+
if(CGInfo.DirectCallees.size() > 0)
8377+
this->W.printHexList("direct_callees", CGInfo.DirectCallees);
84458378
}
84468379
}
84478380

0 commit comments

Comments
 (0)