[Lldb-commits] [lldb] [lldb] Expose QueueThreadPlanForStepSingleInstruction function to SBThreadPlan (PR #137904)
Ely Ronnen via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 30 14:10:37 PDT 2025
https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/137904
>From b901b71abbaac768e67913cdbc15da2337c8bb03 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 30 Apr 2025 02:00:44 +0200
Subject: [PATCH 1/3] Expose QueueThreadPlanForStepSingleInstruction function
to SBThreadPlan
---
lldb/include/lldb/API/SBThreadPlan.h | 4 ++++
lldb/source/API/SBThreadPlan.cpp | 31 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/lldb/include/lldb/API/SBThreadPlan.h b/lldb/include/lldb/API/SBThreadPlan.h
index d02ab80f76a76..ce1a1078d69b9 100644
--- a/lldb/include/lldb/API/SBThreadPlan.h
+++ b/lldb/include/lldb/API/SBThreadPlan.h
@@ -105,6 +105,10 @@ class LLDB_API SBThreadPlan {
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
bool first_insn, SBError &error);
+ SBThreadPlan QueueThreadPlanForStepSingleInstruction(bool step_over);
+ SBThreadPlan QueueThreadPlanForStepSingleInstruction(bool step_over,
+ SBError &error);
+
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address);
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address,
SBError &error);
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
index 083a050de8a38..a85afbb043875 100644
--- a/lldb/source/API/SBThreadPlan.cpp
+++ b/lldb/source/API/SBThreadPlan.cpp
@@ -325,6 +325,37 @@ SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
return SBThreadPlan();
}
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepSingleInstruction(bool step_over) {
+ LLDB_INSTRUMENT_VA(this, step_over);
+
+ SBError error;
+ return QueueThreadPlanForStepSingleInstruction(step_over, error);
+}
+
+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);
>From 8d8f4d7edbff13de7f07853700ab717ef275e3da Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 30 Apr 2025 09:37:32 +0200
Subject: [PATCH 2/3] Add API tests for QueueThreadPlanForStepSingleInstruction
---
.../functionalities/step_scripted/Steps.py | 16 +++++++++++
.../step_scripted/TestStepScripted.py | 28 +++++++++++++++++++
.../API/functionalities/step_scripted/main.c | 2 +-
3 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/lldb/test/API/functionalities/step_scripted/Steps.py b/lldb/test/API/functionalities/step_scripted/Steps.py
index 3325dba753657..e9e0fae1b14be 100644
--- a/lldb/test/API/functionalities/step_scripted/Steps.py
+++ b/lldb/test/API/functionalities/step_scripted/Steps.py
@@ -45,6 +45,22 @@ def queue_child_thread_plan(self):
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)
+
+
+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)
+
+
# This plan does a step-over until a variable changes value.
class StepUntil(StepWithChild):
def __init__(self, thread_plan, args_data):
diff --git a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
index 53901718019f9..f65c366a09e87 100644
--- a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
+++ b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
@@ -44,6 +44,34 @@ def step_out_with_scripted_plan(self, name):
stop_desc = thread.GetStopDescription(1000)
self.assertIn("Stepping out from", stop_desc, "Got right description")
+ def test_step_single_instruction(self):
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "Break on foo call", self.main_source_file
+ )
+
+ 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):
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "Break on foo call", self.main_source_file
+ )
+
+ 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())
+
def test_misspelled_plan_name(self):
"""Test that we get a useful error if we misspell the plan class name"""
self.build()
diff --git a/lldb/test/API/functionalities/step_scripted/main.c b/lldb/test/API/functionalities/step_scripted/main.c
index bfd8a35d55626..499a999e699d0 100644
--- a/lldb/test/API/functionalities/step_scripted/main.c
+++ b/lldb/test/API/functionalities/step_scripted/main.c
@@ -8,6 +8,6 @@ void foo() {
}
int main() {
- foo();
+ foo(); // Break on foo call.
return 0;
}
>From 7ab3ffdff562751c7398a48c4aa1c68bb6a87198 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 30 Apr 2025 22:32:57 +0200
Subject: [PATCH 3/3] improve QueueThreadPlanForStepSingleInstruction tests
---
.../step_scripted/TestStepScripted.py | 26 ++++++++++++++-----
.../API/functionalities/step_scripted/main.c | 2 +-
2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
index f65c366a09e87..54bc154590ed0 100644
--- a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
+++ b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
@@ -44,11 +44,23 @@ def step_out_with_scripted_plan(self, name):
stop_desc = thread.GetStopDescription(1000)
self.assertIn("Stepping out from", stop_desc, "Got right description")
- def test_step_single_instruction(self):
+ def run_until_branch_instruction(self):
self.build()
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
- self, "Break on foo call", self.main_source_file
+ 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)
@@ -58,10 +70,11 @@ def test_step_single_instruction(self):
self.assertEqual("foo", frame.GetFunctionName())
def test_step_single_instruction_with_step_over(self):
- self.build()
- (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
- self, "Break on foo call", self.main_source_file
- )
+ (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"
@@ -71,6 +84,7 @@ def test_step_single_instruction_with_step_over(self):
# 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"""
diff --git a/lldb/test/API/functionalities/step_scripted/main.c b/lldb/test/API/functionalities/step_scripted/main.c
index 499a999e699d0..9023120c44312 100644
--- a/lldb/test/API/functionalities/step_scripted/main.c
+++ b/lldb/test/API/functionalities/step_scripted/main.c
@@ -8,6 +8,6 @@ void foo() {
}
int main() {
- foo(); // Break on foo call.
+ foo(); // Break on branch instruction.
return 0;
}
More information about the lldb-commits
mailing list