[Lldb-commits] [lldb] Revert "[lldb] Implement basic support for reverse-continue" (PR #123906)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Jan 22 00:42:44 PST 2025


https://github.com/labath created https://github.com/llvm/llvm-project/pull/123906

Reverts llvm/llvm-project#112079 due to failures on the arm bot.

>From bd56b86b4abf44432842427272bd1ff71f169e98 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Wed, 22 Jan 2025 09:42:13 +0100
Subject: [PATCH] Revert "[lldb] Implement basic support for reverse-continue
 (#112079)"

This reverts commit b7b9ccf44988edf49886743ae5c3cf4184db211f.
---
 lldb/include/lldb/API/SBProcess.h             |   1 -
 lldb/include/lldb/Target/Process.h            |  28 +-
 lldb/include/lldb/Target/StopInfo.h           |   7 -
 lldb/include/lldb/Target/Thread.h             |   9 +-
 lldb/include/lldb/Target/ThreadList.h         |   6 +-
 lldb/include/lldb/Target/ThreadPlan.h         |  13 -
 lldb/include/lldb/Target/ThreadPlanBase.h     |   2 -
 lldb/include/lldb/lldb-enumerations.h         |   6 -
 .../Python/lldbsuite/test/gdbclientutils.py   |   5 +-
 .../Python/lldbsuite/test/lldbgdbproxy.py     | 175 -------
 .../Python/lldbsuite/test/lldbreverse.py      | 492 ------------------
 .../Python/lldbsuite/test/lldbtest.py         |   2 -
 .../tools/lldb-server/lldbgdbserverutils.py   |  14 +-
 lldb/source/API/SBProcess.cpp                 |  12 -
 lldb/source/API/SBThread.cpp                  |   2 -
 .../source/Interpreter/CommandInterpreter.cpp |   3 +-
 .../Process/Linux/NativeThreadLinux.cpp       |   3 -
 .../Process/MacOSX-Kernel/ProcessKDP.cpp      |   8 +-
 .../Process/MacOSX-Kernel/ProcessKDP.h        |   2 +-
 .../Process/Windows/Common/ProcessWindows.cpp |   9 +-
 .../Process/Windows/Common/ProcessWindows.h   |   2 +-
 .../GDBRemoteCommunicationClient.cpp          |  20 -
 .../gdb-remote/GDBRemoteCommunicationClient.h |   6 -
 .../GDBRemoteCommunicationServerLLGS.cpp      |   1 -
 .../Process/gdb-remote/ProcessGDBRemote.cpp   |  98 +---
 .../Process/gdb-remote/ProcessGDBRemote.h     |   4 +-
 .../Process/scripted/ScriptedProcess.cpp      |   9 +-
 .../Process/scripted/ScriptedProcess.h        |   2 +-
 lldb/source/Target/Process.cpp                |  24 +-
 lldb/source/Target/StopInfo.cpp               |  28 -
 lldb/source/Target/Thread.cpp                 |   9 +-
 lldb/source/Target/ThreadList.cpp             |  32 +-
 lldb/source/Target/ThreadPlanBase.cpp         |   4 -
 .../reverse-execution/Makefile                |   3 -
 .../TestReverseContinueBreakpoints.py         | 149 ------
 .../TestReverseContinueNotSupported.py        |  31 --
 .../TestReverseContinueWatchpoints.py         | 130 -----
 .../functionalities/reverse-execution/main.c  |  25 -
 lldb/tools/lldb-dap/JSONUtils.cpp             |   3 -
 lldb/tools/lldb-dap/LLDBUtils.cpp             |   1 -
 40 files changed, 47 insertions(+), 1333 deletions(-)
 delete mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py
 delete mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py
 delete mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile
 delete mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
 delete mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py
 delete mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueWatchpoints.py
 delete mode 100644 lldb/test/API/functionalities/reverse-execution/main.c

diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index 882b8bd837131d..1624e02070b1b2 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -159,7 +159,6 @@ class LLDB_API SBProcess {
   lldb::SBError Destroy();
 
   lldb::SBError Continue();
-  lldb::SBError ContinueInDirection(lldb::RunDirection direction);
 
   lldb::SBError Stop();
 
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index b14eb3fbd91d00..a184e6dd891aff 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1089,13 +1089,6 @@ class Process : public std::enable_shared_from_this<Process>,
   ///     Returns an error object.
   virtual Status WillResume() { return Status(); }
 
-  /// Reports whether this process supports reverse execution.
-  ///
-  /// \return
-  ///     Returns true if the process supports reverse execution (at least
-  /// under some circumstances).
-  virtual bool SupportsReverseDirection() { return false; }
-
   /// Resumes all of a process's threads as configured using the Thread run
   /// control functions.
   ///
@@ -1111,13 +1104,9 @@ class Process : public std::enable_shared_from_this<Process>,
   /// \see Thread:Resume()
   /// \see Thread:Step()
   /// \see Thread:Suspend()
-  virtual Status DoResume(lldb::RunDirection direction) {
-    if (direction == lldb::RunDirection::eRunForward)
-      return Status::FromErrorStringWithFormatv(
-          "error: {0} does not support resuming processes", GetPluginName());
+  virtual Status DoResume() {
     return Status::FromErrorStringWithFormatv(
-        "error: {0} does not support reverse execution of processes",
-        GetPluginName());
+        "error: {0} does not support resuming processes", GetPluginName());
   }
 
   /// Called after resuming a process.
@@ -2687,18 +2676,6 @@ void PruneThreadPlans();
                             const AddressRange &range, size_t alignment,
                             Status &error);
 
-  /// Get the base run direction for the process.
-  /// The base direction is the direction the process will execute in
-  /// (forward or backward) if no thread plan overrides the direction.
-  lldb::RunDirection GetBaseDirection() const { return m_base_direction; }
-  /// Set the base run direction for the process.
-  /// As a side-effect, if this changes the base direction, then we
-  /// discard all non-base thread plans to ensure that when execution resumes
-  /// we definitely execute in the requested direction.
-  /// FIXME: this is overkill. In some situations ensuring the latter
-  /// would not require discarding all non-base thread plans.
-  void SetBaseDirection(lldb::RunDirection direction);
-
 protected:
   friend class Trace;
 
@@ -3098,7 +3075,6 @@ void PruneThreadPlans();
   ThreadList
       m_extended_thread_list; ///< Constituent for extended threads that may be
                               /// generated, cleared on natural stops
-  lldb::RunDirection m_base_direction; ///< ThreadPlanBase run direction
   uint32_t m_extended_thread_stop_id; ///< The natural stop id when
                                       ///extended_thread_list was last updated
   QueueList
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index 9a13371708be52..45beac129e86f7 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -20,7 +20,6 @@ namespace lldb_private {
 class StopInfo : public std::enable_shared_from_this<StopInfo> {
   friend class Process::ProcessEventData;
   friend class ThreadPlanBase;
-  friend class ThreadPlanReverseContinue;
 
 public:
   // Constructors and Destructors
@@ -155,12 +154,6 @@ class StopInfo : public std::enable_shared_from_this<StopInfo> {
   static lldb::StopInfoSP
   CreateStopReasonProcessorTrace(Thread &thread, const char *description);
 
-  // This creates a StopInfo indicating that execution stopped because
-  // it was replaying some recorded execution history, and execution reached
-  // the end of that recorded history.
-  static lldb::StopInfoSP
-  CreateStopReasonHistoryBoundary(Thread &thread, const char *description);
-
   static lldb::StopInfoSP CreateStopReasonFork(Thread &thread,
                                                lldb::pid_t child_pid,
                                                lldb::tid_t child_tid);
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index cd82ee7d756030..ef66fa11574db9 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -200,13 +200,14 @@ class Thread : public std::enable_shared_from_this<Thread>,
   ///    The User resume state for this thread.
   lldb::StateType GetResumeState() const { return m_resume_state; }
 
-  // This function is called to determine whether the thread needs to
-  // step over a breakpoint and if so, push a step-over-breakpoint thread
-  // plan.
+  /// This function is called on all the threads before "ShouldResume" and
+  /// "WillResume" in case a thread needs to change its state before the
+  /// ThreadList polls all the threads to figure out which ones actually will
+  /// get to run and how.
   ///
   /// \return
   ///    True if we pushed a ThreadPlanStepOverBreakpoint
-  bool SetupToStepOverBreakpointIfNeeded(lldb::RunDirection direction);
+  bool SetupForResume();
 
   // Do not override this function, it is for thread plan logic only
   bool ShouldResume(lldb::StateType resume_state);
diff --git a/lldb/include/lldb/Target/ThreadList.h b/lldb/include/lldb/Target/ThreadList.h
index c796975de60153..f931bb83a8ceaf 100644
--- a/lldb/include/lldb/Target/ThreadList.h
+++ b/lldb/include/lldb/Target/ThreadList.h
@@ -115,10 +115,6 @@ class ThreadList : public ThreadCollection {
   /// If a thread can "resume" without having to resume the target, it
   /// will return false for WillResume, and then the process will not be
   /// restarted.
-  /// Sets *direction to the run direction of the thread(s) that will
-  /// be resumed. If threads that we want to run disagree about the
-  /// direction, we execute forwards and pop any of the thread plans
-  /// that requested reverse execution.
   ///
   /// \return
   ///    \b true instructs the process to resume normally,
@@ -126,7 +122,7 @@ class ThreadList : public ThreadCollection {
   ///    the process will not actually run.  The thread must then return
   ///    the correct StopInfo when asked.
   ///
-  bool WillResume(lldb::RunDirection &direction);
+  bool WillResume();
 
   void DidResume();
 
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index a7bac8cc5ecf6c..d6da484f4fc137 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -283,15 +283,6 @@ namespace lldb_private {
 //  report_run_vote argument to the constructor works like report_stop_vote, and
 //  is a way for a plan to instruct a sub-plan on how to respond to
 //  ShouldReportStop.
-//
-//  Reverse execution:
-//
-//  Every thread plan has an associated RunDirection (forward or backward).
-//  For ThreadPlanBase, this direction is the Process's base direction.
-//  Whenever we resume the target, we need to ensure that the topmost thread
-//  plans for each runnable thread all agree on their direction. This is
-//  ensured in ThreadList::WillResume(), which chooses a direction and then
-//  discards thread plans incompatible with that direction.
 
 class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
                    public UserID {
@@ -506,10 +497,6 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
 
   virtual lldb::StateType GetPlanRunState() = 0;
 
-  virtual lldb::RunDirection GetDirection() const {
-    return lldb::RunDirection::eRunForward;
-  }
-
 protected:
   // Constructors and Destructors
   ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
diff --git a/lldb/include/lldb/Target/ThreadPlanBase.h b/lldb/include/lldb/Target/ThreadPlanBase.h
index f4418d779a4dab..5c44b9fb17b271 100644
--- a/lldb/include/lldb/Target/ThreadPlanBase.h
+++ b/lldb/include/lldb/Target/ThreadPlanBase.h
@@ -38,8 +38,6 @@ class ThreadPlanBase : public ThreadPlan {
 
   bool IsBasePlan() override { return true; }
 
-  lldb::RunDirection GetDirection() const override;
-
 protected:
   bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
   bool DoPlanExplainsStop(Event *event_ptr) override;
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 5f12e648684d7f..50d2233509de6f 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -135,9 +135,6 @@ FLAGS_ENUM(LaunchFlags){
 /// Thread Run Modes.
 enum RunMode { eOnlyThisThread, eAllThreads, eOnlyDuringStepping };
 
-/// Execution directions
-enum RunDirection { eRunForward, eRunReverse };
-
 /// Byte ordering definitions.
 enum ByteOrder {
   eByteOrderInvalid = 0,
@@ -257,9 +254,6 @@ enum StopReason {
   eStopReasonVFork,
   eStopReasonVForkDone,
   eStopReasonInterrupt, ///< Thread requested interrupt
-  // Indicates that execution stopped because the debugger backend relies
-  // on recorded data and we reached the end of that data.
-  eStopReasonHistoryBoundary,
 };
 
 /// Command Return Status Types.
diff --git a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
index 732d6171320680..1784487323ad6b 100644
--- a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -510,9 +510,8 @@ def start(self):
         self._thread.start()
 
     def stop(self):
-        if self._thread is not None:
-            self._thread.join()
-            self._thread = None
+        self._thread.join()
+        self._thread = None
 
     def get_connect_address(self):
         return self._socket.get_connect_address()
diff --git a/lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py b/lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py
deleted file mode 100644
index a84c80f155a0a4..00000000000000
--- a/lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import logging
-import os
-import os.path
-import random
-
-import lldb
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test.gdbclientutils import *
-import lldbgdbserverutils
-from lldbsuite.support import seven
-
-
-class GDBProxyTestBase(TestBase):
-    """
-    Base class for gdbserver proxy tests.
-
-    This class will setup and start a mock GDB server for the test to use.
-    It pases through requests to a regular lldb-server/debugserver and
-    forwards replies back to the LLDB under test.
-    """
-
-    """The gdbserver that we implement."""
-    server = None
-    """The inner lldb-server/debugserver process that we proxy requests into."""
-    monitor_server = None
-    monitor_sock = None
-
-    server_socket_class = TCPServerSocket
-
-    DEFAULT_TIMEOUT = 20 * (10 if ("ASAN_OPTIONS" in os.environ) else 1)
-
-    _verbose_log_handler = None
-    _log_formatter = logging.Formatter(fmt="%(asctime)-15s %(levelname)-8s %(message)s")
-
-    def setUpBaseLogging(self):
-        self.logger = logging.getLogger(__name__)
-
-        self.logger.propagate = False
-        self.logger.setLevel(logging.DEBUG)
-
-        # log all warnings to stderr
-        handler = logging.StreamHandler()
-        handler.setLevel(logging.WARNING)
-        handler.setFormatter(self._log_formatter)
-        self.logger.addHandler(handler)
-
-    def setUp(self):
-        TestBase.setUp(self)
-
-        self.setUpBaseLogging()
-
-        if self.isVerboseLoggingRequested():
-            # If requested, full logs go to a log file
-            log_file_name = self.getLogBasenameForCurrentTest() + "-proxy.log"
-            self._verbose_log_handler = logging.FileHandler(log_file_name)
-            self._verbose_log_handler.setFormatter(self._log_formatter)
-            self._verbose_log_handler.setLevel(logging.DEBUG)
-            self.logger.addHandler(self._verbose_log_handler)
-
-        if lldbplatformutil.getPlatform() == "macosx":
-            self.debug_monitor_exe = lldbgdbserverutils.get_debugserver_exe()
-            self.debug_monitor_extra_args = []
-        else:
-            self.debug_monitor_exe = lldbgdbserverutils.get_lldb_server_exe()
-            self.debug_monitor_extra_args = ["gdbserver"]
-        self.assertIsNotNone(self.debug_monitor_exe)
-
-        self.server = MockGDBServer(self.server_socket_class())
-        self.server.responder = self
-
-    def tearDown(self):
-        # TestBase.tearDown will kill the process, but we need to kill it early
-        # so its client connection closes and we can stop the server before
-        # finally calling the base tearDown.
-        if self.process() is not None:
-            self.process().Kill()
-        self.server.stop()
-
-        self.logger.removeHandler(self._verbose_log_handler)
-        self._verbose_log_handler = None
-
-        TestBase.tearDown(self)
-
-    def isVerboseLoggingRequested(self):
-        # We will report our detailed logs if the user requested that the "gdb-remote" channel is
-        # logged.
-        return any(("gdb-remote" in channel) for channel in lldbtest_config.channels)
-
-    def connect(self, target):
-        """
-        Create a process by connecting to the mock GDB server.
-        """
-        self.prep_debug_monitor_and_inferior()
-        self.server.start()
-
-        listener = self.dbg.GetListener()
-        error = lldb.SBError()
-        process = target.ConnectRemote(
-            listener, self.server.get_connect_url(), "gdb-remote", error
-        )
-        self.assertTrue(error.Success(), error.description)
-        self.assertTrue(process, PROCESS_IS_VALID)
-        return process
-
-    def prep_debug_monitor_and_inferior(self):
-        inferior_exe_path = self.getBuildArtifact("a.out")
-        self.connect_to_debug_monitor([inferior_exe_path])
-        self.assertIsNotNone(self.monitor_server)
-        self.initial_handshake()
-
-    def initial_handshake(self):
-        self.monitor_server.send_packet(seven.bitcast_to_bytes("+"))
-        reply = seven.bitcast_to_string(self.monitor_server.get_normal_packet())
-        self.assertEqual(reply, "+")
-        self.monitor_server.send_packet(seven.bitcast_to_bytes("QStartNoAckMode"))
-        reply = seven.bitcast_to_string(self.monitor_server.get_normal_packet())
-        self.assertEqual(reply, "+")
-        reply = seven.bitcast_to_string(self.monitor_server.get_normal_packet())
-        self.assertEqual(reply, "OK")
-        self.monitor_server.set_validate_checksums(False)
-        self.monitor_server.send_packet(seven.bitcast_to_bytes("+"))
-        reply = seven.bitcast_to_string(self.monitor_server.get_normal_packet())
-        self.assertEqual(reply, "+")
-
-    def get_debug_monitor_command_line_args(self, connect_address, launch_args):
-        return (
-            self.debug_monitor_extra_args
-            + ["--reverse-connect", connect_address]
-            + launch_args
-        )
-
-    def launch_debug_monitor(self, launch_args):
-        family, type, proto, _, addr = socket.getaddrinfo(
-            "localhost", 0, proto=socket.IPPROTO_TCP
-        )[0]
-        sock = socket.socket(family, type, proto)
-        sock.settimeout(self.DEFAULT_TIMEOUT)
-        sock.bind(addr)
-        sock.listen(1)
-        addr = sock.getsockname()
-        connect_address = "[{}]:{}".format(*addr)
-
-        commandline_args = self.get_debug_monitor_command_line_args(
-            connect_address, launch_args
-        )
-
-        # Start the server.
-        self.logger.info(f"Spawning monitor {commandline_args}")
-        monitor_process = self.spawnSubprocess(
-            self.debug_monitor_exe, commandline_args, install_remote=False
-        )
-        self.assertIsNotNone(monitor_process)
-
-        self.monitor_sock = sock.accept()[0]
-        self.monitor_sock.settimeout(self.DEFAULT_TIMEOUT)
-        return monitor_process
-
-    def connect_to_debug_monitor(self, launch_args):
-        monitor_process = self.launch_debug_monitor(launch_args)
-        # Turn off checksum validation because debugserver does not produce
-        # correct checksums.
-        self.monitor_server = lldbgdbserverutils.Server(
-            self.monitor_sock, monitor_process
-        )
-
-    def respond(self, packet):
-        """Subclasses can override this to change how packets are handled."""
-        return self.pass_through(packet)
-
-    def pass_through(self, packet):
-        self.logger.info(f"Sending packet {packet}")
-        self.monitor_server.send_packet(seven.bitcast_to_bytes(packet))
-        reply = seven.bitcast_to_string(self.monitor_server.get_normal_packet())
-        self.logger.info(f"Received reply {reply}")
-        return reply
diff --git a/lldb/packages/Python/lldbsuite/test/lldbreverse.py b/lldb/packages/Python/lldbsuite/test/lldbreverse.py
deleted file mode 100644
index bf95667f0094d8..00000000000000
--- a/lldb/packages/Python/lldbsuite/test/lldbreverse.py
+++ /dev/null
@@ -1,492 +0,0 @@
-import os
-import os.path
-import lldb
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test.gdbclientutils import *
-from lldbsuite.test.lldbgdbproxy import *
-import lldbgdbserverutils
-import re
-
-
-class ThreadSnapshot:
-    def __init__(self, thread_id, registers):
-        self.thread_id = thread_id
-        self.registers = registers
-
-
-class MemoryBlockSnapshot:
-    def __init__(self, address, data):
-        self.address = address
-        self.data = data
-
-
-class StateSnapshot:
-    def __init__(self, thread_snapshots, memory):
-        self.thread_snapshots = thread_snapshots
-        self.memory = memory
-        self.thread_id = None
-
-
-class RegisterInfo:
-    def __init__(self, lldb_index, bitsize, little_endian):
-        self.lldb_index = lldb_index
-        self.bitsize = bitsize
-        self.little_endian = little_endian
-
-
-BELOW_STACK_POINTER = 16384
-ABOVE_STACK_POINTER = 4096
-
-BLOCK_SIZE = 1024
-
-SOFTWARE_BREAKPOINTS = 0
-HARDWARE_BREAKPOINTS = 1
-WRITE_WATCHPOINTS = 2
-
-
-class ReverseTestBase(GDBProxyTestBase):
-    """
-    Base class for tests that need reverse execution.
-
-    This class uses a gdbserver proxy to add very limited reverse-
-    execution capability to lldb-server/debugserver for testing
-    purposes only.
-
-    To use this class, run the inferior forward until some stopping point.
-    Then call `start_recording()` and execute forward again until reaching
-    a software breakpoint; this class records the state before each execution executes.
-    At that point, the server will accept "bc" and "bs" packets to step
-    backwards through the state.
-    When executing during recording, we only allow single-step and continue without
-    delivering a signal, and only software breakpoint stops are allowed.
-
-    We assume that while recording is enabled, the only effects of instructions
-    are on general-purpose registers (read/written by the 'g' and 'G' packets)
-    and on memory bytes between [SP - BELOW_STACK_POINTER, SP + ABOVE_STACK_POINTER).
-    """
-
-    NO_DEBUG_INFO_TESTCASE = True
-
-    """
-    A list of StateSnapshots in time order.
-
-    There is one snapshot per single-stepped instruction,
-    representing the state before that instruction was
-    executed. The last snapshot in the list is the
-    snapshot before the last instruction was executed.
-    This is an undo log; we snapshot a superset of the state that may have
-    been changed by the instruction's execution.
-    """
-    snapshots = None
-    recording_enabled = False
-
-    breakpoints = None
-
-    pc_register_info = None
-    sp_register_info = None
-    general_purpose_register_info = None
-
-    def __init__(self, *args, **kwargs):
-        GDBProxyTestBase.__init__(self, *args, **kwargs)
-        self.breakpoints = [set(), set(), set(), set(), set()]
-
-    def respond(self, packet):
-        if not packet:
-            raise ValueError("Invalid empty packet")
-        if packet == self.server.PACKET_INTERRUPT:
-            # Don't send a response. We'll just run to completion.
-            return []
-        if self.is_command(packet, "qSupported", ":"):
-            # Disable multiprocess support in the server and in LLDB
-            # since Mac debugserver doesn't support it and we want lldb-server to
-            # be consistent with that
-            reply = self.pass_through(packet.replace(";multiprocess", ""))
-            return reply.replace(";multiprocess", "") + ";ReverseStep+;ReverseContinue+"
-        if packet == "c" or packet == "s":
-            packet = "vCont;" + packet
-        elif (
-            packet[0] == "c" or packet[0] == "s" or packet[0] == "C" or packet[0] == "S"
-        ):
-            raise ValueError(
-                "Old-style continuation packets with address or signal not supported yet"
-            )
-        if self.is_command(packet, "vCont", ";"):
-            if self.recording_enabled:
-                return self.continue_with_recording(packet)
-            snapshots = []
-        if packet == "bc":
-            return self.reverse_continue()
-        if packet == "bs":
-            return self.reverse_step()
-        if packet == "jThreadsInfo":
-            # Suppress this because it contains thread stop reasons which we might
-            # need to modify, and we don't want to have to implement that.
-            return ""
-        if packet[0] == "z" or packet[0] == "Z":
-            reply = self.pass_through(packet)
-            if reply == "OK":
-                self.update_breakpoints(packet)
-            return reply
-        return GDBProxyTestBase.respond(self, packet)
-
-    def start_recording(self):
-        self.recording_enabled = True
-        self.snapshots = []
-
-    def stop_recording(self):
-        """
-        Don't record when executing foward.
-
-        Reverse execution is still supported until the next forward continue.
-        """
-        self.recording_enabled = False
-
-    def is_command(self, packet, cmd, follow_token):
-        return packet == cmd or packet[0 : len(cmd) + 1] == cmd + follow_token
-
-    def update_breakpoints(self, packet):
-        m = re.match("([zZ])([01234]),([0-9a-f]+),([0-9a-f]+)", packet)
-        if m is None:
-            raise ValueError("Invalid breakpoint packet: " + packet)
-        t = int(m.group(2))
-        addr = int(m.group(3), 16)
-        kind = int(m.group(4), 16)
-        if m.group(1) == "Z":
-            self.breakpoints[t].add((addr, kind))
-        else:
-            self.breakpoints[t].discard((addr, kind))
-
-    def breakpoint_triggered_at(self, pc):
-        if any(addr == pc for addr, kind in self.breakpoints[SOFTWARE_BREAKPOINTS]):
-            return True
-        if any(addr == pc for addr, kind in self.breakpoints[HARDWARE_BREAKPOINTS]):
-            return True
-        return False
-
-    def watchpoint_triggered(self, new_value_block, current_contents):
-        """Returns the address or None."""
-        for watch_addr, kind in self.breakpoints[WRITE_WATCHPOINTS]:
-            for offset in range(0, kind):
-                addr = watch_addr + offset
-                if (
-                    addr >= new_value_block.address
-                    and addr < new_value_block.address + len(new_value_block.data)
-                ):
-                    index = addr - new_value_block.address
-                    if (
-                        new_value_block.data[index * 2 : (index + 1) * 2]
-                        != current_contents[index * 2 : (index + 1) * 2]
-                    ):
-                        return watch_addr
-        return None
-
-    def continue_with_recording(self, packet):
-        self.logger.debug("Continue with recording enabled")
-
-        step_packet = "vCont;s"
-        if packet == "vCont":
-            requested_step = False
-        else:
-            m = re.match("vCont;(c|s)(.*)", packet)
-            if m is None:
-                raise ValueError("Unsupported vCont packet: " + packet)
-            requested_step = m.group(1) == "s"
-            step_packet += m.group(2)
-
-        while True:
-            snapshot = self.capture_snapshot()
-            reply = self.pass_through(step_packet)
-            (stop_signal, stop_pairs) = self.parse_stop_reply(reply)
-            if stop_signal != 5:
-                raise ValueError("Unexpected stop signal: " + reply)
-            is_swbreak = False
-            thread_id = None
-            for key, value in stop_pairs.items():
-                if key == "thread":
-                    thread_id = self.parse_thread_id(value)
-                    continue
-                if re.match("[0-9a-f]+", key):
-                    continue
-                if key == "swbreak" or (key == "reason" and value == "breakpoint"):
-                    is_swbreak = True
-                    continue
-                if key == "metype":
-                    reason = self.stop_reason_from_mach_exception(stop_pairs)
-                    if reason == "breakpoint":
-                        is_swbreak = True
-                    elif reason != "singlestep":
-                        raise ValueError(f"Unsupported stop reason in {reply}")
-                    continue
-                if key in [
-                    "name",
-                    "threads",
-                    "thread-pcs",
-                    "reason",
-                    "mecount",
-                    "medata",
-                    "memory",
-                ]:
-                    continue
-                raise ValueError(f"Unknown stop key '{key}' in {reply}")
-            if is_swbreak:
-                self.logger.debug("Recording stopped")
-                return reply
-            if thread_id is None:
-                return ValueError("Expected thread ID: " + reply)
-            snapshot.thread_id = thread_id
-            self.snapshots.append(snapshot)
-            if requested_step:
-                self.logger.debug("Recording stopped for step")
-                return reply
-
-    def stop_reason_from_mach_exception(self, stop_pairs):
-        # See StopInfoMachException::CreateStopReasonWithMachException.
-        if int(stop_pairs["metype"]) != 6:  # EXC_BREAKPOINT
-            raise ValueError(f"Unsupported exception type {value} in {reply}")
-        medata = stop_pairs["medata"]
-        arch = self.getArchitecture()
-        if arch in ["amd64", "i386", "x86_64"]:
-            if int(medata[0], 16) == 2:
-                return "breakpoint"
-            if int(medata[0], 16) == 1 and int(medata[1], 16) == 0:
-                return "singlestep"
-        elif arch in ["arm64", "arm64e"]:
-            if int(medata[0], 16) == 1 and int(medata[1], 16) != 0:
-                return "breakpoint"
-            elif int(medata[0], 16) == 1 and int(medata[1], 16) == 0:
-                return "singlestep"
-        else:
-            raise ValueError(f"Unsupported architecture '{arch}'")
-        raise ValueError(f"Unsupported exception details in {reply}")
-
-    def parse_stop_reply(self, reply):
-        if not reply:
-            raise ValueError("Invalid empty packet")
-        if reply[0] == "T" and len(reply) >= 3:
-            result = {}
-            for k, v in self.parse_pairs(reply[3:]):
-                if k in ["medata", "memory"]:
-                    if k in result:
-                        result[k].append(v)
-                    else:
-                        result[k] = [v]
-                else:
-                    result[k] = v
-            return (int(reply[1:3], 16), result)
-        raise ValueError("Unsupported stop reply: " + reply)
-
-    def parse_pairs(self, text):
-        for pair in text.split(";"):
-            if not pair:
-                continue
-            m = re.match("([^:]+):(.*)", pair)
-            if m is None:
-                raise ValueError("Invalid pair text: " + text)
-            yield (m.group(1), m.group(2))
-
-    def capture_snapshot(self):
-        """Snapshot all threads and their stack memories."""
-        self.ensure_register_info()
-        current_thread = self.get_current_thread()
-        thread_snapshots = []
-        memory = []
-        for thread_id in self.get_thread_list():
-            registers = {}
-            for index in sorted(self.general_purpose_register_info.keys()):
-                reply = self.pass_through(f"p{index:x};thread:{thread_id:x};")
-                if reply == "" or reply[0] == "E":
-                    raise ValueError("Can't read register")
-                registers[index] = reply
-            thread_snapshot = ThreadSnapshot(thread_id, registers)
-            thread_sp = self.get_register(
-                self.sp_register_info, thread_snapshot.registers
-            )
-            memory += self.read_memory(
-                thread_sp - BELOW_STACK_POINTER, thread_sp + ABOVE_STACK_POINTER
-            )
-            thread_snapshots.append(thread_snapshot)
-        self.set_current_thread(current_thread)
-        return StateSnapshot(thread_snapshots, memory)
-
-    def restore_snapshot(self, snapshot):
-        """
-        Restore the snapshot during reverse execution.
-
-        If this triggers a breakpoint or watchpoint, return the stop reply,
-        otherwise None.
-        """
-        current_thread = self.get_current_thread()
-        stop_reasons = []
-        for thread_snapshot in snapshot.thread_snapshots:
-            thread_id = thread_snapshot.thread_id
-            for lldb_index in sorted(thread_snapshot.registers.keys()):
-                data = thread_snapshot.registers[lldb_index]
-                reply = self.pass_through(
-                    f"P{lldb_index:x}={data};thread:{thread_id:x};"
-                )
-                if reply != "OK":
-                    raise ValueError("Can't restore thread register")
-            if thread_id == snapshot.thread_id:
-                new_pc = self.get_register(
-                    self.pc_register_info, thread_snapshot.registers
-                )
-                if self.breakpoint_triggered_at(new_pc):
-                    stop_reasons.append([("reason", "breakpoint")])
-        self.set_current_thread(current_thread)
-        for block in snapshot.memory:
-            current_memory = self.pass_through(
-                f"m{block.address:x},{(len(block.data)//2):x}"
-            )
-            if not current_memory or current_memory[0] == "E":
-                raise ValueError("Can't read back memory")
-            reply = self.pass_through(
-                f"M{block.address:x},{len(block.data)//2:x}:" + block.data
-            )
-            if reply != "OK":
-                raise ValueError("Can't restore memory")
-            watch_addr = self.watchpoint_triggered(block, current_memory)
-            if watch_addr is not None:
-                stop_reasons.append(
-                    [("reason", "watchpoint"), ("watch", f"{watch_addr:x}")]
-                )
-        if stop_reasons:
-            pairs = ";".join(f"{key}:{value}" for key, value in stop_reasons[0])
-            return f"T05thread:{snapshot.thread_id:x};{pairs};"
-        return None
-
-    def reverse_step(self):
-        if not self.snapshots:
-            self.logger.debug("Reverse-step at history boundary")
-            return self.history_boundary_reply(self.get_current_thread())
-        self.logger.debug("Reverse-step started")
-        snapshot = self.snapshots.pop()
-        stop_reply = self.restore_snapshot(snapshot)
-        self.set_current_thread(snapshot.thread_id)
-        self.logger.debug("Reverse-step stopped")
-        if stop_reply is None:
-            return self.singlestep_stop_reply(snapshot.thread_id)
-        return stop_reply
-
-    def reverse_continue(self):
-        self.logger.debug("Reverse-continue started")
-        thread_id = None
-        while self.snapshots:
-            snapshot = self.snapshots.pop()
-            stop_reply = self.restore_snapshot(snapshot)
-            thread_id = snapshot.thread_id
-            if stop_reply is not None:
-                self.set_current_thread(thread_id)
-                self.logger.debug("Reverse-continue stopped")
-                return stop_reply
-        if thread_id is None:
-            thread_id = self.get_current_thread()
-        else:
-            self.set_current_thread(snapshot.thread_id)
-        self.logger.debug("Reverse-continue stopped at history boundary")
-        return self.history_boundary_reply(thread_id)
-
-    def get_current_thread(self):
-        reply = self.pass_through("qC")
-        return self.parse_thread_id(reply[2:])
-
-    def parse_thread_id(self, thread_id):
-        m = re.match("([0-9a-f]+)", thread_id)
-        if m is None:
-            raise ValueError("Invalid thread ID: " + thread_id)
-        return int(m.group(1), 16)
-
-    def history_boundary_reply(self, thread_id):
-        return f"T00thread:{thread_id:x};replaylog:begin;"
-
-    def singlestep_stop_reply(self, thread_id):
-        return f"T05thread:{thread_id:x};"
-
-    def set_current_thread(self, thread_id):
-        """
-        Set current thread in inner gdbserver.
-        """
-        if thread_id >= 0:
-            self.pass_through(f"Hg{thread_id:x}")
-            self.pass_through(f"Hc{thread_id:x}")
-        else:
-            self.pass_through(f"Hc-1")
-            self.pass_through(f"Hg-1")
-
-    def get_register(self, register_info, registers):
-        if register_info.bitsize % 8 != 0:
-            raise ValueError("Register size must be a multiple of 8 bits")
-        if register_info.lldb_index not in registers:
-            raise ValueError("Register value not captured")
-        data = registers[register_info.lldb_index]
-        num_bytes = register_info.bitsize // 8
-        bytes = []
-        for i in range(0, num_bytes):
-            bytes.append(int(data[i * 2 : (i + 1) * 2], 16))
-        if register_info.little_endian:
-            bytes.reverse()
-        result = 0
-        for byte in bytes:
-            result = (result << 8) + byte
-        return result
-
-    def read_memory(self, start_addr, end_addr):
-        """
-        Read a region of memory from the target.
-
-        Some of the addresses may extend into invalid virtual memory;
-        skip those areas.
-        Return a list of blocks containing the valid area(s) in the
-        requested range.
-        """
-        regions = []
-        start_addr = start_addr - (start_addr % BLOCK_SIZE)
-        if end_addr % BLOCK_SIZE > 0:
-            end_addr = end_addr - (end_addr % BLOCK_SIZE) + BLOCK_SIZE
-        for addr in range(start_addr, end_addr, BLOCK_SIZE):
-            reply = self.pass_through(f"m{addr:x},{(BLOCK_SIZE - 1):x}")
-            if reply and reply[0] != "E":
-                block = MemoryBlockSnapshot(addr, reply)
-                regions.append(block)
-        return regions
-
-    def ensure_register_info(self):
-        if self.general_purpose_register_info is not None:
-            return
-        reply = self.pass_through("qHostInfo")
-        little_endian = any(
-            kv == ("endian", "little") for kv in self.parse_pairs(reply)
-        )
-        self.general_purpose_register_info = {}
-        lldb_index = 0
-        while True:
-            reply = self.pass_through(f"qRegisterInfo{lldb_index:x}")
-            if not reply or reply[0] == "E":
-                break
-            info = {k: v for k, v in self.parse_pairs(reply)}
-            reg_info = RegisterInfo(lldb_index, int(info["bitsize"]), little_endian)
-            if (
-                info["set"] == "General Purpose Registers"
-                and not "container-regs" in info
-            ):
-                self.general_purpose_register_info[lldb_index] = reg_info
-            if "generic" in info:
-                if info["generic"] == "pc":
-                    self.pc_register_info = reg_info
-                elif info["generic"] == "sp":
-                    self.sp_register_info = reg_info
-            lldb_index += 1
-        if self.pc_register_info is None or self.sp_register_info is None:
-            raise ValueError("Can't find generic pc or sp register")
-
-    def get_thread_list(self):
-        threads = []
-        reply = self.pass_through("qfThreadInfo")
-        while True:
-            if not reply:
-                raise ValueError("Missing reply packet")
-            if reply[0] == "m":
-                for id in reply[1:].split(","):
-                    threads.append(self.parse_thread_id(id))
-            elif reply[0] == "l":
-                return threads
-            reply = self.pass_through("qsThreadInfo")
diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index b0d2a27dba0eef..81b286340560dc 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -143,8 +143,6 @@
 
 STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
 
-STOPPED_DUE_TO_HISTORY_BOUNDARY = "Process should be stopped due to history boundary"
-
 DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
 
 VALID_BREAKPOINT = "Got a valid breakpoint"
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
index fc552ef887ce58..94376a16d39f6a 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
@@ -863,7 +863,6 @@ def __init__(self, sock, proc=None):
         self._output_queue = []
         self._sock = sock
         self._proc = proc
-        self._validate_checksums = True
 
     def send_raw(self, frame):
         self._sock.sendall(frame)
@@ -874,9 +873,6 @@ def send_ack(self):
     def send_packet(self, packet):
         self.send_raw(b"$%s#%02x" % (packet, self._checksum(packet)))
 
-    def set_validate_checksums(self, validate):
-        self._validate_checksums = validate
-
     @staticmethod
     def _checksum(packet):
         checksum = 0
@@ -935,12 +931,12 @@ def get_raw_output_packet(self):
     def get_raw_normal_packet(self):
         return self._read(self._normal_queue)
 
-    def _get_payload(self, frame):
+    @staticmethod
+    def _get_payload(frame):
         payload = frame[1:-3]
-        if self._validate_checksums:
-            checksum = int(frame[-2:], 16)
-            if checksum != Server._checksum(payload):
-                raise ChecksumMismatch
+        checksum = int(frame[-2:], 16)
+        if checksum != Server._checksum(payload):
+            raise ChecksumMismatch
         return payload
 
     def get_normal_packet(self):
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 23ea449b30ccad..9773144723c34c 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -583,18 +583,6 @@ SBError SBProcess::Continue() {
   return sb_error;
 }
 
-SBError SBProcess::ContinueInDirection(RunDirection direction) {
-  if (ProcessSP process_sp = GetSP()) {
-    if (direction == RunDirection::eRunReverse &&
-        !process_sp->SupportsReverseDirection())
-      return Status::FromErrorStringWithFormatv(
-          "error: {0} does not support reverse execution of processes",
-          GetPluginName());
-    process_sp->SetBaseDirection(direction);
-  }
-  return Continue();
-}
-
 SBError SBProcess::Destroy() {
   LLDB_INSTRUMENT_VA(this);
 
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index d9469fc1390d62..cc848076dab5fa 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -172,7 +172,6 @@ size_t SBThread::GetStopReasonDataCount() {
         case eStopReasonInstrumentation:
         case eStopReasonProcessorTrace:
         case eStopReasonVForkDone:
-        case eStopReasonHistoryBoundary:
           // There is no data for these stop reasons.
           return 0;
 
@@ -234,7 +233,6 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
         case eStopReasonInstrumentation:
         case eStopReasonProcessorTrace:
         case eStopReasonVForkDone:
-        case eStopReasonHistoryBoundary:
           // There is no data for these stop reasons.
           return 0;
 
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 284955a65a4429..764dcfd1903b19 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -2557,8 +2557,7 @@ bool CommandInterpreter::DidProcessStopAbnormally() const {
     const StopReason reason = stop_info->GetStopReason();
     if (reason == eStopReasonException ||
         reason == eStopReasonInstrumentation ||
-        reason == eStopReasonProcessorTrace || reason == eStopReasonInterrupt ||
-        reason == eStopReasonHistoryBoundary)
+        reason == eStopReasonProcessorTrace || reason == eStopReasonInterrupt)
       return true;
 
     if (reason == eStopReasonSignal) {
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index b0aa664775b463..de047ee214c11e 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -82,9 +82,6 @@ void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
   case eStopReasonProcessorTrace:
     log.Printf("%s: %s processor trace", __FUNCTION__, header);
     return;
-  case eStopReasonHistoryBoundary:
-    log.Printf("%s: %s history boundary", __FUNCTION__, header);
-    return;
   default:
     log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
                static_cast<uint32_t>(stop_info.reason));
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index ef57e7bfd1e425..9b2907c6809965 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -402,15 +402,9 @@ lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() {
 
 Status ProcessKDP::WillResume() { return Status(); }
 
-Status ProcessKDP::DoResume(RunDirection direction) {
+Status ProcessKDP::DoResume() {
   Status error;
   Log *log = GetLog(KDPLog::Process);
-
-  if (direction == RunDirection::eRunReverse)
-    return Status::FromErrorStringWithFormatv(
-        "error: {0} does not support reverse execution of processes",
-        GetPluginName());
-
   // Only start the async thread if we try to do any process control
   if (!m_async_thread.IsJoinable())
     StartAsyncThread();
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index 1b71d83f70b087..e5ec5914f9600d 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -90,7 +90,7 @@ class ProcessKDP : public lldb_private::Process {
   // Process Control
   lldb_private::Status WillResume() override;
 
-  lldb_private::Status DoResume(lldb::RunDirection direction) override;
+  lldb_private::Status DoResume() override;
 
   lldb_private::Status DoHalt(bool &caused_stop) override;
 
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 7ff32ee96e0041..1bdacec221695e 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -236,18 +236,11 @@ ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,
   return error;
 }
 
-Status ProcessWindows::DoResume(RunDirection direction) {
+Status ProcessWindows::DoResume() {
   Log *log = GetLog(WindowsLog::Process);
   llvm::sys::ScopedLock lock(m_mutex);
   Status error;
 
-  if (direction == RunDirection::eRunReverse) {
-    error.FromErrorStringWithFormatv(
-        "error: {0} does not support reverse execution of processes",
-        GetPluginName());
-    return error;
-  }
-
   StateType private_state = GetPrivateState();
   if (private_state == eStateStopped || private_state == eStateCrashed) {
     LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
index 97284b7cd1436e..e97cfb790248be 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -52,7 +52,7 @@ class ProcessWindows : public Process, public ProcessDebugger {
   Status DoAttachToProcessWithID(
       lldb::pid_t pid,
       const lldb_private::ProcessAttachInfo &attach_info) override;
-  Status DoResume(lldb::RunDirection direction) override;
+  Status DoResume() override;
   Status DoDestroy() override;
   Status DoHalt(bool &caused_stop) override;
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index adc311ce2dd280..b3f1c6f052955b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -199,18 +199,6 @@ uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
   return m_max_packet_size;
 }
 
-bool GDBRemoteCommunicationClient::GetReverseContinueSupported() {
-  if (m_supports_reverse_continue == eLazyBoolCalculate)
-    GetRemoteQSupported();
-  return m_supports_reverse_continue == eLazyBoolYes;
-}
-
-bool GDBRemoteCommunicationClient::GetReverseStepSupported() {
-  if (m_supports_reverse_step == eLazyBoolCalculate)
-    GetRemoteQSupported();
-  return m_supports_reverse_step == eLazyBoolYes;
-}
-
 bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
   if (m_supports_not_sending_acks == eLazyBoolCalculate) {
     m_send_acks = true;
@@ -307,8 +295,6 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
     m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
     m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
     m_uses_native_signals = eLazyBoolCalculate;
-    m_supports_reverse_continue = eLazyBoolCalculate;
-    m_supports_reverse_step = eLazyBoolCalculate;
     m_supports_qProcessInfoPID = true;
     m_supports_qfProcessInfo = true;
     m_supports_qUserName = true;
@@ -362,8 +348,6 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
   m_supports_memory_tagging = eLazyBoolNo;
   m_supports_qSaveCore = eLazyBoolNo;
   m_uses_native_signals = eLazyBoolNo;
-  m_supports_reverse_continue = eLazyBoolNo;
-  m_supports_reverse_step = eLazyBoolNo;
 
   m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
                                   // not, we assume no limit
@@ -417,10 +401,6 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
         m_supports_qSaveCore = eLazyBoolYes;
       else if (x == "native-signals+")
         m_uses_native_signals = eLazyBoolYes;
-      else if (x == "ReverseContinue+")
-        m_supports_reverse_continue = eLazyBoolYes;
-      else if (x == "ReverseStep+")
-        m_supports_reverse_step = eLazyBoolYes;
       // Look for a list of compressions in the features list e.g.
       // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
       // deflate,lzma
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 116b47c1edf033..898d176abc3465 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -331,10 +331,6 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
 
   bool GetMultiprocessSupported();
 
-  bool GetReverseContinueSupported();
-
-  bool GetReverseStepSupported();
-
   LazyBool SupportsAllocDeallocMemory() // const
   {
     // Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -565,8 +561,6 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
   LazyBool m_supports_memory_tagging = eLazyBoolCalculate;
   LazyBool m_supports_qSaveCore = eLazyBoolCalculate;
   LazyBool m_uses_native_signals = eLazyBoolCalculate;
-  LazyBool m_supports_reverse_continue = eLazyBoolCalculate;
-  LazyBool m_supports_reverse_step = eLazyBoolCalculate;
 
   bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
       m_supports_qUserName : 1, m_supports_qGroupName : 1,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 89d2730cfccd02..8cdeaac5c7cb28 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -716,7 +716,6 @@ static const char *GetStopReasonString(StopReason stop_reason) {
     return "vforkdone";
   case eStopReasonInterrupt:
     return "async interrupt";
-  case eStopReasonHistoryBoundary:
   case eStopReasonInstrumentation:
   case eStopReasonInvalid:
   case eStopReasonPlanComplete:
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index fa511af9b6d549..538c8680140091 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -169,8 +169,6 @@ class PluginProperties : public Properties {
   }
 };
 
-std::chrono::seconds ResumeTimeout() { return std::chrono::seconds(5); }
-
 } // namespace
 
 static PluginProperties &GetGlobalPluginProperties() {
@@ -1182,16 +1180,10 @@ Status ProcessGDBRemote::WillResume() {
   return Status();
 }
 
-bool ProcessGDBRemote::SupportsReverseDirection() {
-  return m_gdb_comm.GetReverseStepSupported() ||
-         m_gdb_comm.GetReverseContinueSupported();
-}
-
-Status ProcessGDBRemote::DoResume(RunDirection direction) {
+Status ProcessGDBRemote::DoResume() {
   Status error;
   Log *log = GetLog(GDBRLog::Process);
-  LLDB_LOGF(log, "ProcessGDBRemote::Resume(%s)",
-            direction == RunDirection::eRunForward ? "" : "reverse");
+  LLDB_LOGF(log, "ProcessGDBRemote::Resume()");
 
   ListenerSP listener_sp(
       Listener::MakeListener("gdb-remote.resume-packet-sent"));
@@ -1205,24 +1197,12 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) {
 
     StreamString continue_packet;
     bool continue_packet_error = false;
-    // Number of threads continuing with "c", i.e. continuing without a signal
-    // to deliver.
-    const size_t num_continue_c_tids = m_continue_c_tids.size();
-    // Number of threads continuing with "C", i.e. continuing with a signal to
-    // deliver.
-    const size_t num_continue_C_tids = m_continue_C_tids.size();
-    // Number of threads continuing with "s", i.e. single-stepping.
-    const size_t num_continue_s_tids = m_continue_s_tids.size();
-    // Number of threads continuing with "S", i.e. single-stepping with a signal
-    // to deliver.
-    const size_t num_continue_S_tids = m_continue_S_tids.size();
-    if (direction == RunDirection::eRunForward &&
-        m_gdb_comm.HasAnyVContSupport()) {
+    if (m_gdb_comm.HasAnyVContSupport()) {
       std::string pid_prefix;
       if (m_gdb_comm.GetMultiprocessSupported())
         pid_prefix = llvm::formatv("p{0:x-}.", GetID());
 
-      if (num_continue_c_tids == num_threads ||
+      if (m_continue_c_tids.size() == num_threads ||
           (m_continue_c_tids.empty() && m_continue_C_tids.empty() &&
            m_continue_s_tids.empty() && m_continue_S_tids.empty())) {
         // All threads are continuing
@@ -1285,10 +1265,14 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) {
     } else
       continue_packet_error = true;
 
-    if (direction == RunDirection::eRunForward && continue_packet_error) {
+    if (continue_packet_error) {
       // Either no vCont support, or we tried to use part of the vCont packet
       // that wasn't supported by the remote GDB server. We need to try and
-      // make a simple packet that can do our continue.
+      // make a simple packet that can do our continue
+      const size_t num_continue_c_tids = m_continue_c_tids.size();
+      const size_t num_continue_C_tids = m_continue_C_tids.size();
+      const size_t num_continue_s_tids = m_continue_s_tids.size();
+      const size_t num_continue_S_tids = m_continue_S_tids.size();
       if (num_continue_c_tids > 0) {
         if (num_continue_c_tids == num_threads) {
           // All threads are resuming...
@@ -1379,59 +1363,9 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) {
       }
     }
 
-    if (direction == RunDirection::eRunReverse) {
-      if (num_continue_s_tids > 0 || num_continue_S_tids > 0) {
-        if (!m_gdb_comm.GetReverseStepSupported()) {
-          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: target does not "
-                         "support reverse-stepping");
-          return Status::FromErrorString(
-              "target does not support reverse-stepping");
-        }
-
-        if (num_continue_S_tids > 0) {
-          LLDB_LOGF(
-              log,
-              "ProcessGDBRemote::DoResume: Signals not supported in reverse");
-          return Status::FromErrorString(
-              "can't deliver signals while running in reverse");
-        }
-
-        if (num_continue_s_tids > 1) {
-          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: can't step multiple "
-                         "threads in reverse");
-          return Status::FromErrorString(
-              "can't step multiple threads while reverse-stepping");
-        }
-
-        m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front());
-        continue_packet.PutCString("bs");
-      } else {
-        if (!m_gdb_comm.GetReverseContinueSupported()) {
-          LLDB_LOGF(log, "ProcessGDBRemote::DoResume: target does not "
-                         "support reverse-continue");
-          return Status::FromErrorString(
-              "target does not support reverse-continue");
-        }
-
-        if (num_continue_C_tids > 0) {
-          LLDB_LOGF(
-              log,
-              "ProcessGDBRemote::DoResume: Signals not supported in reverse");
-          return Status::FromErrorString(
-              "can't deliver signals while running in reverse");
-        }
-
-        // All threads continue whether requested or not ---
-        // we can't change how threads ran in the past.
-        continue_packet.PutCString("bc");
-      }
-
-      continue_packet_error = false;
-    }
-
     if (continue_packet_error) {
-      return Status::FromErrorString(
-          "can't make continue packet for this resume");
+      error =
+          Status::FromErrorString("can't make continue packet for this resume");
     } else {
       EventSP event_sp;
       if (!m_async_thread.IsJoinable()) {
@@ -1446,7 +1380,7 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) {
           std::make_shared<EventDataBytes>(continue_packet.GetString());
       m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp);
 
-      if (!listener_sp->GetEvent(event_sp, ResumeTimeout())) {
+      if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) {
         error = Status::FromErrorString("Resume timed out.");
         LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out.");
       } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
@@ -1929,10 +1863,6 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
           thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
               *thread_sp, description.c_str()));
           handled = true;
-        } else if (reason == "history boundary") {
-          thread_sp->SetStopInfo(StopInfo::CreateStopReasonHistoryBoundary(
-              *thread_sp, description.c_str()));
-          handled = true;
         } else if (reason == "exec") {
           did_exec = true;
           thread_sp->SetStopInfo(
@@ -2388,8 +2318,6 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
         description = std::string(ostr.GetString());
       } else if (key.compare("swbreak") == 0 || key.compare("hwbreak") == 0) {
         reason = "breakpoint";
-      } else if (key.compare("replaylog") == 0) {
-        reason = "history boundary";
       } else if (key.compare("library") == 0) {
         auto error = LoadModules();
         if (error) {
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 1cbd1e82b381d9..2492795851388a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -111,9 +111,7 @@ class ProcessGDBRemote : public Process,
   // Process Control
   Status WillResume() override;
 
-  bool SupportsReverseDirection() override;
-
-  Status DoResume(lldb::RunDirection direction) override;
+  Status DoResume() override;
 
   Status DoHalt(bool &caused_stop) override;
 
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
index 3360bd9a044bd2..d2111ce877ce55 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -182,15 +182,10 @@ void ScriptedProcess::DidResume() {
   m_pid = GetInterface().GetProcessID();
 }
 
-Status ScriptedProcess::DoResume(RunDirection direction) {
+Status ScriptedProcess::DoResume() {
   LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
 
-  if (direction == RunDirection::eRunForward)
-    return GetInterface().Resume();
-  // FIXME: Pipe reverse continue through Scripted Processes
-  return Status::FromErrorStringWithFormatv(
-      "error: {0} does not support reverse execution of processes",
-      GetPluginName());
+  return GetInterface().Resume();
 }
 
 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
index 8ebe4ca5f3d449..0335364b4010b2 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -52,7 +52,7 @@ class ScriptedProcess : public Process {
 
   void DidResume() override;
 
-  Status DoResume(lldb::RunDirection direction) override;
+  Status DoResume() override;
 
   Status DoAttachToProcessWithID(lldb::pid_t pid,
                                  const ProcessAttachInfo &attach_info) override;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index c594fd94c9904b..89731f798deda8 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -437,8 +437,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
       m_mod_id(), m_process_unique_id(0), m_thread_index_id(0),
       m_thread_id_to_index_id_map(), m_exit_status(-1),
       m_thread_list_real(*this), m_thread_list(*this), m_thread_plans(*this),
-      m_extended_thread_list(*this),
-      m_base_direction(RunDirection::eRunForward), m_extended_thread_stop_id(0),
+      m_extended_thread_list(*this), m_extended_thread_stop_id(0),
       m_queue_list(this), m_queue_list_stop_id(0),
       m_unix_signals_sp(unix_signals_sp), m_abi_sp(), m_process_input_reader(),
       m_stdio_communication("process.stdio"), m_stdio_communication_mutex(),
@@ -846,7 +845,6 @@ bool Process::HandleProcessStateChangedEvent(
             switch (thread_stop_reason) {
             case eStopReasonInvalid:
             case eStopReasonNone:
-            case eStopReasonHistoryBoundary:
               break;
 
             case eStopReasonSignal: {
@@ -3237,13 +3235,6 @@ Status Process::ConnectRemote(llvm::StringRef remote_url) {
   return error;
 }
 
-void Process::SetBaseDirection(RunDirection direction) {
-  if (m_base_direction == direction)
-    return;
-  m_thread_list.DiscardThreadPlans();
-  m_base_direction = direction;
-}
-
 Status Process::PrivateResume() {
   Log *log(GetLog(LLDBLog::Process | LLDBLog::Step));
   LLDB_LOGF(log,
@@ -3270,25 +3261,18 @@ Status Process::PrivateResume() {
     // (suspended/running/stepping). Threads should also check their resume
     // signal in lldb::Thread::GetResumeSignal() to see if they are supposed to
     // start back up with a signal.
-    RunDirection direction;
-    if (m_thread_list.WillResume(direction)) {
-      LLDB_LOGF(log, "Process::PrivateResume WillResume direction=%d",
-                direction);
+    if (m_thread_list.WillResume()) {
       // Last thing, do the PreResumeActions.
       if (!RunPreResumeActions()) {
         error = Status::FromErrorString(
             "Process::PrivateResume PreResumeActions failed, not resuming.");
-        LLDB_LOGF(
-            log,
-            "Process::PrivateResume PreResumeActions failed, not resuming.");
       } else {
         m_mod_id.BumpResumeID();
-        error = DoResume(direction);
+        error = DoResume();
         if (error.Success()) {
           DidResume();
           m_thread_list.DidResume();
-          LLDB_LOGF(log,
-                    "Process::PrivateResume thinks the process has resumed.");
+          LLDB_LOGF(log, "Process thinks the process has resumed.");
         } else {
           LLDB_LOGF(log, "Process::PrivateResume() DoResume failed.");
           return error;
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 355d3a9ad6e8f1..356917a45b7b34 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -1269,29 +1269,6 @@ class StopInfoProcessorTrace : public StopInfo {
   }
 };
 
-// StopInfoHistoryBoundary
-
-class StopInfoHistoryBoundary : public StopInfo {
-public:
-  StopInfoHistoryBoundary(Thread &thread, const char *description)
-      : StopInfo(thread, LLDB_INVALID_UID) {
-    if (description)
-      SetDescription(description);
-  }
-
-  ~StopInfoHistoryBoundary() override = default;
-
-  StopReason GetStopReason() const override {
-    return eStopReasonHistoryBoundary;
-  }
-
-  const char *GetDescription() override {
-    if (m_description.empty())
-      return "history boundary";
-    return m_description.c_str();
-  }
-};
-
 // StopInfoThreadPlan
 
 class StopInfoThreadPlan : public StopInfo {
@@ -1519,11 +1496,6 @@ StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
   return StopInfoSP(new StopInfoProcessorTrace(thread, description));
 }
 
-StopInfoSP StopInfo::CreateStopReasonHistoryBoundary(Thread &thread,
-                                                     const char *description) {
-  return StopInfoSP(new StopInfoHistoryBoundary(thread, description));
-}
-
 StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
   return StopInfoSP(new StopInfoExec(thread));
 }
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 2c4d925c732227..b5261310970611 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -617,7 +617,7 @@ void Thread::WillStop() {
   current_plan->WillStop();
 }
 
-bool Thread::SetupToStepOverBreakpointIfNeeded(RunDirection direction) {
+bool Thread::SetupForResume() {
   if (GetResumeState() != eStateSuspended) {
     // First check whether this thread is going to "actually" resume at all.
     // For instance, if we're stepping from one level to the next of an
@@ -632,11 +632,10 @@ bool Thread::SetupToStepOverBreakpointIfNeeded(RunDirection direction) {
     // what the current plan is.
 
     lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
-    ProcessSP process_sp(GetProcess());
-    if (reg_ctx_sp && process_sp && direction == eRunForward) {
+    if (reg_ctx_sp) {
       const addr_t thread_pc = reg_ctx_sp->GetPC();
       BreakpointSiteSP bp_site_sp =
-          process_sp->GetBreakpointSiteList().FindByAddress(thread_pc);
+          GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
       if (bp_site_sp) {
         // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the
         // target may not require anything special to step over a breakpoint.
@@ -1743,8 +1742,6 @@ std::string Thread::StopReasonAsString(lldb::StopReason reason) {
     return "processor trace";
   case eStopReasonInterrupt:
     return "async interrupt";
-  case eStopReasonHistoryBoundary:
-    return "history boundary";
   }
 
   return "StopReason = " + std::to_string(reason);
diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp
index 99e2c1204146a5..6cbef330bf4888 100644
--- a/lldb/source/Target/ThreadList.cpp
+++ b/lldb/source/Target/ThreadList.cpp
@@ -508,7 +508,7 @@ void ThreadList::DiscardThreadPlans() {
     (*pos)->DiscardThreadPlans(true);
 }
 
-bool ThreadList::WillResume(RunDirection &direction) {
+bool ThreadList::WillResume() {
   // Run through the threads and perform their momentary actions. But we only
   // do this for threads that are running, user suspended threads stay where
   // they are.
@@ -566,12 +566,6 @@ bool ThreadList::WillResume(RunDirection &direction) {
     }
   }
 
-  if (thread_to_run != nullptr) {
-    direction = thread_to_run->GetCurrentPlan()->GetDirection();
-  } else {
-    direction = m_process.GetBaseDirection();
-  }
-
   // Give all the threads that are likely to run a last chance to set up their
   // state before we negotiate who is actually going to get a chance to run...
   // Don't set to resume suspended threads, and if any thread wanted to stop
@@ -583,12 +577,7 @@ bool ThreadList::WillResume(RunDirection &direction) {
     // "StopOthers" plans which would then get to be part of the who-gets-to-run
     // negotiation, but they're coming in after the fact, and the threads that
     // are already set up should take priority.
-    if (thread_to_run->SetupToStepOverBreakpointIfNeeded(direction)) {
-      // We only need to step over breakpoints when running forward, and the
-      // step-over-breakpoint plan itself wants to run forward, so this
-      // keeps our desired direction.
-      assert(thread_to_run->GetCurrentPlan()->GetDirection() == direction);
-    }
+    thread_to_run->SetupForResume();
   } else {
     for (pos = m_threads.begin(); pos != end; ++pos) {
       ThreadSP thread_sp(*pos);
@@ -596,11 +585,7 @@ bool ThreadList::WillResume(RunDirection &direction) {
         if (thread_sp->IsOperatingSystemPluginThread() &&
             !thread_sp->GetBackingThread())
           continue;
-        if (thread_sp->SetupToStepOverBreakpointIfNeeded(direction)) {
-          // We only need to step over breakpoints when running forward, and the
-          // step-over-breakpoint plan itself wants to run forward, so this
-          // keeps our desired direction.
-          assert(thread_sp->GetCurrentPlan()->GetDirection() == direction);
+        if (thread_sp->SetupForResume()) {
           // You can't say "stop others" and also want yourself to be suspended.
           assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
           thread_to_run = thread_sp;
@@ -641,17 +626,6 @@ bool ThreadList::WillResume(RunDirection &direction) {
       if (!thread_sp->ShouldResume(run_state))
         need_to_resume = false;
     }
-    if (need_to_resume) {
-      // Ensure all threads are running in the right direction
-      for (pos = m_threads.begin(); pos != end; ++pos) {
-        ThreadSP thread_sp(*pos);
-        while (thread_sp->GetCurrentPlan()->GetDirection() != direction) {
-          // This can't discard the base plan because its direction is
-          // m_process.GetBaseDirection() i.e. `direction`.
-          thread_sp->DiscardPlan();
-        }
-      }
-    }
   } else {
     for (pos = m_threads.begin(); pos != end; ++pos) {
       ThreadSP thread_sp(*pos);
diff --git a/lldb/source/Target/ThreadPlanBase.cpp b/lldb/source/Target/ThreadPlanBase.cpp
index 09437b0048c2cf..dfd2157e70d4ad 100644
--- a/lldb/source/Target/ThreadPlanBase.cpp
+++ b/lldb/source/Target/ThreadPlanBase.cpp
@@ -196,7 +196,3 @@ bool ThreadPlanBase::MischiefManaged() {
   // The base plan is never done.
   return false;
 }
-
-RunDirection ThreadPlanBase::GetDirection() const {
-  return m_process.GetBaseDirection();
-}
diff --git a/lldb/test/API/functionalities/reverse-execution/Makefile b/lldb/test/API/functionalities/reverse-execution/Makefile
deleted file mode 100644
index 10495940055b63..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-C_SOURCES := main.c
-
-include Makefile.rules
diff --git a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py b/lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
deleted file mode 100644
index 5b76e76f6fdb7b..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
+++ /dev/null
@@ -1,149 +0,0 @@
-import lldb
-import time
-import unittest
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test.decorators import *
-from lldbsuite.test.gdbclientutils import *
-from lldbsuite.test.lldbreverse import ReverseTestBase
-from lldbsuite.test import lldbutil
-
-
-class TestReverseContinueBreakpoints(ReverseTestBase):
-    def test_reverse_continue(self):
-        self.reverse_continue_internal(async_mode=False)
-
-    def test_reverse_continue_async(self):
-        self.reverse_continue_internal(async_mode=True)
-
-    def reverse_continue_internal(self, async_mode):
-        target, process, initial_threads = self.setup_recording(async_mode)
-
-        # Reverse-continue. We'll stop at the point where we started recording.
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.assertSuccess(status)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_HISTORY_BOUNDARY,
-            substrs=["stopped", "stop reason = history boundary"],
-        )
-
-        # Continue forward normally until the target exits.
-        status = process.ContinueInDirection(lldb.eRunForward)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateExited]
-        )
-        self.assertSuccess(status)
-        self.assertState(process.GetState(), lldb.eStateExited)
-        self.assertEqual(process.GetExitStatus(), 0)
-
-    def test_reverse_continue_breakpoint(self):
-        self.reverse_continue_breakpoint_internal(async_mode=False)
-
-    def test_reverse_continue_breakpoint_async(self):
-        self.reverse_continue_breakpoint_internal(async_mode=True)
-
-    def reverse_continue_breakpoint_internal(self, async_mode):
-        target, process, initial_threads = self.setup_recording(async_mode)
-
-        # Reverse-continue to the function "trigger_breakpoint".
-        trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None)
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.assertSuccess(status)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        threads_now = lldbutil.get_threads_stopped_at_breakpoint(process, trigger_bkpt)
-        self.assertEqual(threads_now, initial_threads)
-
-    def test_reverse_continue_skip_breakpoint(self):
-        self.reverse_continue_skip_breakpoint_internal(async_mode=False)
-
-    def test_reverse_continue_skip_breakpoint_async(self):
-        self.reverse_continue_skip_breakpoint_internal(async_mode=True)
-
-    def reverse_continue_skip_breakpoint_internal(self, async_mode):
-        target, process, initial_threads = self.setup_recording(async_mode)
-
-        # Reverse-continue over a breakpoint at "trigger_breakpoint" whose
-        # condition is false (via function call).
-        # This tests that we continue in the correct direction after hitting
-        # the breakpoint.
-        trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None)
-        trigger_bkpt.SetCondition("false_condition()")
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        self.assertSuccess(status)
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_HISTORY_BOUNDARY,
-            substrs=["stopped", "stop reason = history boundary"],
-        )
-
-    def test_continue_preserves_direction(self):
-        self.continue_preserves_direction_internal(async_mode=False)
-
-    def test_continue_preserves_direction_asyhc(self):
-        self.continue_preserves_direction_internal(async_mode=True)
-
-    def continue_preserves_direction_internal(self, async_mode):
-        target, process, initial_threads = self.setup_recording(async_mode)
-
-        # Reverse-continue to the function "trigger_breakpoint".
-        trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None)
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.assertSuccess(status)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        # This should continue in reverse.
-        status = process.Continue()
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        self.assertSuccess(status)
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_HISTORY_BOUNDARY,
-            substrs=["stopped", "stop reason = history boundary"],
-        )
-
-    def setup_recording(self, async_mode):
-        """
-        Record execution of code between "start_recording" and "stop_recording" breakpoints.
-
-        Returns with the target stopped at "stop_recording", with recording disabled,
-        ready to reverse-execute.
-        """
-        self.build()
-        target = self.dbg.CreateTarget("")
-        process = self.connect(target)
-
-        # Record execution from the start of the function "start_recording"
-        # to the start of the function "stop_recording". We want to keep the
-        # interval that we record as small as possible to minimize the run-time
-        # of our single-stepping recorder.
-        start_recording_bkpt = target.BreakpointCreateByName("start_recording", None)
-        initial_threads = lldbutil.continue_to_breakpoint(process, start_recording_bkpt)
-        self.assertEqual(len(initial_threads), 1)
-        target.BreakpointDelete(start_recording_bkpt.GetID())
-        self.start_recording()
-        stop_recording_bkpt = target.BreakpointCreateByName("stop_recording", None)
-        lldbutil.continue_to_breakpoint(process, stop_recording_bkpt)
-        target.BreakpointDelete(stop_recording_bkpt.GetID())
-        self.stop_recording()
-
-        self.dbg.SetAsync(async_mode)
-        self.expect_async_state_changes(async_mode, process, [lldb.eStateStopped])
-
-        return target, process, initial_threads
-
-    def expect_async_state_changes(self, async_mode, process, states):
-        if not async_mode:
-            return
-        listener = self.dbg.GetListener()
-        lldbutil.expect_state_changes(self, listener, process, states)
diff --git a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py b/lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py
deleted file mode 100644
index 137e9d2b617689..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import lldb
-import unittest
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test.decorators import *
-from lldbsuite.test import lldbutil
-
-
-class TestReverseContinueNotSupported(TestBase):
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def test_reverse_continue_not_supported(self):
-        self.build()
-        exe = self.getBuildArtifact("a.out")
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
-
-        main_bkpt = target.BreakpointCreateByName("main", None)
-        self.assertTrue(main_bkpt, VALID_BREAKPOINT)
-
-        process = target.LaunchSimple(None, None, self.get_process_working_directory())
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # This will fail gracefully.
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.assertFailure(
-            status, "error: gdb-remote does not support reverse execution of processes"
-        )
-
-        self.assertSuccess(process.ContinueInDirection(lldb.eRunForward))
-        self.assertState(process.GetState(), lldb.eStateExited)
-        self.assertEqual(process.GetExitStatus(), 0)
diff --git a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueWatchpoints.py b/lldb/test/API/functionalities/reverse-execution/TestReverseContinueWatchpoints.py
deleted file mode 100644
index 897220bf198071..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueWatchpoints.py
+++ /dev/null
@@ -1,130 +0,0 @@
-import lldb
-import time
-import unittest
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test.decorators import *
-from lldbsuite.test.gdbclientutils import *
-from lldbsuite.test.lldbreverse import ReverseTestBase
-from lldbsuite.test import lldbutil
-
-
-class TestReverseContinueWatchpoints(ReverseTestBase):
-    def test_reverse_continue_watchpoint(self):
-        self.reverse_continue_watchpoint_internal(async_mode=False)
-
-    def test_reverse_continue_watchpoint_async(self):
-        self.reverse_continue_watchpoint_internal(async_mode=True)
-
-    def reverse_continue_watchpoint_internal(self, async_mode):
-        target, process, initial_threads, watch_addr = self.setup_recording(async_mode)
-
-        error = lldb.SBError()
-        wp_opts = lldb.SBWatchpointOptions()
-        wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)
-        watchpoint = target.WatchpointCreateByAddress(watch_addr, 4, wp_opts, error)
-        self.assertTrue(watchpoint)
-
-        watch_var = target.EvaluateExpression("*g_watched_var_ptr")
-        self.assertEqual(watch_var.GetValueAsSigned(-1), 2)
-
-        # Reverse-continue to the function "trigger_watchpoint".
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.assertSuccess(status)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        # We should stop at the point just before the location was modified.
-        watch_var = target.EvaluateExpression("*g_watched_var_ptr")
-        self.assertEqual(watch_var.GetValueAsSigned(-1), 1)
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_WATCHPOINT,
-            substrs=["stopped", "trigger_watchpoint", "stop reason = watchpoint 1"],
-        )
-
-        # Stepping forward one instruction should change the value of the variable.
-        initial_threads[0].StepInstruction(False)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        watch_var = target.EvaluateExpression("*g_watched_var_ptr")
-        self.assertEqual(watch_var.GetValueAsSigned(-1), 2)
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_WATCHPOINT,
-            substrs=["stopped", "trigger_watchpoint", "stop reason = watchpoint 1"],
-        )
-
-    def test_reverse_continue_skip_watchpoint(self):
-        self.reverse_continue_skip_watchpoint_internal(async_mode=False)
-
-    def test_reverse_continue_skip_watchpoint_async(self):
-        self.reverse_continue_skip_watchpoint_internal(async_mode=True)
-
-    def reverse_continue_skip_watchpoint_internal(self, async_mode):
-        target, process, initial_threads, watch_addr = self.setup_recording(async_mode)
-
-        # Reverse-continue over a watchpoint whose condition is false
-        # (via function call).
-        # This tests that we continue in the correct direction after hitting
-        # the watchpoint.
-        error = lldb.SBError()
-        wp_opts = lldb.SBWatchpointOptions()
-        wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)
-        watchpoint = target.WatchpointCreateByAddress(watch_addr, 4, wp_opts, error)
-        self.assertTrue(watchpoint)
-        watchpoint.SetCondition("false_condition()")
-        status = process.ContinueInDirection(lldb.eRunReverse)
-        self.expect_async_state_changes(
-            async_mode, process, [lldb.eStateRunning, lldb.eStateStopped]
-        )
-        self.assertSuccess(status)
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_HISTORY_BOUNDARY,
-            substrs=["stopped", "stop reason = history boundary"],
-        )
-
-    def setup_recording(self, async_mode):
-        """
-        Record execution of code between "start_recording" and "stop_recording" breakpoints.
-
-        Returns with the target stopped at "stop_recording", with recording disabled,
-        ready to reverse-execute.
-        """
-        self.build()
-        target = self.dbg.CreateTarget("")
-        process = self.connect(target)
-
-        # Record execution from the start of the function "start_recording"
-        # to the start of the function "stop_recording". We want to keep the
-        # interval that we record as small as possible to minimize the run-time
-        # of our single-stepping recorder.
-        start_recording_bkpt = target.BreakpointCreateByName("start_recording", None)
-        initial_threads = lldbutil.continue_to_breakpoint(process, start_recording_bkpt)
-        self.assertEqual(len(initial_threads), 1)
-        target.BreakpointDelete(start_recording_bkpt.GetID())
-
-        frame0 = initial_threads[0].GetFrameAtIndex(0)
-        watched_var_ptr = frame0.FindValue(
-            "g_watched_var_ptr", lldb.eValueTypeVariableGlobal
-        )
-        watch_addr = watched_var_ptr.GetValueAsUnsigned(0)
-        self.assertTrue(watch_addr > 0)
-
-        self.start_recording()
-        stop_recording_bkpt = target.BreakpointCreateByName("stop_recording", None)
-        lldbutil.continue_to_breakpoint(process, stop_recording_bkpt)
-        target.BreakpointDelete(stop_recording_bkpt.GetID())
-        self.stop_recording()
-
-        self.dbg.SetAsync(async_mode)
-        self.expect_async_state_changes(async_mode, process, [lldb.eStateStopped])
-
-        return target, process, initial_threads, watch_addr
-
-    def expect_async_state_changes(self, async_mode, process, states):
-        if not async_mode:
-            return
-        listener = self.dbg.GetListener()
-        lldbutil.expect_state_changes(self, listener, process, states)
diff --git a/lldb/test/API/functionalities/reverse-execution/main.c b/lldb/test/API/functionalities/reverse-execution/main.c
deleted file mode 100644
index 520e3415bf0265..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/main.c
+++ /dev/null
@@ -1,25 +0,0 @@
-int false_condition() { return 0; }
-
-int *g_watched_var_ptr;
-
-static void start_recording() {}
-
-static void trigger_watchpoint() { *g_watched_var_ptr = 2; }
-
-static void trigger_breakpoint() {}
-
-static void stop_recording() {}
-
-int main() {
-  // The watched memory location is on the stack because
-  // that's what our reverse execution engine records and
-  // replays.
-  int watched_var = 1;
-  g_watched_var_ptr = &watched_var;
-
-  start_recording();
-  trigger_watchpoint();
-  trigger_breakpoint();
-  stop_recording();
-  return 0;
-}
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 57e6b254771f11..6ca4dfb4711a13 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -996,9 +996,6 @@ llvm::json::Value CreateThreadStopped(DAP &dap, lldb::SBThread &thread,
   case lldb::eStopReasonProcessorTrace:
     body.try_emplace("reason", "processor trace");
     break;
-  case lldb::eStopReasonHistoryBoundary:
-    body.try_emplace("reason", "history boundary");
-    break;
   case lldb::eStopReasonSignal:
   case lldb::eStopReasonException:
     body.try_emplace("reason", "exception");
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 16ca3d779dfea0..48b63b59e0e3fe 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -113,7 +113,6 @@ bool ThreadHasStopReason(lldb::SBThread &thread) {
   case lldb::eStopReasonVFork:
   case lldb::eStopReasonVForkDone:
   case lldb::eStopReasonInterrupt:
-  case lldb::eStopReasonHistoryBoundary:
     return true;
   case lldb::eStopReasonThreadExiting:
   case lldb::eStopReasonInvalid:



More information about the lldb-commits mailing list