[lldb] Expose QueueThreadPlanForStepSingleInstruction function to SBThreadPlan (#137904)

Expose `QueueThreadPlanForStepSingleInstruction` function to
SBThreadPlan
This commit is contained in:
Ely Ronnen 2025-05-08 14:01:42 +02:00 committed by GitHub
parent c290f48a45
commit 4132141681
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 89 additions and 1 deletions

View File

@ -105,6 +105,9 @@ public:
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
bool first_insn, SBError &error);
SBThreadPlan QueueThreadPlanForStepSingleInstruction(bool step_over,
SBError &error);
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address);
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address,
SBError &error);

View File

@ -325,6 +325,29 @@ SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
return SBThreadPlan();
}
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepSingleInstruction(bool step_over,
SBError &error) {
LLDB_INSTRUMENT_VA(this, step_over, error);
ThreadPlanSP thread_plan_sp(GetSP());
if (thread_plan_sp) {
Status plan_status;
SBThreadPlan plan(
thread_plan_sp->GetThread().QueueThreadPlanForStepSingleInstruction(
step_over, false, false, plan_status));
if (plan_status.Fail())
error.SetErrorString(plan_status.AsCString());
else
plan.GetSP()->SetPrivate(true);
return plan;
}
return SBThreadPlan();
}
SBThreadPlan
SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) {
LLDB_INSTRUMENT_VA(this, sb_address);

View File

@ -45,6 +45,26 @@ class StepScripted(StepWithChild):
return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut")
class StepSingleInstruction(StepWithChild):
def __init__(self, thread_plan, dict):
super().__init__(thread_plan)
def queue_child_thread_plan(self):
return self.thread_plan.QueueThreadPlanForStepSingleInstruction(
False, lldb.SBError()
)
class StepSingleInstructionWithStepOver(StepWithChild):
def __init__(self, thread_plan, dict):
super().__init__(thread_plan)
def queue_child_thread_plan(self):
return self.thread_plan.QueueThreadPlanForStepSingleInstruction(
True, lldb.SBError()
)
# This plan does a step-over until a variable changes value.
class StepUntil(StepWithChild):
def __init__(self, thread_plan, args_data):

View File

@ -44,6 +44,48 @@ class StepScriptedTestCase(TestBase):
stop_desc = thread.GetStopDescription(1000)
self.assertIn("Stepping out from", stop_desc, "Got right description")
def run_until_branch_instruction(self):
self.build()
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Break on branch instruction", self.main_source_file
)
# Check that we landed in a call instruction
frame = thread.GetFrameAtIndex(0)
current_instruction = target.ReadInstructions(frame.GetPCAddress(), 1)[0]
self.assertEqual(
lldb.eInstructionControlFlowKindCall,
current_instruction.GetControlFlowKind(target),
)
return (target, process, thread, bkpt)
def test_step_single_instruction(self):
(target, process, thread, bkpt) = self.run_until_branch_instruction()
err = thread.StepUsingScriptedThreadPlan("Steps.StepSingleInstruction")
self.assertSuccess(err)
# Verify that stepping a single instruction after "foo();" steps into `foo`
frame = thread.GetFrameAtIndex(0)
self.assertEqual("foo", frame.GetFunctionName())
def test_step_single_instruction_with_step_over(self):
(target, process, thread, bkpt) = self.run_until_branch_instruction()
frame = thread.GetFrameAtIndex(0)
next_instruction = target.ReadInstructions(frame.GetPCAddress(), 2)[1]
next_instruction_address = next_instruction.GetAddress()
err = thread.StepUsingScriptedThreadPlan(
"Steps.StepSingleInstructionWithStepOver"
)
self.assertSuccess(err)
# Verify that stepping over an instruction doesn't step into `foo`
frame = thread.GetFrameAtIndex(0)
self.assertEqual("main", frame.GetFunctionName())
self.assertEqual(next_instruction_address, frame.GetPCAddress())
def test_misspelled_plan_name(self):
"""Test that we get a useful error if we misspell the plan class name"""
self.build()

View File

@ -8,6 +8,6 @@ void foo() {
}
int main() {
foo();
foo(); // Break on branch instruction.
return 0;
}