[Lldb-commits] [lldb] [lldb] Add step back single instruction for targets supporting reverse execution (PR #191183)
Maarten Steevens via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 9 05:57:41 PDT 2026
https://github.com/MaartenS11 updated https://github.com/llvm/llvm-project/pull/191183
>From 0c0db27fff745bd87908181435ad07beb5e56243 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 10:08:17 +0200
Subject: [PATCH 1/5] Early attempt at step back with a threadplan
---
.../Process/gdb-remote/ProcessGDBRemote.cpp | 53 +++++++++++++++++++
.../Process/gdb-remote/ProcessGDBRemote.h | 2 +
2 files changed, 55 insertions(+)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index d74649a48405d..ed99c5103fb5d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3903,6 +3903,37 @@ void ProcessGDBRemote::StopAsyncThread() {
__FUNCTION__);
}
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+
+class ThreadPlanStepBackInstruction : public ThreadPlanStepInstruction {
+public:
+ ThreadPlanStepBackInstruction(Thread &thread,
+ bool step_over,
+ bool stop_other_threads,
+ Vote report_stop_vote,
+ Vote report_run_vote)
+ : ThreadPlanStepInstruction(thread, step_over, stop_other_threads, report_stop_vote, report_run_vote) {}
+
+ lldb::RunDirection GetDirection() const override {
+ return lldb::RunDirection::eRunReverse;
+ }
+};
+
+Status ProcessGDBRemote::StepBack() {
+ LLDB_LOGF(GetLog(GDBRLog::Process), "Thread count = %d", m_thread_ids.size());
+ ThreadSP thread = GetThreadList().FindThreadByID(m_thread_ids[0]);
+
+ ThreadPlanSP thread_plan_sp(new ThreadPlanStepBackInstruction(
+ *thread, false, true, eVoteNoOpinion, eVoteNoOpinion));
+ thread->QueueThreadPlan(thread_plan_sp, false);
+
+ thread_plan_sp->SetIsControllingPlan(true);
+ thread_plan_sp->SetOkayToDiscard(false);
+
+ GetThreadList().SetSelectedThreadByID(m_thread_ids[0]);
+ return Resume();
+}
+
thread_result_t ProcessGDBRemote::AsyncThread() {
Log *log = GetLog(GDBRLog::Process);
LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...",
@@ -5953,6 +5984,25 @@ class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed {
}
};
+class CommandObjectProcessGDBRemotePacketStepBack : public CommandObjectParsed {
+ private:
+public:
+ CommandObjectProcessGDBRemotePacketStepBack(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet step-back",
+ "Step back one instruction",
+ nullptr) {}
+
+ ~CommandObjectProcessGDBRemotePacketStepBack() override = default;
+
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ process->StepBack();
+ }
+ }
+};
+
class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw {
private:
public:
@@ -6012,6 +6062,9 @@ class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
LoadSubCommand(
"send", CommandObjectSP(
new CommandObjectProcessGDBRemotePacketSend(interpreter)));
+ LoadSubCommand(
+ "step-back", CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketStepBack(interpreter)));
LoadSubCommand(
"monitor",
CommandObjectSP(
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 434c4f29201e5..5dec9b1061e77 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -255,6 +255,8 @@ class ProcessGDBRemote : public Process,
llvm::Expected<bool> SaveCore(llvm::StringRef outfile) override;
+ Status StepBack();
+
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;
>From 25dc464c626e275ac94a0f0ac12326cb2045afb8 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 10:24:45 +0200
Subject: [PATCH 2/5] Use the currently selected thread instead of thread 0
---
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index ed99c5103fb5d..860339a0ec28f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3920,8 +3920,7 @@ class ThreadPlanStepBackInstruction : public ThreadPlanStepInstruction {
};
Status ProcessGDBRemote::StepBack() {
- LLDB_LOGF(GetLog(GDBRLog::Process), "Thread count = %d", m_thread_ids.size());
- ThreadSP thread = GetThreadList().FindThreadByID(m_thread_ids[0]);
+ ThreadSP thread = GetThreadList().GetSelectedThread();
ThreadPlanSP thread_plan_sp(new ThreadPlanStepBackInstruction(
*thread, false, true, eVoteNoOpinion, eVoteNoOpinion));
@@ -3930,7 +3929,6 @@ Status ProcessGDBRemote::StepBack() {
thread_plan_sp->SetIsControllingPlan(true);
thread_plan_sp->SetOkayToDiscard(false);
- GetThreadList().SetSelectedThreadByID(m_thread_ids[0]);
return Resume();
}
>From 3959964d73d24fc8ddb7f9b3897e4619f94acfd7 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 10:39:08 +0200
Subject: [PATCH 3/5] Move some code into Thread.cpp so other platforms can
also implement step back
---
lldb/include/lldb/Target/Thread.h | 7 ++++
.../Process/gdb-remote/ProcessGDBRemote.cpp | 31 +--------------
.../Process/gdb-remote/ProcessGDBRemote.h | 2 -
lldb/source/Target/Thread.cpp | 38 +++++++++++++++++++
4 files changed, 46 insertions(+), 32 deletions(-)
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index c698dd8015885..7b52fc3238b97 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -629,6 +629,13 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// An error that describes anything that went wrong
virtual Status StepOut(uint32_t frame_idx = 0);
+ /// Default implementation for stepping back one instruction.
+ ///
+ /// This function is designed to be used by commands where the
+ /// process is publicly stopped.
+ ///
+ virtual Status StepBack();
+
/// Retrieves the per-thread data area.
/// Most OSs maintain a per-thread pointer (e.g. the FS register on
/// x64), which we return the value of here.
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 860339a0ec28f..d75d092954611 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -3903,35 +3903,6 @@ void ProcessGDBRemote::StopAsyncThread() {
__FUNCTION__);
}
-#include "lldb/Target/ThreadPlanStepInstruction.h"
-
-class ThreadPlanStepBackInstruction : public ThreadPlanStepInstruction {
-public:
- ThreadPlanStepBackInstruction(Thread &thread,
- bool step_over,
- bool stop_other_threads,
- Vote report_stop_vote,
- Vote report_run_vote)
- : ThreadPlanStepInstruction(thread, step_over, stop_other_threads, report_stop_vote, report_run_vote) {}
-
- lldb::RunDirection GetDirection() const override {
- return lldb::RunDirection::eRunReverse;
- }
-};
-
-Status ProcessGDBRemote::StepBack() {
- ThreadSP thread = GetThreadList().GetSelectedThread();
-
- ThreadPlanSP thread_plan_sp(new ThreadPlanStepBackInstruction(
- *thread, false, true, eVoteNoOpinion, eVoteNoOpinion));
- thread->QueueThreadPlan(thread_plan_sp, false);
-
- thread_plan_sp->SetIsControllingPlan(true);
- thread_plan_sp->SetOkayToDiscard(false);
-
- return Resume();
-}
-
thread_result_t ProcessGDBRemote::AsyncThread() {
Log *log = GetLog(GDBRLog::Process);
LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...",
@@ -5996,7 +5967,7 @@ class CommandObjectProcessGDBRemotePacketStepBack : public CommandObjectParsed {
ProcessGDBRemote *process =
(ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
if (process) {
- process->StepBack();
+ process->GetThreadList().GetSelectedThread()->StepBack();
}
}
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 5dec9b1061e77..434c4f29201e5 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -255,8 +255,6 @@ class ProcessGDBRemote : public Process,
llvm::Expected<bool> SaveCore(llvm::StringRef outfile) override;
- Status StepBack();
-
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index c8e50db2316ad..5c5449126343b 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -2322,6 +2322,44 @@ Status Thread::StepOut(uint32_t frame_idx) {
return error;
}
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+
+class ThreadPlanStepBackInstruction : public ThreadPlanStepInstruction {
+public:
+ ThreadPlanStepBackInstruction(Thread &thread,
+ bool step_over,
+ bool stop_other_threads,
+ Vote report_stop_vote,
+ Vote report_run_vote)
+ : ThreadPlanStepInstruction(thread, step_over, stop_other_threads, report_stop_vote, report_run_vote) {}
+
+ lldb::RunDirection GetDirection() const override {
+ return lldb::RunDirection::eRunReverse;
+ }
+};
+
+Status Thread::StepBack() {
+ Process *process = GetProcess().get();
+ if (!StateIsStoppedState(process->GetState(), true)) {
+ return Status::FromErrorString("process not stopped");
+ }
+
+ if (!process->SupportsReverseDirection()) {
+ return Status::FromErrorString("process does not support reverse execution");
+ }
+
+ ThreadPlanSP thread_plan_sp(new ThreadPlanStepBackInstruction(
+ *this, false, true, eVoteNoOpinion, eVoteNoOpinion));
+ QueueThreadPlan(thread_plan_sp, false);
+
+ thread_plan_sp->SetIsControllingPlan(true);
+ thread_plan_sp->SetOkayToDiscard(false);
+
+ // Why do we need to set the current thread by ID here???
+ process->GetThreadList().SetSelectedThreadByID(GetID());
+ return process->Resume();
+}
+
ValueObjectSP Thread::GetCurrentException() {
if (auto frame_sp = GetStackFrameAtIndex(0))
if (auto recognized_frame = frame_sp->GetRecognizedFrame())
>From 789629468bc5aa85a9aedba79429d5df1193b433 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 11:16:29 +0200
Subject: [PATCH 4/5] Add thread step-back-inst + stepbi sbi alias + remove old
testing command
---
lldb/source/Commands/CommandObjectThread.cpp | 24 +++++++++++++++++++
.../source/Interpreter/CommandInterpreter.cpp | 6 +++++
.../Process/gdb-remote/ProcessGDBRemote.cpp | 22 -----------------
3 files changed, 30 insertions(+), 22 deletions(-)
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 6786741cd04b6..bbf38981aee60 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -632,6 +632,26 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
OptionGroupOptions m_all_options;
};
+// CommandObjectThreadStepBackInstruction
+
+class CommandObjectThreadStepBackInstruction : public CommandObjectParsed {
+ private:
+public:
+ CommandObjectThreadStepBackInstruction(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet step-back",
+ "Step back one instruction.",
+ nullptr) {}
+
+ ~CommandObjectThreadStepBackInstruction() override = default;
+
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ if (process) {
+ process->GetThreadList().GetSelectedThread()->StepBack();
+ }
+ }
+};
+
// CommandObjectThreadContinue
class CommandObjectThreadContinue : public CommandObjectParsed {
@@ -2590,6 +2610,10 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread(
"Defaults to current thread unless specified.",
nullptr, eStepTypeTrace)));
+ LoadSubCommand("step-back-inst",
+ CommandObjectSP(new CommandObjectThreadStepBackInstruction(
+ interpreter)));
+
LoadSubCommand("step-inst-over",
CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
interpreter, "thread step-inst-over",
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index eeb1ae0ff3eb8..139ac072a4ee9 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -335,6 +335,12 @@ void CommandInterpreter::Initialize() {
AddAlias("si", cmd_obj_sp);
}
+ cmd_obj_sp = GetCommandSPExact("thread step-back-inst");
+ if (cmd_obj_sp) {
+ AddAlias("stepbi", cmd_obj_sp);
+ AddAlias("sbi", cmd_obj_sp);
+ }
+
cmd_obj_sp = GetCommandSPExact("thread step-inst-over");
if (cmd_obj_sp) {
AddAlias("nexti", cmd_obj_sp);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index d75d092954611..d74649a48405d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -5953,25 +5953,6 @@ class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed {
}
};
-class CommandObjectProcessGDBRemotePacketStepBack : public CommandObjectParsed {
- private:
-public:
- CommandObjectProcessGDBRemotePacketStepBack(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "process plugin packet step-back",
- "Step back one instruction",
- nullptr) {}
-
- ~CommandObjectProcessGDBRemotePacketStepBack() override = default;
-
- void DoExecute(Args &command, CommandReturnObject &result) override {
- ProcessGDBRemote *process =
- (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process) {
- process->GetThreadList().GetSelectedThread()->StepBack();
- }
- }
-};
-
class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw {
private:
public:
@@ -6031,9 +6012,6 @@ class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
LoadSubCommand(
"send", CommandObjectSP(
new CommandObjectProcessGDBRemotePacketSend(interpreter)));
- LoadSubCommand(
- "step-back", CommandObjectSP(
- new CommandObjectProcessGDBRemotePacketStepBack(interpreter)));
LoadSubCommand(
"monitor",
CommandObjectSP(
>From 6d4acca4f66f806f57dcc163600d697523f33243 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 14:23:40 +0200
Subject: [PATCH 5/5] Refactor code to integerate with
QueueThreadPlanForStepSingleInstruction which now has a direction
---
lldb/include/lldb/Target/Thread.h | 4 +-
.../lldb/Target/ThreadPlanStepInstruction.h | 9 ++-
lldb/include/lldb/lldb-private-enumerations.h | 1 +
lldb/source/API/SBThread.cpp | 8 ++-
lldb/source/API/SBThreadPlan.cpp | 2 +-
lldb/source/Commands/CommandObjectThread.cpp | 43 +++++--------
.../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 4 +-
.../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 2 +-
lldb/source/Target/StopInfo.cpp | 6 +-
lldb/source/Target/Thread.cpp | 63 ++++++++-----------
.../Target/ThreadPlanStepInstruction.cpp | 14 +++--
11 files changed, 72 insertions(+), 84 deletions(-)
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 7b52fc3238b97..31205acba5fb3 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -730,8 +730,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
virtual lldb::ThreadPlanSP QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads,
- Status &status);
+ bool step_over, lldb::RunDirection direction, bool abort_other_plans,
+ bool stop_other_threads, Status &status);
/// Queues the plan used to step through an address range, stepping over
/// function calls.
diff --git a/lldb/include/lldb/Target/ThreadPlanStepInstruction.h b/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
index 52a5a2efc0a47..f8a3f56cb422a 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
@@ -17,7 +17,8 @@ namespace lldb_private {
class ThreadPlanStepInstruction : public ThreadPlan {
public:
- ThreadPlanStepInstruction(Thread &thread, bool step_over, bool stop_others,
+ ThreadPlanStepInstruction(Thread &thread, bool step_over,
+ lldb::RunDirection direction, bool stop_others,
Vote report_stop_vote, Vote report_run_vote);
~ThreadPlanStepInstruction() override;
@@ -30,6 +31,7 @@ class ThreadPlanStepInstruction : public ThreadPlan {
bool WillStop() override;
bool MischiefManaged() override;
bool IsPlanStale() override;
+ lldb::RunDirection GetDirection() const override;
protected:
bool DoPlanExplainsStop(Event *event_ptr) override;
@@ -38,12 +40,13 @@ class ThreadPlanStepInstruction : public ThreadPlan {
private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads,
- Status &status);
+ bool step_over, lldb::RunDirection direction, bool abort_other_plans,
+ bool stop_other_threads, Status &status);
lldb::addr_t m_instruction_addr;
bool m_stop_other_threads;
bool m_step_over;
+ lldb::RunDirection m_direction;
// These two are used only for the step over case.
bool m_start_has_symbol;
StackID m_stack_id;
diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h
index a6965657f5bc9..db26f53f4056b 100644
--- a/lldb/include/lldb/lldb-private-enumerations.h
+++ b/lldb/include/lldb/lldb-private-enumerations.h
@@ -21,6 +21,7 @@ namespace lldb_private {
enum StepType {
eStepTypeNone,
eStepTypeTrace, ///< Single step one instruction.
+ eStepTypeTraceBack, ///< Single step back one instruction.
eStepTypeTraceOver, ///< Single step one instruction, stepping over.
eStepTypeInto, ///< Single step into a specified context.
eStepTypeOver, ///< Single step over a specified context.
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 9efc39c70d1a4..2c4bc8795a53b 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -507,7 +507,8 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
new_plan_status, avoid_no_debug);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, stop_other_threads, new_plan_status);
+ true, eRunForward, abort_other_plans, stop_other_threads,
+ new_plan_status);
}
}
error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
@@ -573,7 +574,8 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, stop_other_threads, new_plan_status);
+ false, eRunForward, abort_other_plans, stop_other_threads,
+ new_plan_status);
}
if (new_plan_status.Success())
@@ -694,7 +696,7 @@ void SBThread::StepInstruction(bool step_over, SBError &error) {
Thread *thread = exe_ctx->GetThreadPtr();
Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
- step_over, false, true, new_plan_status));
+ step_over, eRunForward, false, true, new_plan_status));
if (new_plan_status.Success())
error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
index c8ca6c81a3efb..21d834e0674dd 100644
--- a/lldb/source/API/SBThreadPlan.cpp
+++ b/lldb/source/API/SBThreadPlan.cpp
@@ -335,7 +335,7 @@ SBThreadPlan::QueueThreadPlanForStepSingleInstruction(bool step_over,
Status plan_status;
SBThreadPlan plan(
thread_plan_sp->GetThread().QueueThreadPlanForStepSingleInstruction(
- step_over, false, false, plan_status));
+ step_over, eRunForward, false, false, plan_status));
if (plan_status.Fail())
error.SetErrorString(plan_status.AsCString());
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index bbf38981aee60..2b882468a380e 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -536,7 +536,8 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
}
} else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads, new_plan_status);
+ false, eRunForward, abort_other_plans, bool_stop_other_threads,
+ new_plan_status);
} else if (m_step_type == eStepTypeOver) {
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
@@ -549,13 +550,20 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
m_options.m_step_out_avoid_no_debug);
else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads, new_plan_status);
+ true, eRunForward, abort_other_plans, bool_stop_other_threads,
+ new_plan_status);
} else if (m_step_type == eStepTypeTrace) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads, new_plan_status);
+ false, eRunForward, abort_other_plans, bool_stop_other_threads,
+ new_plan_status);
+ } else if (m_step_type == eStepTypeTraceBack) {
+ new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
+ false, eRunReverse, abort_other_plans, bool_stop_other_threads,
+ new_plan_status);
} else if (m_step_type == eStepTypeTraceOver) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads, new_plan_status);
+ true, eRunForward, abort_other_plans, bool_stop_other_threads,
+ new_plan_status);
} else if (m_step_type == eStepTypeOut) {
new_plan_sp = thread->QueueThreadPlanForStepOut(
abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
@@ -632,26 +640,6 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
OptionGroupOptions m_all_options;
};
-// CommandObjectThreadStepBackInstruction
-
-class CommandObjectThreadStepBackInstruction : public CommandObjectParsed {
- private:
-public:
- CommandObjectThreadStepBackInstruction(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "process plugin packet step-back",
- "Step back one instruction.",
- nullptr) {}
-
- ~CommandObjectThreadStepBackInstruction() override = default;
-
- void DoExecute(Args &command, CommandReturnObject &result) override {
- Process *process = m_exe_ctx.GetProcessPtr();
- if (process) {
- process->GetThreadList().GetSelectedThread()->StepBack();
- }
- }
-};
-
// CommandObjectThreadContinue
class CommandObjectThreadContinue : public CommandObjectParsed {
@@ -2611,8 +2599,11 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread(
nullptr, eStepTypeTrace)));
LoadSubCommand("step-back-inst",
- CommandObjectSP(new CommandObjectThreadStepBackInstruction(
- interpreter)));
+ CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
+ interpreter, "thread step-back-inst",
+ "Instruction level back step. "
+ "Defaults to current thread unless specified.",
+ nullptr, eStepTypeTraceBack)));
LoadSubCommand("step-inst-over",
CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index afa0ef28a381d..fa11896d749e8 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -1080,8 +1080,8 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
if (!thread_plan_sp && is_branch_island) {
thread_plan_sp = std::make_shared<ThreadPlanStepInstruction>(
thread,
- /* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
- eVoteNoOpinion);
+ /* step_over= */ false, eRunForward, /* stop_others */ false,
+ eVoteNoOpinion, eVoteNoOpinion);
LLDB_LOG(log, "Stepping one instruction over branch island: '{0}'.",
current_name);
}
diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 79fb4d46eff41..bd735ef884b8f 100644
--- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -228,5 +228,5 @@ DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
assert(first_insn->DoesBranch() && !second_insn->DoesBranch());
return ThreadPlanSP(new ThreadPlanStepInstruction(
- thread, false, false, eVoteNoOpinion, eVoteNoOpinion));
+ thread, false, eRunForward, false, eVoteNoOpinion, eVoteNoOpinion));
}
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 5110ed16edc91..89c85081733c6 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -788,11 +788,11 @@ class StopInfoWatchpoint : public StopInfo {
// them and they won't behave correctly.
class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {
public:
- ThreadPlanStepOverWatchpoint(Thread &thread,
+ ThreadPlanStepOverWatchpoint(Thread &thread,
StopInfoWatchpointSP stop_info_sp,
WatchpointSP watch_sp)
- : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,
- eVoteNoOpinion),
+ : ThreadPlanStepInstruction(thread, false, eRunForward, true,
+ eVoteNoOpinion, eVoteNoOpinion),
m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {
assert(watch_sp);
}
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 5c5449126343b..3c1b5db81516c 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -372,14 +372,14 @@ lldb::StopInfoSP Thread::GetStopInfo() {
// from completed plan stack - m_stop_info_sp (trace stop reason is OK now) -
// ask GetPrivateStopInfo to set stop info
- bool have_valid_stop_info = m_stop_info_sp &&
- m_stop_info_sp ->IsValid() &&
- m_stop_info_stop_id == stop_id;
- bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
+ bool have_valid_stop_info = m_stop_info_sp && m_stop_info_sp->IsValid() &&
+ m_stop_info_stop_id == stop_id;
+ bool have_valid_completed_plan =
+ completed_plan_sp && completed_plan_sp->PlanSucceeded();
bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
bool plan_overrides_trace =
- have_valid_stop_info && have_valid_completed_plan
- && (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
+ have_valid_stop_info && have_valid_completed_plan &&
+ (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
return m_stop_info_sp;
@@ -415,8 +415,8 @@ lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) {
// 4) If this thread wasn't allowed to run the last time round.
if (m_stop_info_sp) {
if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() ||
- GetCurrentPlan()->IsVirtualStep()
- || GetTemporaryResumeState() == eStateSuspended)
+ GetCurrentPlan()->IsVirtualStep() ||
+ GetTemporaryResumeState() == eStateSuspended)
SetStopInfo(m_stop_info_sp);
else
m_stop_info_sp.reset();
@@ -1204,7 +1204,7 @@ bool Thread::CompletedPlanOverridesBreakpoint() const {
return GetPlans().AnyCompletedPlans();
}
-ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{
+ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const {
return GetPlans().GetPreviousPlan(current_plan);
}
@@ -1294,10 +1294,11 @@ ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) {
}
ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads,
- Status &status) {
+ bool step_over, lldb::RunDirection direction, bool abort_other_plans,
+ bool stop_other_threads, Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
- *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
+ *this, step_over, direction, stop_other_threads, eVoteNoOpinion,
+ eVoteNoOpinion));
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -2250,7 +2251,7 @@ Status Thread::StepIn(bool source_step,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, run_mode, error);
+ false, eRunForward, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsControllingPlan(true);
@@ -2283,7 +2284,7 @@ Status Thread::StepOver(bool source_step,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, run_mode, error);
+ true, eRunForward, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsControllingPlan(true);
@@ -2322,22 +2323,6 @@ Status Thread::StepOut(uint32_t frame_idx) {
return error;
}
-#include "lldb/Target/ThreadPlanStepInstruction.h"
-
-class ThreadPlanStepBackInstruction : public ThreadPlanStepInstruction {
-public:
- ThreadPlanStepBackInstruction(Thread &thread,
- bool step_over,
- bool stop_other_threads,
- Vote report_stop_vote,
- Vote report_run_vote)
- : ThreadPlanStepInstruction(thread, step_over, stop_other_threads, report_stop_vote, report_run_vote) {}
-
- lldb::RunDirection GetDirection() const override {
- return lldb::RunDirection::eRunReverse;
- }
-};
-
Status Thread::StepBack() {
Process *process = GetProcess().get();
if (!StateIsStoppedState(process->GetState(), true)) {
@@ -2345,11 +2330,13 @@ Status Thread::StepBack() {
}
if (!process->SupportsReverseDirection()) {
- return Status::FromErrorString("process does not support reverse execution");
+ return Status::FromErrorString(
+ "process does not support reverse execution");
}
-
- ThreadPlanSP thread_plan_sp(new ThreadPlanStepBackInstruction(
- *this, false, true, eVoteNoOpinion, eVoteNoOpinion));
+
+ Status error;
+ ThreadPlanSP thread_plan_sp(QueueThreadPlanForStepSingleInstruction(
+ false, eRunReverse, false, true, error));
QueueThreadPlan(thread_plan_sp, false);
thread_plan_sp->SetIsControllingPlan(true);
@@ -2415,7 +2402,9 @@ lldb::ValueObjectSP Thread::GetSiginfoValue() {
return ValueObjectConstResult::Create(&target,
Status::FromError(data.takeError()));
- DataExtractor data_extractor{data.get()->getBufferStart(), data.get()->getBufferSize(),
- process_sp->GetByteOrder(), arch.GetAddressByteSize()};
- return ValueObjectConstResult::Create(&target, type, ConstString("__lldb_siginfo"), data_extractor);
+ DataExtractor data_extractor{
+ data.get()->getBufferStart(), data.get()->getBufferSize(),
+ process_sp->GetByteOrder(), arch.GetAddressByteSize()};
+ return ValueObjectConstResult::Create(
+ &target, type, ConstString("__lldb_siginfo"), data_extractor);
}
diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp
index e9db3171a5bef..ace663f59841a 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -20,16 +20,14 @@ using namespace lldb_private;
// ThreadPlanStepInstruction: Step over the current instruction
-ThreadPlanStepInstruction::ThreadPlanStepInstruction(Thread &thread,
- bool step_over,
- bool stop_other_threads,
- Vote report_stop_vote,
- Vote report_run_vote)
+ThreadPlanStepInstruction::ThreadPlanStepInstruction(
+ Thread &thread, bool step_over, lldb::RunDirection direction,
+ bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote)
: ThreadPlan(ThreadPlan::eKindStepInstruction,
"Step over single instruction", thread, report_stop_vote,
report_run_vote),
m_instruction_addr(0), m_stop_other_threads(stop_other_threads),
- m_step_over(step_over) {
+ m_step_over(step_over), m_direction(direction) {
m_takes_iteration_count = true;
SetUpState();
}
@@ -246,3 +244,7 @@ bool ThreadPlanStepInstruction::MischiefManaged() {
return false;
}
}
+
+lldb::RunDirection ThreadPlanStepInstruction::GetDirection() const {
+ return m_direction;
+}
More information about the lldb-commits
mailing list