mib updated this revision to Diff 500317.
mib retitled this revision from "[lldb] Fix watchpoint command function
stopping behavior" to "[lldb] Fix {break,watch}point command function stopping
behavior".
mib edited the summary of this revision.
mib added a comment.
Address @jingham & @delcypher feedbacks.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D144688/new/
https://reviews.llvm.org/D144688
Files:
lldb/source/Commands/CommandObjectWatchpointCommand.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
lldb/test/API/commands/watchpoints/watchpoint_commands/command/TestWatchpointCommandPython.py
lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp
lldb/test/API/commands/watchpoints/watchpoint_commands/command/watchpoint_command.py
Index: lldb/test/API/commands/watchpoints/watchpoint_commands/command/watchpoint_command.py
===================================================================
--- lldb/test/API/commands/watchpoints/watchpoint_commands/command/watchpoint_command.py
+++ lldb/test/API/commands/watchpoints/watchpoint_commands/command/watchpoint_command.py
@@ -9,7 +9,12 @@
print ("I stopped the first time")
frame.EvaluateExpression("cookie = 888")
num_hits += 1
- frame.thread.process.Continue()
+ return True
+ if num_hits == 1:
+ print ("I stopped the second time, but with no return")
+ frame.EvaluateExpression("cookie = 666")
+ num_hits += 1
else:
print ("I stopped the %d time" % (num_hits))
frame.EvaluateExpression("cookie = 999")
+ return False # This cause the process to continue.
Index: lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp
===================================================================
--- lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp
+++ lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp
@@ -16,5 +16,5 @@
modify(global);
printf("global=%d\n", global);
- printf("cookie=%d\n", cookie);
+ printf("cookie=%d\n", cookie); // Set another breakpoint here.
}
Index: lldb/test/API/commands/watchpoints/watchpoint_commands/command/TestWatchpointCommandPython.py
===================================================================
--- lldb/test/API/commands/watchpoints/watchpoint_commands/command/TestWatchpointCommandPython.py
+++ lldb/test/API/commands/watchpoints/watchpoint_commands/command/TestWatchpointCommandPython.py
@@ -1,4 +1,4 @@
-"""
+"""
Test 'watchpoint command'.
"""
@@ -22,6 +22,8 @@
# Find the line number to break inside main().
self.line = line_number(
self.source, '// Set break point at this line.')
+ self.second_line = line_number(
+ self.source, '// Set another breakpoint here.')
# And the watchpoint variable declaration line number.
self.decl = line_number(self.source,
'// Watchpoint variable declaration.')
@@ -143,6 +145,32 @@
self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
substrs=['stop reason = watchpoint'])
+ # We should have hit the watchpoint once, set cookie to 888, since the
+ # user callback returned True.
+ self.expect("frame variable --show-globals cookie",
+ substrs=['(int32_t)', 'cookie = 888'])
+
+ self.runCmd("process continue")
+
+ # We should be stopped again due to the watchpoint (write type).
+ # The stop reason of the thread should be watchpoint.
+ self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
+ substrs=['stop reason = watchpoint'])
+
+ # We should have hit the watchpoint a second time, set cookie to 666,
+ # even if the user callback didn't return anything and then continue.
+ self.expect("frame variable --show-globals cookie",
+ substrs=['(int32_t)', 'cookie = 666'])
+
+ # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
+ lldbutil.run_break_set_by_file_and_line(
+ self, None, self.second_line, num_expected_locations=1)
+
+ self.runCmd("process continue")
+
+ self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stop reason = breakpoint'])
+
# We should have hit the watchpoint once, set cookie to 888, then continued to the
# second hit and set it to 999
self.expect("frame variable --show-globals cookie",
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1292,40 +1292,52 @@
StringList auto_generated_function;
auto_generated_function.AppendString(signature);
auto_generated_function.AppendString(
- " global_dict = globals()"); // Grab the global dictionary
+ " global_dict = globals()"); // Grab the global dictionary
auto_generated_function.AppendString(
- " new_keys = internal_dict.keys()"); // Make a list of keys in the
- // session dict
+ " new_keys = internal_dict.keys()"); // Make a list of keys in the
+ // session dict
auto_generated_function.AppendString(
- " old_keys = global_dict.keys()"); // Save list of keys in global dict
+ " old_keys = global_dict.keys()"); // Save list of keys in global dict
auto_generated_function.AppendString(
- " global_dict.update (internal_dict)"); // Add the session dictionary
- // to the
- // global dictionary.
+ " global_dict.update (internal_dict)"); // Add the session dictionary
+ // to the global dictionary.
+ auto_generated_function.AppendString(
+ " __return_val = None"); // Initialize user callback return value.
// Wrap everything up inside the function, increasing the indentation.
- auto_generated_function.AppendString(" if True:");
+ auto_generated_function.AppendString(" def __user_callback():");
+ auto_generated_function.AppendString(" nonlocal __return_val");
for (int i = 0; i < num_lines; ++i) {
sstr.Clear();
- sstr.Printf(" %s", input.GetStringAtIndex(i));
+ llvm::StringRef line = input.GetStringAtIndex(i);
+ if (line.startswith("return ")) {
+ llvm::StringRef return_val =
+ line.substr(llvm::StringRef("return ").size());
+ sstr.Printf(" __return_val = %s", return_val.data());
+ } else {
+ sstr.Printf(" %s", line.data());
+ }
auto_generated_function.AppendString(sstr.GetData());
}
auto_generated_function.AppendString(
- " for key in new_keys:"); // Iterate over all the keys from session
- // dict
+ " __user_callback()"); // Call user callback
auto_generated_function.AppendString(
- " internal_dict[key] = global_dict[key]"); // Update session dict
- // values
+ " for key in new_keys:"); // Iterate over all the keys from session
+ // dict
auto_generated_function.AppendString(
- " if key not in old_keys:"); // If key was not originally in
- // global dict
+ " internal_dict[key] = global_dict[key]"); // Update session dict
+ // values
auto_generated_function.AppendString(
- " del global_dict[key]"); // ...then remove key/value from
- // global dict
+ " if key not in old_keys:"); // If key was not originally in
+ // global dict
+ auto_generated_function.AppendString(
+ " del global_dict[key]"); // ...then remove key/value from
+ // global dict
+ auto_generated_function.AppendString(
+ " return __return_val"); // Return the user callback return value.
// Verify that the results are valid Python.
-
error = ExportFunctionDefinitionToInterpreter(auto_generated_function);
return error;
Index: lldb/source/Commands/CommandObjectWatchpointCommand.cpp
===================================================================
--- lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -422,7 +422,8 @@
// automatize what the user would do manually: make their watchpoint
// command be a function call
else if (!m_options.m_function_name.empty()) {
- std::string oneliner(m_options.m_function_name);
+ std::string oneliner("return ");
+ oneliner += m_options.m_function_name;
oneliner += "(frame, wp, internal_dict)";
script_interp->SetWatchpointCommandCallback(
wp_options, oneliner.c_str());
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits