Skip to content

Commit cfc0958

Browse files
authored
Merge pull request #10463 from jimingham/internal_dict-management
Fix the managing of the session dictionary when you have nested wrapp…
2 parents 8d40812 + 6f3c593 commit cfc0958

File tree

5 files changed

+115
-5
lines changed

5 files changed

+115
-5
lines changed

lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,8 @@ Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(
12861286
StringList &function_def) {
12871287
// Convert StringList to one long, newline delimited, const char *.
12881288
std::string function_def_string(function_def.CopyList());
1289+
LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n%s\n",
1290+
function_def_string.c_str());
12891291

12901292
Status error = ExecuteMultipleLines(
12911293
function_def_string.c_str(),
@@ -1356,13 +1358,15 @@ Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,
13561358
" for key in new_keys:"); // Iterate over all the keys from session
13571359
// dict
13581360
auto_generated_function.AppendString(
1359-
" internal_dict[key] = global_dict[key]"); // Update session dict
1360-
// values
1361+
" if key in old_keys:"); // If key was originally in
1362+
// global dict
13611363
auto_generated_function.AppendString(
1362-
" if key not in old_keys:"); // If key was not originally in
1363-
// global dict
1364+
" internal_dict[key] = global_dict[key]"); // Update it
13641365
auto_generated_function.AppendString(
1365-
" del global_dict[key]"); // ...then remove key/value from
1366+
" elif key in global_dict:"); // Then if it is still in the
1367+
// global dict
1368+
auto_generated_function.AppendString(
1369+
" del global_dict[key]"); // remove key/value from the
13661370
// global dict
13671371
auto_generated_function.AppendString(
13681372
" return __return_val"); // Return the user callback return value.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
C_SOURCES := main.c
2+
CFLAGS_EXTRAS := -std=c99
3+
4+
include Makefile.rules
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
Test that a Python breakpoint callback defined in another Python
3+
breakpoint callback works properly.
4+
"""
5+
6+
7+
import lldb
8+
import os
9+
import lldbsuite.test.lldbutil as lldbutil
10+
from lldbsuite.test.lldbtest import *
11+
12+
13+
class TestNestedBreakpointCommands(TestBase):
14+
NO_DEBUG_INFO_TESTCASE = True
15+
16+
def test_nested_commands(self):
17+
self.build()
18+
self.main_source_file = lldb.SBFileSpec("main.c")
19+
self.callback_module = "make_bkpt_cmds"
20+
self.do_test()
21+
22+
def do_test(self):
23+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
24+
self, "Set a breakpoint here", self.main_source_file
25+
)
26+
27+
outer_bkpt = target.BreakpointCreateBySourceRegex(
28+
"Set outer breakpoint here", self.main_source_file
29+
)
30+
cmd_file_path = os.path.join(self.getSourceDir(), f"{self.callback_module}.py")
31+
self.runCmd(f"command script import {cmd_file_path}")
32+
outer_bkpt.SetScriptCallbackFunction(f"{self.callback_module}.outer_callback")
33+
34+
process.Continue()
35+
36+
self.assertEqual(
37+
thread.stop_reason, lldb.eStopReasonBreakpoint, "Right stop reason"
38+
)
39+
40+
bkpt_no = thread.stop_reason_data[0]
41+
42+
# We made the callbacks record the new breakpoint ID and the number of
43+
# times a callback ran in some globals in the target. Find them now:
44+
exec_module = target.FindModule(target.executable)
45+
self.assertTrue(exec_module.IsValid(), "Found executable module")
46+
var = exec_module.FindFirstGlobalVariable(target, "g_global")
47+
self.assertSuccess(var.GetError(), "Found globals")
48+
num_hits = var.GetChildAtIndex(1).GetValueAsUnsigned()
49+
inner_id = var.GetChildAtIndex(2).GetValueAsUnsigned()
50+
51+
# Make sure they have the right values:
52+
self.assertEqual(bkpt_no, inner_id, "Hit the right breakpoint")
53+
self.assertEqual(num_hits, 2, "Right counter end value")
54+
self.assertEqual(thread.frames[0].name, "main", "Got to main")
55+
56+
self.assertEqual(outer_bkpt.GetHitCount(), 1, "Hit outer breakpoint once")
57+
58+
inner_bkpt = target.FindBreakpointByID(inner_id)
59+
self.assertEqual(inner_bkpt.GetHitCount(), 1, "Hit inner breakpoint once")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stdio.h>
2+
3+
int g_global[3] = {0, 100000, 100000};
4+
5+
void doSomething() {
6+
g_global[0] = 1; // Set outer breakpoint here
7+
}
8+
9+
int main() {
10+
doSomething(); // Set a breakpoint here
11+
12+
return g_global[0];
13+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import lldb
2+
3+
4+
def set_globals(target, index, value):
5+
exe_module = target.FindModule(target.executable)
6+
var = exe_module.FindFirstGlobalVariable(target, "g_global")
7+
child = var.GetChildAtIndex(index)
8+
child.SetValueFromCString(str(value))
9+
10+
11+
def outer_callback(frame: lldb.SBFrame, bp_loc, internal_dict):
12+
thread = frame.GetThread()
13+
14+
# address of the next frame
15+
next_frame_pc = thread.get_thread_frames()[1].GetPC()
16+
17+
target = thread.process.target
18+
bp = target.BreakpointCreateByAddress(next_frame_pc)
19+
bp.SetScriptCallbackFunction(f"{__name__}.nested_bp_callback")
20+
set_globals(target, 1, 1)
21+
set_globals(target, 2, bp.GetID())
22+
23+
return False
24+
25+
26+
def nested_bp_callback(frame: lldb.SBFrame, bp_loc, extra_args, internal_dict):
27+
target = frame.thread.process.target
28+
set_globals(target, 1, 2)
29+
30+
return True

0 commit comments

Comments
 (0)