[Lldb-commits] [lldb] 2ff4c25 - Revert "[lldb] Implement basic support for reverse-continue (#99736)"
Augusto Noronha via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 10 15:10:55 PDT 2024
Author: Augusto Noronha
Date: 2024-10-10T15:05:58-07:00
New Revision: 2ff4c25b7efff64b3b662d0bedcfe7edebcf20b9
URL: https://github.com/llvm/llvm-project/commit/2ff4c25b7efff64b3b662d0bedcfe7edebcf20b9
DIFF: https://github.com/llvm/llvm-project/commit/2ff4c25b7efff64b3b662d0bedcfe7edebcf20b9.diff
LOG: Revert "[lldb] Implement basic support for reverse-continue (#99736)"
This reverts commit d5e1de6da96c1ab3b8cae68447e8ed3696a7006e.
Added:
Modified:
lldb/include/lldb/API/SBProcess.h
lldb/include/lldb/Target/Process.h
lldb/include/lldb/Target/StopInfo.h
lldb/include/lldb/lldb-enumerations.h
lldb/packages/Python/lldbsuite/test/gdbclientutils.py
lldb/packages/Python/lldbsuite/test/lldbtest.py
lldb/source/API/SBProcess.cpp
lldb/source/API/SBThread.cpp
lldb/source/Interpreter/CommandInterpreter.cpp
lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
lldb/source/Plugins/Process/scripted/ScriptedProcess.h
lldb/source/Target/Process.cpp
lldb/source/Target/StopInfo.cpp
lldb/source/Target/Thread.cpp
lldb/tools/lldb-dap/JSONUtils.cpp
lldb/tools/lldb-dap/LLDBUtils.cpp
Removed:
lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py
lldb/packages/Python/lldbsuite/test/lldbreverse.py
lldb/test/API/functionalities/reverse-execution/Makefile
lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py
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 8b8ed830b54cc0..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 Continue(RunDirection direction);
lldb::SBError Stop();
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index fe7fbc50fd5770..b8c53a474ba6b9 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -857,10 +857,10 @@ class Process : public std::enable_shared_from_this<Process>,
/// \see Thread:Resume()
/// \see Thread:Step()
/// \see Thread:Suspend()
- Status Resume(lldb::RunDirection direction = lldb::eRunForward);
+ Status Resume();
/// Resume a process, and wait for it to stop.
- Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward);
+ Status ResumeSynchronous(Stream *stream);
/// Halts a running process.
///
@@ -1104,14 +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());
- } else {
- return Status::FromErrorStringWithFormatv(
- "error: {0} does not support reverse execution of processes", GetPluginName());
- }
+ virtual Status DoResume() {
+ return Status::FromErrorStringWithFormatv(
+ "error: {0} does not support resuming processes", GetPluginName());
}
/// Called after resuming a process.
@@ -2337,8 +2332,6 @@ class Process : public std::enable_shared_from_this<Process>,
bool IsRunning() const;
- lldb::RunDirection GetLastRunDirection() { return m_last_run_direction; }
-
DynamicCheckerFunctions *GetDynamicCheckers() {
return m_dynamic_checkers_up.get();
}
@@ -2858,7 +2851,7 @@ void PruneThreadPlans();
///
/// \return
/// An Status object describing the success or failure of the resume.
- Status PrivateResume(lldb::RunDirection direction = lldb::eRunForward);
+ Status PrivateResume();
// Called internally
void CompleteAttach();
@@ -3134,8 +3127,6 @@ void PruneThreadPlans();
// m_currently_handling_do_on_removals are true,
// Resume will only request a resume, using this
// flag to check.
- // The direction of execution from the last time this process was resumed.
- lldb::RunDirection m_last_run_direction;
lldb::tid_t m_interrupt_tid; /// The tid of the thread that issued the async
/// interrupt, used by thread plan timeout. It
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index 072f71f6b1122f..fae90364deaf0a 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -142,12 +142,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/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 232d1dfdb5c9d0..938f6e3abe8f2a 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 2a9592bf4545a4..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__)
-
- if len(self.logger.handlers) > 0:
- return # We have set up this handler already
-
- 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)
-
- lldb_server_exe = lldbgdbserverutils.get_lldb_server_exe()
- if lldb_server_exe is None:
- self.debug_monitor_exe = lldbgdbserverutils.get_debugserver_exe()
- self.assertTrue(self.debug_monitor_exe is not None)
- self.debug_monitor_extra_args = []
- else:
- self.debug_monitor_exe = lldb_server_exe
- self.debug_monitor_extra_args = ["gdbserver"]
-
- 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 get_next_port(self):
- return 12000 + random.randint(0, 3999)
-
- 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.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)
- 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 0f02fdffbdeada..00000000000000
--- a/lldb/packages/Python/lldbsuite/test/lldbreverse.py
+++ /dev/null
@@ -1,418 +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).
- """
-
- """
- 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
-
- pid = 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", ":"):
- reply = self.pass_through(packet)
- return reply + ";ReverseStep+;ReverseContinue+"
- if self.is_command(packet, "vCont", ";"):
- if self.recording_enabled:
- return self.continue_with_recording(packet)
- snapshots = []
- if packet[0] == "c" or packet[0] == "s" or packet[0] == "C" or packet[0] == "S":
- raise ValueError("LLDB should not be sending old-style continuation packets")
- 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 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)
- 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 in ["name", "threads", "thread-pcs", "reason"]:
- 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 parse_stop(self, reply):
- result = {}
- if not reply:
- raise ValueError("Invalid empty packet")
- if reply[0] == "T" and len(reply) >= 3:
- result = {k:v for k, v in self.parse_pairs(reply[3:])}
- return (int(reply[1:3], 16), result)
- raise "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[1:])
- 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:{self.pid:x}.{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("(p([0-9a-f]+)[.])?([0-9a-f]+)$", thread_id)
- if m is None:
- raise ValueError("Invalid thread ID: " + thread_id)
- if self.pid is None:
- self.pid = int(m.group(2), 16)
- return int(m.group(3), 16)
-
- def history_boundary_reply(self, thread_id):
- return f"T00thread:{self.pid:x}.{thread_id:x};replaylog:begin;"
-
- def singlestep_stop_reply(self, thread_id):
- return f"T05thread:{self.pid:x}.{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{self.pid:x}.{thread_id:x}")
- self.pass_through(f"Hc{self.pid:x}.{thread_id:x}")
- else:
- self.pass_through(f"Hc-1.-1")
- self.pass_through(f"Hg-1.-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 & (BLOCK_SIZE - 1)
- end_addr = (end_addr + BLOCK_SIZE - 1) & (BLOCK_SIZE - 1)
- 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[1:])
- 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 7cc1ac9749ec93..8884ef5933ada8 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/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 07780f9f9c8393..9773144723c34c 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -564,10 +564,6 @@ uint32_t SBProcess::GetAddressByteSize() const {
}
SBError SBProcess::Continue() {
- return Continue(RunDirection::eRunForward);
-}
-
-SBError SBProcess::Continue(RunDirection direction) {
LLDB_INSTRUMENT_VA(this);
SBError sb_error;
@@ -578,9 +574,9 @@ SBError SBProcess::Continue(RunDirection direction) {
process_sp->GetTarget().GetAPIMutex());
if (process_sp->GetTarget().GetDebugger().GetAsyncExecution())
- sb_error.ref() = process_sp->Resume(direction);
+ sb_error.ref() = process_sp->Resume();
else
- sb_error.ref() = process_sp->ResumeSynchronous(nullptr, direction);
+ sb_error.ref() = process_sp->ResumeSynchronous(nullptr);
} else
sb_error = Status::FromErrorString("SBProcess is invalid");
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index aca8a039952960..a99456e06d0329 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 ea60492ac46a10..8d3a82ef6c990a 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -2553,8 +2553,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 116c43343c01d1..9b2907c6809965 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -402,16 +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) {
- error.SetErrorStringWithFormatv(
- "error: {0} does not support reverse execution of processes", GetPluginName());
- return error;
- }
-
// 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 76b7095deaa503..703aa082f0476f 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -204,17 +204,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.SetErrorStringWithFormatv(
- "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 fc792a4409410b..e42526c8fd7266 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -199,20 +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;
@@ -309,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;
@@ -364,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
@@ -419,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 4016cde74ebea8..35fa93e53bc66f 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 3fc03bd05d5df0..3e09c316d74f44 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -169,10 +169,6 @@ class PluginProperties : public Properties {
}
};
-std::chrono::seconds ResumeTimeout() {
- return std::chrono::seconds(5);
-}
-
} // namespace
static PluginProperties &GetGlobalPluginProperties() {
@@ -1184,11 +1180,10 @@ Status ProcessGDBRemote::WillResume() {
return Status();
}
-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"));
@@ -1202,21 +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
@@ -1279,11 +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, or it's the reverse
- // direction. We need to try and make a simple packet that can do our
- // continue.
+ // that wasn't supported by the remote GDB server. We need to try and
+ // 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...
@@ -1374,41 +1363,9 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) {
}
}
- if (direction == RunDirection::eRunReverse && continue_packet_error) {
- if (num_continue_C_tids > 0 || num_continue_S_tids > 0) {
- LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: Signals not supported");
- return Status::FromErrorString("can't deliver signals while running in reverse");
- }
-
- if (num_continue_s_tids > 0) {
- if (num_continue_s_tids > 1) {
- LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: can't step multiple threads");
- return Status::FromErrorString("can't step multiple threads while reverse-stepping");
- }
-
- if (!m_gdb_comm.GetReverseStepSupported()) {
- LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: target does not support reverse-stepping");
- return Status::FromErrorString("target does not support 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::DoResumeReverse: target does not support reverse-continue");
- return Status::FromErrorString("target does not support reverse-continue");
- }
-
- // 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()) {
@@ -1423,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)) {
@@ -1906,10 +1863,6 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
*thread_sp, description.c_str()));
handled = true;
- } else if (reason == "replaylog") {
- thread_sp->SetStopInfo(StopInfo::CreateStopReasonHistoryBoundary(
- *thread_sp, description.c_str()));
- handled = true;
} else if (reason == "exec") {
did_exec = true;
thread_sp->SetStopInfo(
@@ -2365,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 = "replaylog";
} 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 fa3e1cec76e2b3..2492795851388a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -111,7 +111,7 @@ class ProcessGDBRemote : public Process,
// Process Control
Status WillResume() 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 304c12173dd35d..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();
- } else {
- 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 ff6a2f59eba35f..aca08972811470 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -446,8 +446,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
m_memory_cache(*this), m_allocated_memory_cache(*this),
m_should_detach(false), m_next_event_action_up(), m_public_run_lock(),
m_private_run_lock(), m_currently_handling_do_on_removals(false),
- m_resume_requested(false), m_last_run_direction(eRunForward),
- m_interrupt_tid(LLDB_INVALID_THREAD_ID),
+ m_resume_requested(false), m_interrupt_tid(LLDB_INVALID_THREAD_ID),
m_finalizing(false), m_destructing(false),
m_clear_thread_plans_on_stop(false), m_force_next_event_delivery(false),
m_last_broadcast_state(eStateInvalid), m_destroy_in_process(false),
@@ -846,7 +845,6 @@ bool Process::HandleProcessStateChangedEvent(
switch (thread_stop_reason) {
case eStopReasonInvalid:
case eStopReasonNone:
- case eStopReasonHistoryBoundary:
break;
case eStopReasonSignal: {
@@ -1354,7 +1352,7 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
}
}
-Status Process::Resume(RunDirection direction) {
+Status Process::Resume() {
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
LLDB_LOGF(log, "(plugin = %s) -- locking run lock", GetPluginName().data());
if (!m_public_run_lock.TrySetRunning()) {
@@ -1363,7 +1361,7 @@ Status Process::Resume(RunDirection direction) {
return Status::FromErrorString(
"Resume request failed - process still running.");
}
- Status error = PrivateResume(direction);
+ Status error = PrivateResume();
if (!error.Success()) {
// Undo running state change
m_public_run_lock.SetStopped();
@@ -1371,7 +1369,7 @@ Status Process::Resume(RunDirection direction) {
return error;
}
-Status Process::ResumeSynchronous(Stream *stream, RunDirection direction) {
+Status Process::ResumeSynchronous(Stream *stream) {
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
LLDB_LOGF(log, "Process::ResumeSynchronous -- locking run lock");
if (!m_public_run_lock.TrySetRunning()) {
@@ -1384,7 +1382,7 @@ Status Process::ResumeSynchronous(Stream *stream, RunDirection direction) {
Listener::MakeListener(ResumeSynchronousHijackListenerName.data()));
HijackProcessEvents(listener_sp);
- Status error = PrivateResume(direction);
+ Status error = PrivateResume();
if (error.Success()) {
StateType state =
WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream,
@@ -3241,7 +3239,7 @@ Status Process::ConnectRemote(llvm::StringRef remote_url) {
return error;
}
-Status Process::PrivateResume(RunDirection direction) {
+Status Process::PrivateResume() {
Log *log(GetLog(LLDBLog::Process | LLDBLog::Step));
LLDB_LOGF(log,
"Process::PrivateResume() m_stop_id = %u, public state: %s "
@@ -3257,15 +3255,6 @@ Status Process::PrivateResume(RunDirection direction) {
if (!GetModID().IsLastResumeForUserExpression())
ResetExtendedCrashInfoDict();
- if (m_last_run_direction != direction) {
- // In the future we might want to support mixed-direction plans,
- // e.g. a forward step-over stops at a breakpoint, the user does
- // a reverse-step, then disables the breakpoint and continues forward.
- // This code will need to be changed to support that.
- m_thread_list.DiscardThreadPlans();
- m_last_run_direction = direction;
- }
-
Status error(WillResume());
// Tell the process it is about to resume before the thread list
if (error.Success()) {
@@ -3283,7 +3272,7 @@ Status Process::PrivateResume(RunDirection direction) {
"Process::PrivateResume PreResumeActions failed, not resuming.");
} else {
m_mod_id.BumpResumeID();
- error = DoResume(direction);
+ error = DoResume();
if (error.Success()) {
DidResume();
m_thread_list.DidResume();
@@ -3746,7 +3735,7 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) {
"from state: %s",
static_cast<void *>(event_ptr), StateAsCString(state));
ProcessEventData::SetRestartedInEvent(event_ptr, true);
- PrivateResume(m_last_run_direction);
+ PrivateResume();
}
} else {
return_value = true;
@@ -4357,7 +4346,7 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
SetRestarted(true);
// Use the private resume method here, since we aren't changing the run
// lock state.
- process_sp->PrivateResume(process_sp->m_last_run_direction);
+ process_sp->PrivateResume();
} else {
bool hijacked = process_sp->IsHijackedForEvent(eBroadcastBitStateChanged) &&
!process_sp->StateChangedIsHijackedForSynchronousResume();
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 08e9a7c099bad2..bd7032b803df90 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -1212,30 +1212,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";
- else
- return m_description.c_str();
- }
-};
-
// StopInfoThreadPlan
class StopInfoThreadPlan : public StopInfo {
@@ -1463,11 +1439,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 bbb586f033b746..902fbb2b519ef7 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -624,12 +624,10 @@ void Thread::SetupForResume() {
// what the current plan is.
lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
- ProcessSP process_sp(GetProcess());
- if (reg_ctx_sp && process_sp &&
- process_sp->GetLastRunDirection() == 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.
@@ -1734,8 +1732,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/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 b37578fbd82468..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py
+++ /dev/null
@@ -1,115 +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):
- NO_DEBUG_INFO_TESTCASE = True
-
- 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.Continue(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.Continue()
- 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.Continue(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.
- # 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.Continue(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())
- 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 d610761b8cb0bc..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py
+++ /dev/null
@@ -1,30 +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.Continue(lldb.eRunReverse)
- self.assertFailure(status, "target does not support reverse-continue")
-
- status = process.Continue()
- self.assertSuccess(status)
- self.assertState(process.GetState(), lldb.eStateExited)
- self.assertEqual(process.GetExitStatus(), 0)
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 40e45dc9f5c317..00000000000000
--- a/lldb/test/API/functionalities/reverse-execution/main.c
+++ /dev/null
@@ -1,14 +0,0 @@
-volatile int false_condition = 0;
-
-static void start_recording() {}
-
-static void trigger_breakpoint() {}
-
-static void stop_recording() {}
-
-int main() {
- start_recording();
- trigger_breakpoint();
- stop_recording();
- return 0;
-}
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 211fd34957f496..558f889c4b7f23 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1045,9 +1045,6 @@ llvm::json::Value CreateThreadStopped(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 1c5e3ac7008727..b38833c0fdb6b6 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -111,7 +111,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