Skip to content

Commit 2d7db4c

Browse files
committed
[lldb] Fix {break,watch}point command function stopping behaviour
In order to run a {break,watch}point command, lldb can resolve to the script interpreter to run an arbitrary piece of code or call into a user-provided function. To do so, we will generate a wrapping function, where we first copy lldb's internal dictionary keys into the interpreter's global dictionary, copied inline the user code before resetting the global dictionary to its previous state. However, {break,watch}point commands can optionally return a value that would tell lldb whether we should stop or not. This feature was only implemented for breakpoint commands and since we inlined the user code directly into the wrapping function, introducing an early return, that caused lldb to let the interpreter global dictionary tinted with the internal dictionary keys. This patch fixes that issue while also adding the stopping behaviour to watchpoint commands. To do so, this patch refactors the {break,watch}point command creation method, to let the lldb wrapper function generator know if the user code is a function call or a arbitrary expression. Then the wrapper generator, if the user input was a function call, the wrapper function will call the user function and save the return value into a variable. If the user input was an arbitrary expression, the wrapper will inline it into a nested function, call the nested function and save the return value into the same variable. After resetting the interpreter global dictionary to its previous state, the generated wrapper function will return the varible containing the return value. rdar://105461140 Differential Revision: https://reviews.llvm.org/D144688 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent befd447 commit 2d7db4c

File tree

12 files changed

+163
-86
lines changed

12 files changed

+163
-86
lines changed

lldb/include/lldb/Interpreter/ScriptInterpreter.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,17 +178,18 @@ class ScriptInterpreter : public PluginInterface {
178178
return error;
179179
}
180180

181-
virtual Status GenerateBreakpointCommandCallbackData(
182-
StringList &input,
183-
std::string &output,
184-
bool has_extra_args) {
181+
virtual Status GenerateBreakpointCommandCallbackData(StringList &input,
182+
std::string &output,
183+
bool has_extra_args,
184+
const bool is_callback) {
185185
Status error;
186186
error.SetErrorString("not implemented");
187187
return error;
188188
}
189189

190190
virtual bool GenerateWatchpointCommandCallbackData(StringList &input,
191-
std::string &output) {
191+
std::string &output,
192+
const bool is_callback) {
192193
return false;
193194
}
194195

@@ -354,7 +355,8 @@ class ScriptInterpreter : public PluginInterface {
354355
}
355356

356357
virtual Status GenerateFunction(const char *signature,
357-
const StringList &input) {
358+
const StringList &input,
359+
const bool is_callback) {
358360
Status error;
359361
error.SetErrorString("unimplemented");
360362
return error;
@@ -374,7 +376,8 @@ class ScriptInterpreter : public PluginInterface {
374376
const char *callback_text);
375377

376378
virtual Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
377-
const char *callback_text) {
379+
const char *callback_text,
380+
const bool is_callback) {
378381
Status error;
379382
error.SetErrorString("unimplemented");
380383
return error;
@@ -405,7 +408,8 @@ class ScriptInterpreter : public PluginInterface {
405408

406409
/// Set a one-liner as the callback for the watchpoint.
407410
virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
408-
const char *oneliner) {}
411+
const char *user_input,
412+
const bool is_callback) {}
409413

410414
virtual bool GetScriptedSummary(const char *function_name,
411415
lldb::ValueObjectSP valobj,

lldb/source/API/SBBreakpoint.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,8 @@ SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
645645
bkpt_sp->GetTarget()
646646
.GetDebugger()
647647
.GetScriptInterpreter()
648-
->SetBreakpointCommandCallback(bp_options, callback_body_text);
648+
->SetBreakpointCommandCallback(bp_options, callback_body_text,
649+
/*is_callback=*/false);
649650
sb_error.SetError(error);
650651
} else
651652
sb_error.SetErrorString("invalid breakpoint");

lldb/source/API/SBBreakpointLocation.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
263263
.GetTarget()
264264
.GetDebugger()
265265
.GetScriptInterpreter()
266-
->SetBreakpointCommandCallback(bp_options, callback_body_text);
266+
->SetBreakpointCommandCallback(bp_options, callback_body_text,
267+
/*is_callback=*/false);
267268
sb_error.SetError(error);
268269
} else
269270
sb_error.SetErrorString("invalid breakpoint");

lldb/source/API/SBBreakpointName.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,11 +593,11 @@ SBBreakpointName::SetScriptCallbackBody(const char *callback_body_text) {
593593
m_impl_up->GetTarget()->GetAPIMutex());
594594

595595
BreakpointOptions &bp_options = bp_name->GetOptions();
596-
Status error =
597-
m_impl_up->GetTarget()
598-
->GetDebugger()
599-
.GetScriptInterpreter()
600-
->SetBreakpointCommandCallback(bp_options, callback_body_text);
596+
Status error = m_impl_up->GetTarget()
597+
->GetDebugger()
598+
.GetScriptInterpreter()
599+
->SetBreakpointCommandCallback(
600+
bp_options, callback_body_text, /*is_callback=*/false);
601601
sb_error.SetError(error);
602602
if (!sb_error.Fail())
603603
UpdateName(*bp_name);

lldb/source/Commands/CommandObjectWatchpointCommand.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,17 +415,18 @@ are no syntax errors may indicate that a function was declared but never called.
415415
// Special handling for one-liner specified inline.
416416
if (m_options.m_use_one_liner) {
417417
script_interp->SetWatchpointCommandCallback(
418-
wp_options, m_options.m_one_liner.c_str());
418+
wp_options, m_options.m_one_liner.c_str(),
419+
/*is_callback=*/false);
419420
}
420421
// Special handling for using a Python function by name instead of
421422
// extending the watchpoint callback data structures, we just
422423
// automatize what the user would do manually: make their watchpoint
423424
// command be a function call
424425
else if (!m_options.m_function_name.empty()) {
425-
std::string oneliner(m_options.m_function_name);
426-
oneliner += "(frame, wp, internal_dict)";
426+
std::string function_signature = m_options.m_function_name;
427+
function_signature += "(frame, wp, internal_dict)";
427428
script_interp->SetWatchpointCommandCallback(
428-
wp_options, oneliner.c_str());
429+
wp_options, function_signature.c_str(), /*is_callback=*/true);
429430
} else {
430431
script_interp->CollectDataForWatchpointCommandCallback(wp_options,
431432
result);

lldb/source/Interpreter/ScriptInterpreter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ Status ScriptInterpreter::SetBreakpointCommandCallback(
108108
const char *callback_text) {
109109
Status error;
110110
for (BreakpointOptions &bp_options : bp_options_vec) {
111-
error = SetBreakpointCommandCallback(bp_options, callback_text);
111+
error = SetBreakpointCommandCallback(bp_options, callback_text,
112+
/*is_callback=*/false);
112113
if (!error.Success())
113114
break;
114115
}

lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class ScriptInterpreterLua : public ScriptInterpreter {
8888
CommandReturnObject &result) override;
8989

9090
Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
91-
const char *command_body_text) override;
91+
const char *command_body_text,
92+
const bool is_callback) override;
9293

9394
void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
9495
const char *command_body_text) override;

0 commit comments

Comments
 (0)