15
15
16
16
#include " llvm/Transforms/Utils/Debugify.h"
17
17
#include " llvm/ADT/BitVector.h"
18
+ #include " llvm/ADT/DenseMap.h"
19
+ #include " llvm/ADT/DenseSet.h"
18
20
#include " llvm/ADT/StringExtras.h"
21
+ #include " llvm/Config/config.h"
19
22
#include " llvm/IR/DIBuilder.h"
20
23
#include " llvm/IR/DebugInfo.h"
21
24
#include " llvm/IR/InstIterator.h"
28
31
#include " llvm/Support/FileSystem.h"
29
32
#include " llvm/Support/JSON.h"
30
33
#include < optional>
34
+ #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
35
+ // We need the Signals header to operate on stacktraces if we're using DebugLoc
36
+ // origin-tracking.
37
+ #include " llvm/Support/Signals.h"
38
+ #endif
31
39
32
40
#define DEBUG_TYPE " debugify"
33
41
@@ -59,6 +67,52 @@ cl::opt<Level> DebugifyLevel(
59
67
60
68
raw_ostream &dbg () { return Quiet ? nulls () : errs (); }
61
69
70
+ #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
71
+ // These maps refer to addresses in this instance of LLVM, so we can reuse them
72
+ // everywhere - therefore, we store them at file scope.
73
+ static DenseMap<void *, SmallVector<std::string, 0 >> SymbolizedAddrs;
74
+ static DenseSet<void *> UnsymbolizedAddrs;
75
+
76
+ std::string symbolizeStackTrace (const Instruction *I) {
77
+ // We flush the set of unsymbolized addresses at the latest possible moment,
78
+ // i.e. now.
79
+ if (!UnsymbolizedAddrs.empty ()) {
80
+ sys::symbolizeAddresses (UnsymbolizedAddrs, SymbolizedAddrs);
81
+ UnsymbolizedAddrs.clear ();
82
+ }
83
+ auto OriginStackTraces = I->getDebugLoc ().getOriginStackTraces ();
84
+ std::string Result;
85
+ raw_string_ostream OS (Result);
86
+ for (size_t TraceIdx = 0 ; TraceIdx < OriginStackTraces.size (); ++TraceIdx) {
87
+ if (TraceIdx != 0 )
88
+ OS << " ========================================\n " ;
89
+ auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
90
+ unsigned VirtualFrameNo = 0 ;
91
+ for (int Frame = 0 ; Frame < Depth; ++Frame) {
92
+ assert (SymbolizedAddrs.contains (StackTrace[Frame]) &&
93
+ " Expected each address to have been symbolized." );
94
+ for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
95
+ OS << right_justify (formatv (" #{0}" , VirtualFrameNo++).str (), std::log10 (Depth) + 2 )
96
+ << ' ' << SymbolizedFrame << ' \n ' ;
97
+ }
98
+ }
99
+ }
100
+ return Result;
101
+ }
102
+ void collectStackAddresses (Instruction &I) {
103
+ auto &OriginStackTraces = I.getDebugLoc ().getOriginStackTraces ();
104
+ for (auto &[Depth, StackTrace] : OriginStackTraces) {
105
+ for (int Frame = 0 ; Frame < Depth; ++Frame) {
106
+ void *Addr = StackTrace[Frame];
107
+ if (!SymbolizedAddrs.contains (Addr))
108
+ UnsymbolizedAddrs.insert (Addr);
109
+ }
110
+ }
111
+ }
112
+ #else
113
+ void collectStackAddresses (Instruction &I) {}
114
+ #endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
115
+
62
116
uint64_t getAllocSizeInBits (Module &M, Type *Ty) {
63
117
return Ty->isSized () ? M.getDataLayout ().getTypeAllocSizeInBits (Ty) : 0 ;
64
118
}
@@ -375,6 +429,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
375
429
LLVM_DEBUG (dbgs () << " Collecting info for inst: " << I << ' \n ' );
376
430
DebugInfoBeforePass.InstToDelete .insert ({&I, &I});
377
431
432
+ // Track the addresses to symbolize, if the feature is enabled.
433
+ collectStackAddresses (I);
378
434
DebugInfoBeforePass.DILocations .insert ({&I, hasLoc (I)});
379
435
}
380
436
}
@@ -450,14 +506,23 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
450
506
auto BBName = BB->hasName () ? BB->getName () : " no-name" ;
451
507
auto InstName = Instruction::getOpcodeName (Instr->getOpcode ());
452
508
509
+ auto CreateJSONBugEntry = [&](const char *Action) {
510
+ Bugs.push_back (llvm::json::Object ({
511
+ {" metadata" , " DILocation" },
512
+ {" fn-name" , FnName.str ()},
513
+ {" bb-name" , BBName.str ()},
514
+ {" instr" , InstName},
515
+ {" action" , Action},
516
+ #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
517
+ {" origin" , symbolizeStackTrace (Instr)},
518
+ #endif
519
+ }));
520
+ };
521
+
453
522
auto InstrIt = DILocsBefore.find (Instr);
454
523
if (InstrIt == DILocsBefore.end ()) {
455
524
if (ShouldWriteIntoJSON)
456
- Bugs.push_back (llvm::json::Object ({{" metadata" , " DILocation" },
457
- {" fn-name" , FnName.str ()},
458
- {" bb-name" , BBName.str ()},
459
- {" instr" , InstName},
460
- {" action" , " not-generate" }}));
525
+ CreateJSONBugEntry (" not-generate" );
461
526
else
462
527
dbg () << " WARNING: " << NameOfWrappedPass
463
528
<< " did not generate DILocation for " << *Instr
@@ -470,11 +535,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
470
535
// If the instr had the !dbg attached before the pass, consider it as
471
536
// a debug info issue.
472
537
if (ShouldWriteIntoJSON)
473
- Bugs.push_back (llvm::json::Object ({{" metadata" , " DILocation" },
474
- {" fn-name" , FnName.str ()},
475
- {" bb-name" , BBName.str ()},
476
- {" instr" , InstName},
477
- {" action" , " drop" }}));
538
+ CreateJSONBugEntry (" drop" );
478
539
else
479
540
dbg () << " WARNING: " << NameOfWrappedPass << " dropped DILocation of "
480
541
<< *Instr << " (BB: " << BBName << " , Fn: " << FnName
@@ -612,6 +673,8 @@ bool llvm::checkDebugInfoMetadata(Module &M,
612
673
613
674
LLVM_DEBUG (dbgs () << " Collecting info for inst: " << I << ' \n ' );
614
675
676
+ // Track the addresses to symbolize, if the feature is enabled.
677
+ collectStackAddresses (I);
615
678
DebugInfoAfterPass.DILocations .insert ({&I, hasLoc (I)});
616
679
}
617
680
}
0 commit comments