Skip to content

Commit 4132141

Browse files
authored
[lldb] Expose QueueThreadPlanForStepSingleInstruction function to SBThreadPlan (#137904)
Expose `QueueThreadPlanForStepSingleInstruction` function to SBThreadPlan
1 parent c290f48 commit 4132141

File tree

5 files changed

+89
-1
lines changed

5 files changed

+89
-1
lines changed

lldb/include/lldb/API/SBThreadPlan.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ class LLDB_API SBThreadPlan {
105105
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
106106
bool first_insn, SBError &error);
107107

108+
SBThreadPlan QueueThreadPlanForStepSingleInstruction(bool step_over,
109+
SBError &error);
110+
108111
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address);
109112
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address,
110113
SBError &error);

lldb/source/API/SBThreadPlan.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,29 @@ SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
325325
return SBThreadPlan();
326326
}
327327

328+
SBThreadPlan
329+
SBThreadPlan::QueueThreadPlanForStepSingleInstruction(bool step_over,
330+
SBError &error) {
331+
LLDB_INSTRUMENT_VA(this, step_over, error);
332+
333+
ThreadPlanSP thread_plan_sp(GetSP());
334+
if (thread_plan_sp) {
335+
Status plan_status;
336+
SBThreadPlan plan(
337+
thread_plan_sp->GetThread().QueueThreadPlanForStepSingleInstruction(
338+
step_over, false, false, plan_status));
339+
340+
if (plan_status.Fail())
341+
error.SetErrorString(plan_status.AsCString());
342+
else
343+
plan.GetSP()->SetPrivate(true);
344+
345+
return plan;
346+
}
347+
348+
return SBThreadPlan();
349+
}
350+
328351
SBThreadPlan
329352
SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) {
330353
LLDB_INSTRUMENT_VA(this, sb_address);

lldb/test/API/functionalities/step_scripted/Steps.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ def queue_child_thread_plan(self):
4545
return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut")
4646

4747

48+
class StepSingleInstruction(StepWithChild):
49+
def __init__(self, thread_plan, dict):
50+
super().__init__(thread_plan)
51+
52+
def queue_child_thread_plan(self):
53+
return self.thread_plan.QueueThreadPlanForStepSingleInstruction(
54+
False, lldb.SBError()
55+
)
56+
57+
58+
class StepSingleInstructionWithStepOver(StepWithChild):
59+
def __init__(self, thread_plan, dict):
60+
super().__init__(thread_plan)
61+
62+
def queue_child_thread_plan(self):
63+
return self.thread_plan.QueueThreadPlanForStepSingleInstruction(
64+
True, lldb.SBError()
65+
)
66+
67+
4868
# This plan does a step-over until a variable changes value.
4969
class StepUntil(StepWithChild):
5070
def __init__(self, thread_plan, args_data):

lldb/test/API/functionalities/step_scripted/TestStepScripted.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,48 @@ def step_out_with_scripted_plan(self, name):
4444
stop_desc = thread.GetStopDescription(1000)
4545
self.assertIn("Stepping out from", stop_desc, "Got right description")
4646

47+
def run_until_branch_instruction(self):
48+
self.build()
49+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
50+
self, "Break on branch instruction", self.main_source_file
51+
)
52+
53+
# Check that we landed in a call instruction
54+
frame = thread.GetFrameAtIndex(0)
55+
current_instruction = target.ReadInstructions(frame.GetPCAddress(), 1)[0]
56+
self.assertEqual(
57+
lldb.eInstructionControlFlowKindCall,
58+
current_instruction.GetControlFlowKind(target),
59+
)
60+
return (target, process, thread, bkpt)
61+
62+
def test_step_single_instruction(self):
63+
(target, process, thread, bkpt) = self.run_until_branch_instruction()
64+
65+
err = thread.StepUsingScriptedThreadPlan("Steps.StepSingleInstruction")
66+
self.assertSuccess(err)
67+
68+
# Verify that stepping a single instruction after "foo();" steps into `foo`
69+
frame = thread.GetFrameAtIndex(0)
70+
self.assertEqual("foo", frame.GetFunctionName())
71+
72+
def test_step_single_instruction_with_step_over(self):
73+
(target, process, thread, bkpt) = self.run_until_branch_instruction()
74+
75+
frame = thread.GetFrameAtIndex(0)
76+
next_instruction = target.ReadInstructions(frame.GetPCAddress(), 2)[1]
77+
next_instruction_address = next_instruction.GetAddress()
78+
79+
err = thread.StepUsingScriptedThreadPlan(
80+
"Steps.StepSingleInstructionWithStepOver"
81+
)
82+
self.assertSuccess(err)
83+
84+
# Verify that stepping over an instruction doesn't step into `foo`
85+
frame = thread.GetFrameAtIndex(0)
86+
self.assertEqual("main", frame.GetFunctionName())
87+
self.assertEqual(next_instruction_address, frame.GetPCAddress())
88+
4789
def test_misspelled_plan_name(self):
4890
"""Test that we get a useful error if we misspell the plan class name"""
4991
self.build()

lldb/test/API/functionalities/step_scripted/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ void foo() {
88
}
99

1010
int main() {
11-
foo();
11+
foo(); // Break on branch instruction.
1212
return 0;
1313
}

0 commit comments

Comments
 (0)