aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Debugify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/Debugify.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Debugify.cpp84
1 files changed, 74 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp
index 5f70bc4..a1f030a 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -16,8 +16,10 @@
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -28,6 +30,11 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
#include <optional>
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
#define DEBUG_TYPE "debugify"
@@ -59,6 +66,54 @@ cl::opt<Level> DebugifyLevel(
raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in the current LLVM process, so we can reuse
+// them everywhere - therefore, we store them at file scope.
+static SymbolizedAddressMap SymbolizedAddrs;
+static AddressSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+ // We flush the set of unsymbolized addresses at the latest possible moment,
+ // i.e. now.
+ if (!UnsymbolizedAddrs.empty()) {
+ sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+ UnsymbolizedAddrs.clear();
+ }
+ const DbgLocOrigin::StackTracesTy &OriginStackTraces =
+ I->getDebugLoc().getOriginStackTraces();
+ std::string Result;
+ raw_string_ostream OS(Result);
+ for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+ if (TraceIdx != 0)
+ OS << "========================================\n";
+ auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+ unsigned VirtualFrameNo = 0;
+ for (int Frame = 0; Frame < Depth; ++Frame) {
+ assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+ for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+ OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(),
+ std::log10(Depth) + 2)
+ << ' ' << SymbolizedFrame << '\n';
+ }
+ }
+ }
+ return Result;
+}
+void collectStackAddresses(Instruction &I) {
+ auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+ for (auto &[Depth, StackTrace] : OriginStackTraces) {
+ for (int Frame = 0; Frame < Depth; ++Frame) {
+ void *Addr = StackTrace[Frame];
+ if (!SymbolizedAddrs.contains(Addr))
+ UnsymbolizedAddrs.insert(Addr);
+ }
+ }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+
uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
}
@@ -375,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
DebugInfoBeforePass.InstToDelete.insert({&I, &I});
+ // Track the addresses to symbolize, if the feature is enabled.
+ collectStackAddresses(I);
DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
}
}
@@ -450,14 +507,23 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
auto BBName = BB->hasName() ? BB->getName() : "no-name";
auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
+ auto CreateJSONBugEntry = [&](const char *Action) {
+ Bugs.push_back(llvm::json::Object({
+ {"metadata", "DILocation"},
+ {"fn-name", FnName.str()},
+ {"bb-name", BBName.str()},
+ {"instr", InstName},
+ {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+ {"origin", symbolizeStackTrace(Instr)},
+#endif
+ }));
+ };
+
auto InstrIt = DILocsBefore.find(Instr);
if (InstrIt == DILocsBefore.end()) {
if (ShouldWriteIntoJSON)
- Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
- {"fn-name", FnName.str()},
- {"bb-name", BBName.str()},
- {"instr", InstName},
- {"action", "not-generate"}}));
+ CreateJSONBugEntry("not-generate");
else
dbg() << "WARNING: " << NameOfWrappedPass
<< " did not generate DILocation for " << *Instr
@@ -470,11 +536,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
// If the instr had the !dbg attached before the pass, consider it as
// a debug info issue.
if (ShouldWriteIntoJSON)
- Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
- {"fn-name", FnName.str()},
- {"bb-name", BBName.str()},
- {"instr", InstName},
- {"action", "drop"}}));
+ CreateJSONBugEntry("drop");
else
dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of "
<< *Instr << " (BB: " << BBName << ", Fn: " << FnName
@@ -612,6 +674,8 @@ bool llvm::checkDebugInfoMetadata(Module &M,
LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
+ // Track the addresses to symbolize, if the feature is enabled.
+ collectStackAddresses(I);
DebugInfoAfterPass.DILocations.insert({&I, hasLoc(I)});
}
}