@@ -203,9 +203,11 @@ enum class FunctionKind : uint64_t {
203203
204204// Per-function call graph information.
205205template <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
211213namespace {
@@ -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+
54695484template <class ELFT > void GNUELFDumper<ELFT>::printCallGraphInfo() {
54705485 if (!this ->processCallGraphSection ())
54715486 return ;
5472-
5473- // Print indirect targets
5474- OS << " \n INDIRECT 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 << " \n UNKNOWN" ;
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 << " \n FormatVersionNumber:: " << CGInfo.FormatVersionNumber ;
5494+ OS << " \n Function Kind:: " << GetFuntionKindString (CGInfo.Kind );
5495+ if (CGInfo.Kind == FunctionKind::INDIRECT_TARGET_KNOWN_TID)
5496+ OS << " \n Function Type ID:: " << CGInfo.FunctionTypeId ;
5497+ OS << " \n Indirect callee count:: " << CGInfo.IndirectCallsites .size ();
5498+ if (CGInfo.IndirectCallsites .size () > 0 ) {
5499+ OS << " \n {" ;
5500+ for (auto &[IndirCallSitePc, TypeId] : CGInfo.IndirectCallsites ) {
5501+ OS << " \n callsite: " << format (" %lx" , IndirCallSitePc);
5502+ OS << " \n calleeTypeId: " << 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\n INDIRECT 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\n INDIRECT 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\n DIRECT 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 << " \n Direct 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
55395518template <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