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