[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
Fri Apr 10 11:16:47 PDT 2026


https://github.com/MaartenS11 updated https://github.com/llvm/llvm-project/pull/191183

>From 05450f4e063810c79e27830cf30d3c16f9031210 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/9] 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 e264161c881f1..8e8885908b2aa 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 8e188a483fa5c2d82be4a4b3246fb348edd6fc3b 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/9] 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 8e8885908b2aa..ee009679df3e2 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 00d4ed398a62489a4858027558b249943dca9e17 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/9] 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 4353725ca47f6..0f86223b493f2 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 ee009679df3e2..7a8482a88fa18 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 c199fd236f5cd..209488ba35885 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -2331,6 +2331,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 20deabf644f8067f7d71d45c6c096910826cbd21 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/9] 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 9f4de72fd1bf3..b03bc8343d958 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -815,6 +815,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 {
@@ -2774,6 +2794,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 abbc2992b19e8..9b13032b0dcdb 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 7a8482a88fa18..e264161c881f1 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 97b06d973f1a44861600277c3fcda91bce3f4c74 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/9] 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 0f86223b493f2..f8c0398a90d31 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 8f672ae539780..d1eece1eae064 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 b03bc8343d958..ec211eb8d21fc 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -719,7 +719,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();
 
@@ -732,13 +733,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,
@@ -815,26 +823,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 {
@@ -2795,8 +2783,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 209488ba35885..067de6673511c 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;
 }
@@ -2259,7 +2260,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);
@@ -2292,7 +2293,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);
@@ -2331,22 +2332,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)) {
@@ -2354,11 +2339,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);
@@ -2424,7 +2411,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;
+}

>From d723878cafb0b21af2568cc5f70ea6d712195bea Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 15:30:05 +0200
Subject: [PATCH 6/9] Add assertion to ensure we don't allow step over +
 backwards execution

---
 lldb/source/Target/ThreadPlanStepInstruction.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp
index ace663f59841a..6a7cd9c2920e3 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -28,6 +28,8 @@ ThreadPlanStepInstruction::ThreadPlanStepInstruction(
                  report_run_vote),
       m_instruction_addr(0), m_stop_other_threads(stop_other_threads),
       m_step_over(step_over), m_direction(direction) {
+  // We don't support step_over when the direction equals eRunReverse.
+  assert(!step_over || direction == eRunForward);
   m_takes_iteration_count = true;
   SetUpState();
 }

>From 8ed9c67ed7fe0d68fc83f001a6c7330b430337b5 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 17:35:04 +0200
Subject: [PATCH 7/9] Stop stepping back if LLDB hits a history boundary

---
 lldb/source/Target/ThreadPlanStepInstruction.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp
index 6a7cd9c2920e3..79e264c179023 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -213,6 +213,13 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
     }
   } else {
     lldb::addr_t pc_addr = thread.GetRegisterContext()->GetPC(0);
+
+    if (m_direction == eRunReverse &&
+        eStopReasonHistoryBoundary == thread.GetStopReason()) {
+      SetPlanComplete();
+      return true;
+    }
+
     if (pc_addr != m_instruction_addr) {
       if (--m_iteration_count <= 0) {
         SetPlanComplete();

>From 114db85e8c01d12fabbf078a7caebfd9aacce50d Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Thu, 9 Apr 2026 17:53:46 +0200
Subject: [PATCH 8/9] Document the additional direction parameter for
 QueueThreadPlanForStepSingleInstruction

---
 lldb/include/lldb/Target/Thread.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index f8c0398a90d31..dc3d9683e9ff6 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -715,6 +715,9 @@ class Thread : public std::enable_shared_from_this<Thread>,
   /// \param[in] step_over
   ///    \b true if we step over calls to functions, false if we step in.
   ///
+  /// \param[in] direction
+  ///    The direction in which a step will be taken.
+  ///
   /// \param[in] abort_other_plans
   ///    \b true if we discard the currently queued plans and replace them with
   ///    this one.

>From 7afb82f315f9aa5abaf423fecc8e81e1affbb887 Mon Sep 17 00:00:00 2001
From: MaartenS11 <maarten.steevens at gmail.com>
Date: Fri, 10 Apr 2026 20:03:53 +0200
Subject: [PATCH 9/9] First set of changes based on feedback

- StepBack -> StepBackInstruction
- Remove accidental formatting changes from Thread.cpp
- Use ValidatePlan instead of an assert in the constructor
---
 lldb/include/lldb/Target/Thread.h             |  2 +-
 lldb/source/Target/Thread.cpp                 | 28 +++++++++----------
 .../Target/ThreadPlanStepInstruction.cpp      |  8 ++----
 3 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index dc3d9683e9ff6..82b01553c5ffc 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -634,7 +634,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
   /// This function is designed to be used by commands where the
   /// process is publicly stopped.
   ///
-  virtual Status StepBack();
+  virtual Status StepBackInstruction();
 
   /// Retrieves the per-thread data area.
   /// Most OSs maintain a per-thread pointer (e.g. the FS register on
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 067de6673511c..c4a7749c72184 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);
 }
 
@@ -2332,7 +2332,7 @@ Status Thread::StepOut(uint32_t frame_idx) {
   return error;
 }
 
-Status Thread::StepBack() {
+Status Thread::StepBackInstruction() {
   Process *process = GetProcess().get();
   if (!StateIsStoppedState(process->GetState(), true)) {
     return Status::FromErrorString("process not stopped");
@@ -2411,9 +2411,7 @@ 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 79e264c179023..6d4bdda5e0dc3 100644
--- a/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -28,8 +28,6 @@ ThreadPlanStepInstruction::ThreadPlanStepInstruction(
                  report_run_vote),
       m_instruction_addr(0), m_stop_other_threads(stop_other_threads),
       m_step_over(step_over), m_direction(direction) {
-  // We don't support step_over when the direction equals eRunReverse.
-  assert(!step_over || direction == eRunForward);
   m_takes_iteration_count = true;
   SetUpState();
 }
@@ -81,9 +79,9 @@ void ThreadPlanStepInstruction::GetDescription(Stream *s,
 }
 
 bool ThreadPlanStepInstruction::ValidatePlan(Stream *error) {
-  // Since we read the instruction we're stepping over from the thread, this
-  // plan will always work.
-  return true;
+  // The plan is always valid when going forward, when going backwards only step
+  // into is supported.
+  return m_direction == eRunForward || !m_step_over;
 }
 
 bool ThreadPlanStepInstruction::DoPlanExplainsStop(Event *event_ptr) {



More information about the lldb-commits mailing list