LLDB mainline
VerboseTrapFrameRecognizer.cpp
Go to the documentation of this file.
2
3#include "lldb/Core/Module.h"
9
11#include "lldb/Utility/Log.h"
12
13#include "clang/CodeGen/ModuleBuilder.h"
14
15using namespace llvm;
16using namespace lldb;
17using namespace lldb_private;
18
19/// The 0th frame is the artificial inline frame generated to store
20/// the verbose_trap message. So, starting with the current parent frame,
21/// find the first frame that's not inside of the STL.
22static StackFrameSP FindMostRelevantFrame(Thread &selected_thread) {
23 // Defensive upper-bound of when we stop walking up the frames in
24 // case we somehow ended up looking at an infinite recursion.
25 const size_t max_stack_depth = 128;
26
27 // Start at parent frame.
28 size_t stack_idx = 1;
29 StackFrameSP most_relevant_frame_sp =
30 selected_thread.GetStackFrameAtIndex(stack_idx);
31
32 while (most_relevant_frame_sp && stack_idx <= max_stack_depth) {
33 auto const &sc =
34 most_relevant_frame_sp->GetSymbolContext(eSymbolContextEverything);
35 ConstString frame_name = sc.GetFunctionName();
36 if (!frame_name)
37 return nullptr;
38
39 // Found a frame outside of the `std` namespace. That's the
40 // first frame in user-code that ended up triggering the
41 // verbose_trap. Hence that's the one we want to display.
42 if (!frame_name.GetStringRef().starts_with("std::"))
43 return most_relevant_frame_sp;
44
45 ++stack_idx;
46 most_relevant_frame_sp = selected_thread.GetStackFrameAtIndex(stack_idx);
47 }
48
49 return nullptr;
50}
51
53 StackFrameSP most_relevant_frame_sp, std::string stop_desc)
54 : m_most_relevant_frame(most_relevant_frame_sp) {
55 m_stop_desc = std::move(stop_desc);
56}
57
60 if (frame_sp->GetFrameIndex())
61 return {};
62
63 ThreadSP thread_sp = frame_sp->GetThread();
64 ProcessSP process_sp = thread_sp->GetProcess();
65
66 StackFrameSP most_relevant_frame_sp = FindMostRelevantFrame(*thread_sp);
67
68 if (!most_relevant_frame_sp) {
71 log,
72 "Failed to find most relevant frame: Hit unwinding bound (1 frame)!");
73 return {};
74 }
75
76 SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
77
78 if (!sc.block)
79 return {};
80
81 // The runtime error is set as the function name in the inlined function info
82 // of frame #0 by the compiler
83 const InlineFunctionInfo *inline_info = nullptr;
84 Block *inline_block = sc.block->GetContainingInlinedBlock();
85
86 if (!inline_block)
87 return {};
88
89 inline_info = sc.block->GetInlinedFunctionInfo();
90
91 if (!inline_info)
92 return {};
93
94 auto func_name = inline_info->GetName().GetStringRef();
95 if (func_name.empty())
96 return {};
97
98 static auto trap_regex =
99 llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str());
100 SmallVector<llvm::StringRef, 3> matches;
101 std::string regex_err_msg;
102 if (!trap_regex.match(func_name, &matches, &regex_err_msg)) {
104 "Failed to parse match trap regex for '%s': %s", func_name.data(),
105 regex_err_msg.c_str());
106
107 return {};
108 }
109
110 // For `__clang_trap_msg$category$message$` we expect 3 matches:
111 // 1. entire string
112 // 2. category
113 // 3. message
114 if (matches.size() != 3) {
116 "Unexpected function name format. Expected '<trap prefix>$<trap "
117 "category>$<trap message>'$ but got: '%s'.",
118 func_name.data());
119
120 return {};
121 }
122
123 auto category = matches[1];
124 auto message = matches[2];
125
126 std::string stop_reason =
127 category.empty() ? "<empty category>" : category.str();
128 if (!message.empty()) {
129 stop_reason += ": ";
130 stop_reason += message.str();
131 }
132
133 return std::make_shared<VerboseTrapRecognizedStackFrame>(
134 most_relevant_frame_sp, std::move(stop_reason));
135}
136
139}
140
141namespace lldb_private {
142
144 RegularExpressionSP module_regex_sp = nullptr;
145 auto symbol_regex_sp = std::make_shared<RegularExpression>(
146 llvm::formatv("^{0}", ClangTrapPrefix).str());
147
148 StackFrameRecognizerSP srf_recognizer_sp =
149 std::make_shared<VerboseTrapFrameRecognizer>();
150
152 srf_recognizer_sp, module_regex_sp, symbol_regex_sp,
154}
155
156} // namespace lldb_private
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:369
#define LLDB_LOGF(log,...)
Definition: Log.h:376
static StackFrameSP FindMostRelevantFrame(Thread &selected_thread)
The 0th frame is the artificial inline frame generated to store the verbose_trap message.
A class that describes a single lexical block.
Definition: Block.h:41
Block * GetContainingInlinedBlock()
Get the inlined block that contains this block.
Definition: Block.cpp:201
const InlineFunctionInfo * GetInlinedFunctionInfo() const
Get const accessor for any inlined function information.
Definition: Block.h:266
A uniqued constant string class.
Definition: ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
A class that describes information for an inlined function.
Definition: Function.h:125
ConstString GetName() const
Definition: Function.cpp:96
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1246
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, Mangled::NamePreference symbol_mangling, bool first_instruction_only=true)
Add a new recognizer that triggers on a given symbol name.
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:34
Block * block
The Block for a given query.
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition: Target.h:1487
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:408
lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame) override
VerboseTrapRecognizedStackFrame(lldb::StackFrameSP most_relevant_frame_sp, std::string stop_desc)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
void RegisterVerboseTrapFrameRecognizer(Process &process)
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::RecognizedStackFrame > RecognizedStackFrameSP
Definition: lldb-forward.h:403
std::shared_ptr< lldb_private::Thread > ThreadSP
Definition: lldb-forward.h:450
std::shared_ptr< lldb_private::RegularExpression > RegularExpressionSP
Definition: lldb-forward.h:397
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
std::shared_ptr< lldb_private::StackFrameRecognizer > StackFrameRecognizerSP
Definition: lldb-forward.h:428
Definition: Debugger.h:54