xref: /freebsd/contrib/llvm-project/lldb/source/Target/VerboseTrapFrameRecognizer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 #include "lldb/Target/VerboseTrapFrameRecognizer.h"
2 
3 #include "lldb/Core/Module.h"
4 #include "lldb/Symbol/Function.h"
5 #include "lldb/Symbol/SymbolContext.h"
6 #include "lldb/Target/Process.h"
7 #include "lldb/Target/StackFrameRecognizer.h"
8 #include "lldb/Target/Target.h"
9 
10 #include "lldb/Utility/LLDBLog.h"
11 #include "lldb/Utility/Log.h"
12 
13 #include "clang/CodeGen/ModuleBuilder.h"
14 
15 using namespace llvm;
16 using namespace lldb;
17 using namespace lldb_private;
18 
VerboseTrapRecognizedStackFrame(StackFrameSP most_relevant_frame_sp,std::string stop_desc)19 VerboseTrapRecognizedStackFrame::VerboseTrapRecognizedStackFrame(
20     StackFrameSP most_relevant_frame_sp, std::string stop_desc)
21     : m_most_relevant_frame(most_relevant_frame_sp) {
22   m_stop_desc = std::move(stop_desc);
23 }
24 
25 lldb::RecognizedStackFrameSP
RecognizeFrame(lldb::StackFrameSP frame_sp)26 VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
27   if (frame_sp->GetFrameIndex())
28     return {};
29 
30   ThreadSP thread_sp = frame_sp->GetThread();
31   ProcessSP process_sp = thread_sp->GetProcess();
32 
33   StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1);
34 
35   if (!most_relevant_frame_sp) {
36     Log *log = GetLog(LLDBLog::Unwind);
37     LLDB_LOG(
38         log,
39         "Failed to find most relevant frame: Hit unwinding bound (1 frame)!");
40     return {};
41   }
42 
43   SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
44 
45   if (!sc.block)
46     return {};
47 
48   // The runtime error is set as the function name in the inlined function info
49   // of frame #0 by the compiler
50   const InlineFunctionInfo *inline_info = nullptr;
51   Block *inline_block = sc.block->GetContainingInlinedBlock();
52 
53   if (!inline_block)
54     return {};
55 
56   inline_info = sc.block->GetInlinedFunctionInfo();
57 
58   if (!inline_info)
59     return {};
60 
61   auto func_name = inline_info->GetName().GetStringRef();
62   if (func_name.empty())
63     return {};
64 
65   static auto trap_regex =
66       llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str());
67   SmallVector<llvm::StringRef, 3> matches;
68   std::string regex_err_msg;
69   if (!trap_regex.match(func_name, &matches, &regex_err_msg)) {
70     LLDB_LOGF(GetLog(LLDBLog::Unwind),
71               "Failed to parse match trap regex for '%s': %s", func_name.data(),
72               regex_err_msg.c_str());
73 
74     return {};
75   }
76 
77   // For `__clang_trap_msg$category$message$` we expect 3 matches:
78   // 1. entire string
79   // 2. category
80   // 3. message
81   if (matches.size() != 3) {
82     LLDB_LOGF(GetLog(LLDBLog::Unwind),
83               "Unexpected function name format. Expected '<trap prefix>$<trap "
84               "category>$<trap message>'$ but got: '%s'.",
85               func_name.data());
86 
87     return {};
88   }
89 
90   auto category = matches[1];
91   auto message = matches[2];
92 
93   std::string stop_reason =
94       category.empty() ? "<empty category>" : category.str();
95   if (!message.empty()) {
96     stop_reason += ": ";
97     stop_reason += message.str();
98   }
99 
100   return std::make_shared<VerboseTrapRecognizedStackFrame>(
101       most_relevant_frame_sp, std::move(stop_reason));
102 }
103 
GetMostRelevantFrame()104 lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() {
105   return m_most_relevant_frame;
106 }
107 
108 namespace lldb_private {
109 
RegisterVerboseTrapFrameRecognizer(Process & process)110 void RegisterVerboseTrapFrameRecognizer(Process &process) {
111   RegularExpressionSP module_regex_sp = nullptr;
112   auto symbol_regex_sp = std::make_shared<RegularExpression>(
113       llvm::formatv("^{0}", ClangTrapPrefix).str());
114 
115   StackFrameRecognizerSP srf_recognizer_sp =
116       std::make_shared<VerboseTrapFrameRecognizer>();
117 
118   process.GetTarget().GetFrameRecognizerManager().AddRecognizer(
119       srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
120 }
121 
122 } // namespace lldb_private
123