[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan created https://github.com/llvm/llvm-project/pull/99736 This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality for use by *tests only*. The majority of this PR is test infrastructure (about 700 of the 950 lines added). >From ce13a715cf12571431b5d7cfc9293dfaa1ff2d4b Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 2 + lldb/include/lldb/Target/Process.h| 25 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 4 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 176 .../Python/lldbsuite/test/lldbreverse.py | 415 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 20 + lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 119 - .../Process/gdb-remote/ProcessGDBRemote.h | 2 + lldb/source/Target/Process.cpp| 29 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 79 .../functionalities/reverse-execution/main.c | 12 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 25 files changed, 946 insertions(+), 28 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create 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 778be79583990..9b17bac0093e6 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -160,6 +160,8 @@ class LLDB_API SBProcess { lldb::SBError Continue(); + lldb::SBError ReverseContinue(); + lldb::SBError Stop(); lldb::SBError Kill(); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index c8475db8ae160..203d3484f3704 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1136,6 +1136,22 @@ class Process : public std::enable_shared_from_this, return error; } + /// Like DoResume() but executes in reverse if supported. + /// + /// \return + /// Returns \b true if the process successfully resumes using + /// the thread run control actions, \b false otherwise. + /// + /// \see Thread:Resume() + /// \see Thread:Step() + /// \see Thread:Suspend() + virtual Status DoResumeReverse() { +Status error; +error.SetErrorStringWithFormatv( +"error: {0} does not support reverse execution of processes", GetPluginName()); +return error; + } + /// Called after resuming a process. /// /// Allow Process plug-ins
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: BTW this was discussed in https://discourse.llvm.org/t/how-to-test-reverse-execution-support-in-lldb/79696. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > I've noticed you didn't check if this works both when the debugger is in > synchronous and asynchronous in your tests. OK, I've added this. > I'm not sure what additional information does the History Boundary stop > reason provides. Can it actually provide historical data to the user ? When a user reverse-continues to the start of recorded time (typically the point where the target was initially execed), execution stops and we must report a reason. None of the existing reasons are appropriate so I created this new one. I've added an explanatory comment to its definition in `lldb-enumerations.h`. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1395,6 +1395,91 @@ Status ProcessGDBRemote::DoResume() { return error; } +Status ProcessGDBRemote::DoResumeReverse() { + Status error; + Log *log = GetLog(GDBRLog::Process); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse()"); + + ListenerSP listener_sp( + Listener::MakeListener("gdb-remote.resume-packet-sent")); + if (listener_sp->StartListeningForEvents( + &m_gdb_comm, GDBRemoteClientBase::eBroadcastBitRunPacketSent)) { +listener_sp->StartListeningForEvents( +&m_async_broadcaster, +ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); + +const size_t num_threads = GetThreadList().GetSize(); + +StreamString continue_packet; + +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(); rocallahan wrote: Done. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,79 @@ +import lldb +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): +@add_test_categories(["dwarf"]) +def test_reverse_continue(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue. We'll stop at the point where we started recording. +status = process.ReverseContinue() +self.assertSuccess(status) +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.assertSuccess(status) +self.assertState(process.GetState(), lldb.eStateExited) +self.assertEqual(process.GetExitStatus(), 0) + +@add_test_categories(["dwarf"]) +def test_reverse_continue_breakpoint(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue to the function "trigger_breakpoint". +trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) +status = process.ReverseContinue() +self.assertSuccess(status) +threads_now = lldbutil.get_threads_stopped_at_breakpoint(process, trigger_bkpt) +self.assertEqual(threads_now, initial_threads) rocallahan wrote: `lldbutil.get_threads_stopped_at_breakpoint()` returns the list of threads stopped at `trigger_bkpt`, and we check that this list is the test's only thread. If we stopped somewhere else, this list will be empty. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,79 @@ +import lldb +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): +@add_test_categories(["dwarf"]) +def test_reverse_continue(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue. We'll stop at the point where we started recording. +status = process.ReverseContinue() +self.assertSuccess(status) +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.assertSuccess(status) +self.assertState(process.GetState(), lldb.eStateExited) +self.assertEqual(process.GetExitStatus(), 0) + +@add_test_categories(["dwarf"]) +def test_reverse_continue_breakpoint(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue to the function "trigger_breakpoint". +trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) +status = process.ReverseContinue() +self.assertSuccess(status) +threads_now = lldbutil.get_threads_stopped_at_breakpoint(process, trigger_bkpt) +self.assertEqual(threads_now, initial_threads) + +@add_test_categories(["dwarf"]) +def test_reverse_continue_skip_breakpoint(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue, skipping a disabled breakpoint at "trigger_breakpoint". +trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) +trigger_bkpt.SetCondition("0") rocallahan wrote: Sorry, my comment was misleading. The goal here is to test reverse-continuing over a conditional breakpoint whose condition is false. We need to continue in the same direction we were going --- if we're not careful we continue forwards from the breakpoint instead, which is broken :-). I've fixed the comment. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,12 @@ +static void start_recording() {} + +static void trigger_breakpoint() {} + +static void stop_recording() {} rocallahan wrote: None of that functionality interacts with reverse execution, so I don't think we need to test it in combination with reverse execution in LLDB. For most purposes reverse execution behaves just like forward execution from LLDB's point of view: there's a stop, then LLDB reads the new target state (memory and registers, mainly) to display information to the user. (There are certainly issues that aren't covered here, e.g. handling the creation and destruction of threads, handling the loading and unloading of shared libraries, and handling watchpoints all interact with reverse execution. I plan to address some of these issues in future work, with their own tests. I'm trying to keep this PR as minimal as possible.) https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,79 @@ +import lldb +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): +@add_test_categories(["dwarf"]) +def test_reverse_continue(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue. We'll stop at the point where we started recording. +status = process.ReverseContinue() +self.assertSuccess(status) +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.assertSuccess(status) +self.assertState(process.GetState(), lldb.eStateExited) +self.assertEqual(process.GetExitStatus(), 0) + +@add_test_categories(["dwarf"]) +def test_reverse_continue_breakpoint(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue to the function "trigger_breakpoint". +trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) +status = process.ReverseContinue() +self.assertSuccess(status) +threads_now = lldbutil.get_threads_stopped_at_breakpoint(process, trigger_bkpt) +self.assertEqual(threads_now, initial_threads) + +@add_test_categories(["dwarf"]) +def test_reverse_continue_skip_breakpoint(self): +target, process, initial_threads = self.setup_recording() + +# Reverse-continue, skipping a disabled breakpoint at "trigger_breakpoint". +trigger_bkpt = target.BreakpointCreateByName("trigger_breakpoint", None) +trigger_bkpt.SetCondition("0") +status = process.ReverseContinue() +self.assertSuccess(status) +self.expect( +"thread list", +STOPPED_DUE_TO_HISTORY_BOUNDARY, +substrs=["stopped", "stop reason = history boundary"], +) + +def setup_recording(self): +""" +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". +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() rocallahan wrote: It's important that we only start recording at the `start_recording` function, not at the very start of the process, because recording execution from the start to `main` (which can be quite a lot of instructions) could be very slow and memory-hungry with the naive `lldbreverse` recorder. I've updated my comments to clarify this. I'm not sure how a stop-hook would help here. For efficiency we want to record the minimal range of instructions that supports the testing we want to do; the `start_recording` and `end_recording` functions mark the boundaries of that range. One-shot breakpoints would be conceptually simpler than manually deleting them, but when I wrote the API calls for one-shot it wasn't simpler. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1881,18 +1970,24 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( handled = true; } } else if (!signo) { -addr_t pc = thread_sp->GetRegisterContext()->GetPC(); -lldb::BreakpointSiteSP bp_site_sp = -thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - -// If a thread is stopped at a breakpoint site, set that as the stop -// reason even if it hasn't executed the breakpoint instruction yet. -// We will silently step over the breakpoint when we resume execution -// and miss the fact that this thread hit the breakpoint. -if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( - *thread_sp, bp_site_sp->GetID())); +if (m_last_run_direction == eRunReverse) { rocallahan wrote: Good idea, thanks. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1881,18 +1970,24 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( handled = true; } } else if (!signo) { -addr_t pc = thread_sp->GetRegisterContext()->GetPC(); -lldb::BreakpointSiteSP bp_site_sp = -thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - -// If a thread is stopped at a breakpoint site, set that as the stop -// reason even if it hasn't executed the breakpoint instruction yet. -// We will silently step over the breakpoint when we resume execution -// and miss the fact that this thread hit the breakpoint. -if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( - *thread_sp, bp_site_sp->GetID())); +if (m_last_run_direction == eRunReverse) { rocallahan wrote: Actually we don't need this code so I've taken it out. (The latest version of rr reports the history boundary stop using `replaylog` --- more or less standard, gdb has supported it for 16 years --- so this "signal 0 when reverse continuing" case would only be hit when using LLDB with non-latest rr, which I don't think we need to care about.) https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 25e184d1f0d06c09726ef72c0b3f1966522ea3df Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 2 + lldb/include/lldb/Target/Process.h| 25 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 176 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 20 + lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 94 .../Process/gdb-remote/ProcessGDBRemote.h | 2 + lldb/source/Target/Process.cpp| 29 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 119 + .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 25 files changed, 979 insertions(+), 17 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create 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 778be79583990..9b17bac0093e6 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -160,6 +160,8 @@ class LLDB_API SBProcess { lldb::SBError Continue(); + lldb::SBError ReverseContinue(); + lldb::SBError Stop(); lldb::SBError Kill(); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index c8475db8ae160..203d3484f3704 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1136,6 +1136,22 @@ class Process : public std::enable_shared_from_this, return error; } + /// Like DoResume() but executes in reverse if supported. + /// + /// \return + /// Returns \b true if the process successfully resumes using + /// the thread run control actions, \b false otherwise. + /// + /// \see Thread:Resume() + /// \see Thread:Step() + /// \see Thread:Suspend() + virtual Status DoResumeReverse() { +Status error; +error.SetErrorStringWithFormatv( +"error: {0} does not support reverse execution of processes", GetPluginName()); +return error; + } + /// Called after resuming a process. /// /// Allow Process plug-ins to execute some code after resuming a process. @@ -2367,6 +2383,8 @@ class Process : public std::enable_shared_from_this, bool IsRunning() const; + lldb::RunDirection GetLastRunDirection() { return m_last_run_direction; } + DynamicCheckerFunctions *GetDynamicCheckers() { return m_dynamic_checkers_up.get(); } @@ -2861,7 +2879,7 @@ void PruneThreadPlans(); /// /// \return /// An Status object describing the success or failure of the resume. - Status PrivateResume(); + Status PrivateResume(lldb::RunDirection direction = lldb::eRunForward); // Called i
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -160,6 +160,8 @@ class LLDB_API SBProcess { lldb::SBError Continue(); + lldb::SBError ReverseContinue(); rocallahan wrote: Yeah OK. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1395,6 +1395,94 @@ Status ProcessGDBRemote::DoResume() { return error; } +Status ProcessGDBRemote::DoResumeReverse() { + Status error; + Log *log = GetLog(GDBRLog::Process); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse()"); + + ListenerSP listener_sp( + Listener::MakeListener("gdb-remote.resume-packet-sent")); + if (listener_sp->StartListeningForEvents( + &m_gdb_comm, GDBRemoteClientBase::eBroadcastBitRunPacketSent)) { +listener_sp->StartListeningForEvents( +&m_async_broadcaster, +ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); + +const size_t num_threads = GetThreadList().GetSize(); + +StreamString continue_packet; + +// 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(); +// We can only `bc` to reverse-continue all threads, +// or `bs` to reverse-step the current thread (which may also +// reverse-continue other threads by some amount). +// These packets do not support delivering signals. +if (num_continue_C_tids > 0 || num_continue_S_tids > 0) { + error.SetErrorString("can't deliver signals while running in reverse"); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: Signals not supported"); + return error; +} + +if (num_continue_s_tids > 0) { + if (num_continue_s_tids > 1) { +error.SetErrorString("can't step multiple threads while reverse-stepping"); +LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: can't step multiple threads"); +return error; + } + + if (!m_gdb_comm.GetReverseStepSupported()) { +error.SetErrorString("target does not support reverse-stepping"); +LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: target does not support reverse-stepping"); +return error; + } + + m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front()); + continue_packet.PutCString("bs"); +} else { + if (!m_gdb_comm.GetReverseContinueSupported()) { +error.SetErrorString("target does not support reverse-continue"); +LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: target does not support reverse-continue"); +return error; + } + + // All threads continue whether requested or not --- + // we can't change how threads ran in the past. + continue_packet.PutCString("bc"); +} + +EventSP event_sp; +if (!m_async_thread.IsJoinable()) { + error.SetErrorString("Trying to resume but the async thread is dead."); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: Trying to resume but the " + "async thread is dead."); + return error; +} + +auto data_sp = +std::make_shared(continue_packet.GetString()); +m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp); + +if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) { rocallahan wrote: This was copied from `ProcessGDBRemote::DoResume()`. I can refactor that. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3264,6 +3266,11 @@ Status Process::PrivateResume() { // filters before resuming. UpdateAutomaticSignalFiltering(); + if (m_last_run_direction != direction) { rocallahan wrote: TBH I don't understand thread plans very well yet so I was trying to avoid interacting with them. I guess implementing your suggestion means extending thread plans with a `RunDirection`, and/or creating new plan subclasses? And then we'd have to test a lot of interactions. Would it be OK to defer that to a future patch to keep this patch reasonably small? https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3264,6 +3266,11 @@ Status Process::PrivateResume() { // filters before resuming. UpdateAutomaticSignalFiltering(); + if (m_last_run_direction != direction) { rocallahan wrote: I'm a bit worried that in general thread plans have a lot of complexity, and adding more complexity by allowing multiple stacked plans with different directions might be bad enough for maintainability that it's overall a bad idea. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3264,6 +3266,11 @@ Status Process::PrivateResume() { // filters before resuming. UpdateAutomaticSignalFiltering(); + if (m_last_run_direction != direction) { rocallahan wrote: If the user does "continue", hits a breakpoint, does "reverse-step", and then "reverse-continue" presumably we do have to abandon the original "continue". Since this patch only implements "reverse-continue" maybe always abandoning the thread plans actually the right thing to do for now? https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan edited https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3281,7 +3288,11 @@ Status Process::PrivateResume() { "Process::PrivateResume PreResumeActions failed, not resuming."); } else { m_mod_id.BumpResumeID(); -error = DoResume(); +if (direction == eRunForward) { + error = DoResume(); rocallahan wrote: The advantage of separate `DoResume()` and `DoResumeReverse()` methods is that `Process` subclasses that don't support reverse execution don't have to change at all; they inherit the default `DoResumeReverse()` that returns an error. If I make `DoResume()` take a direction parameter then those implementations (three out of four AFAICT) need to add a check of the direction parameter. It's not a big deal, I'll change it. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > You might have to be careful in the case where someone runs a function call, > stops at a breakpoint in the function call and decides to go backwards in the > function execution (if that's possible). That is not possible in rr. During user function calls it responds to reverse execution requests with an immediate stop. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 5ecca71b03027e132f3b75612c0783a68eafdf4f Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 2 +- lldb/include/lldb/Target/Process.h| 20 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 176 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 6 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 78 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 11 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 119 + .../TestReverseContinueNotSupported.py| 29 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 976 insertions(+), 44 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 778be79583990..cb7775ae94e46 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -158,7 +158,7 @@ class LLDB_API SBProcess { lldb::SBError Destroy(); - lldb::SBError Continue(); + lldb::SBError Continue(RunDirection direction = RunDirection::eRunForward); lldb::SBError Stop(); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index c8475db8ae160..51d9c166fdda5 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { Status error; -error.SetErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); +if (direction == lldb::RunDirection::eRunForward) { + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); +} else { + error.SetErrorStringWithFormatv( + "error: {0} does not support reverse execution of processes", GetPluginName()); +} return error; } @@ -2
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3281,7 +3288,11 @@ Status Process::PrivateResume() { "Process::PrivateResume PreResumeActions failed, not resuming."); } else { m_mod_id.BumpResumeID(); -error = DoResume(); +if (direction == eRunForward) { + error = DoResume(); rocallahan wrote: I've updated the branch with all these changes. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,176 @@ +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) + +self.port = self.get_next_port() rocallahan wrote: Yes, fixed. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -0,0 +1,119 @@ +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): +@add_test_categories(["dwarf"]) rocallahan wrote: Yes, thanks for that. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -158,7 +158,7 @@ class LLDB_API SBProcess { lldb::SBError Destroy(); - lldb::SBError Continue(); + lldb::SBError Continue(RunDirection direction = RunDirection::eRunForward); rocallahan wrote: Yeah, I originally wrote everything as you suggested, and @jimingham asked me to change it to what you see now. So I need you two to come to an agreement and tell me what it is. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1363,6 +1374,43 @@ Status ProcessGDBRemote::DoResume() { } } +if (direction == RunDirection::eRunReverse && continue_packet_error) { + if (num_continue_C_tids > 0 || num_continue_S_tids > 0) { +error.SetErrorString("can't deliver signals while running in reverse"); +LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: Signals not supported"); +return error; + } + + if (num_continue_s_tids > 0) { +if (num_continue_s_tids > 1) { + error.SetErrorString("can't step multiple threads while reverse-stepping"); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: can't step multiple threads"); + return error; +} + +if (!m_gdb_comm.GetReverseStepSupported()) { + error.SetErrorString("target does not support reverse-stepping"); + LLDB_LOGF(log, "ProcessGDBRemote::DoResumeReverse: target does not support reverse-stepping"); + return error; +} + +m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front()); +continue_packet.PutCString("bs"); + } else { +if (!m_gdb_comm.GetReverseContinueSupported()) { rocallahan wrote: We need to determine whether we're going to step or continue first, so we can check whether the specific packet (`bs` or `bc`) we need is supported. I suppose we could collapse them into one feature flag and check that flag a bit earlier --- that would work fine in practice --- but I think what I have here, with a feature flag check right where we use that exact feature, is a little more intuitive. I think the priority here should be the simplest, clearest code; "user tries to reverse-continue but that's not supported" is not a case that needs to be optimized. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 026930762e967f84f48f8958c2448734692ad62f Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 2 +- lldb/include/lldb/Target/Process.h| 20 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 6 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 78 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 11 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 972 insertions(+), 44 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 778be79583990..cb7775ae94e46 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -158,7 +158,7 @@ class LLDB_API SBProcess { lldb::SBError Destroy(); - lldb::SBError Continue(); + lldb::SBError Continue(RunDirection direction = RunDirection::eRunForward); lldb::SBError Stop(); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index c8475db8ae160..51d9c166fdda5 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { Status error; -error.SetErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); +if (direction == lldb::RunDirection::eRunForward) { + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); +} else { + error.SetErrorStringWithFormatv( + "error: {0} does not support reverse execution of processes", GetPluginName()); +} return error; } @@ -2
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > Most of the execution control logic should just know "forward" and > "backwards", but then whether those are implemented by using the reverse > debugging machinery or by allowing the program to run for realz will be know > deeper in the execution control machinery - most likely governed by the > thread plans. Actually LLDB is (and should be) oblivious to whether the gdbserver is running the program "for realz" or not. When using rr, we currently *never* run the program "for realz" while the user is in a debugging session. The workflow is: a) record a program run and save the recording to disk b) replay the run with the debugger attached. During b), both forward and reverse execution are "on rails", only observing what happened during recording. (Ok, ignoring user-requested function calls made through the debugger for now.) UndoDB and gdb's reverse execution are a bit different. They do support the workflow you're thinking of, where the program is actually "live" while you explore history in the past. But the distinction between "replaying through history" and "runinng live" is never surfaced in the gdbserver protocol and from the debugger's point of view I don't think it should matter. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > First off, for systems that do past motion and forward motion, there are > things you really can't do effectively in the past, like set variable values > and have that make any difference. So we probably will need to know whether > we're executing in the immutable past or the mutable present. Fair point, but AFAIK with all these backends when you try to change state in a situation where that's not allowed, you just get an error from the backend. The gdbserver protocol doesn't tell you in advance whether that will be possible. I don't think this impacts LLDB really, as long as you don't crash when a state change fails. > I am running "for realz", and I do a forward "next" which hits a breakpoint > before the next concludes. I step over another function at that breakpoint. > I realize I wish I had stepped into it, so I do a "reverse next" - is that > how you do it - or set a breakpoint in the function and reverse continue. FWIW rr doesn't support this workflow, but UndoDB does. > Then I step around in the past a bit till I see what I wanted to see. Then > I'm done with the past, and want to go back to the present. Since the last > persistent action I had done was the original next, then `continue` should > take up that next (going forward) and complete it. That is all pretty > straightforward, the "TheadPlanStepOverRange" - which is the current plan on > the plan stack - for that next knows it's going forward, so first it pushes a > "ThreadPlanTakeMeToThePresent" and when that completes, it can continue with > its forward motion. In this case, I think ThreadPlanStepOverRange will just resume with a forward-continue packet. The backend continues forward through the recorded history until it reaches the end of the history, i.e. the current state of the stopped debuggee. Then it automatically resumes the debuggee and keeps going. There is no need for a ThreadPlanTakeMeToThePresent. > So for systems that support live reverse debugging, I do think we'll need a > "reset to the present" gesture, and plans will need to know whether they are > operating on the past or present. I think we'll need to have per-plan directions in some way, yes, but not "reset to the present". https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: One thing that's not entirely clear to me from the discussion so far: apparently the public API rules allow adding an overload of `SBProcess::Continue()` with a direction parameter. Do they allow just adding a direction parameter to the existing overload *with a default value*? Because the latter seems exactly like the former in practice, to me. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From e9a44b4cfd2e3423fbf5ac75124530cc2bb8afed Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 20 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 78 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 11 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 975 insertions(+), 42 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 778be79583990..ba069014defd2 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 c8475db8ae160..51d9c166fdda5 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { Status error; -error.SetErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); +if (direction == lldb::RunDirection::eRunForward) { + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); +} else { + error.SetErrorStringWithFormatv( + "error: {0} does not support reverse execution of processes", GetPluginName()); +} return error; } @@ -2367,6 +2372,8 @@ class Process
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > The two are different when it comes to the ABI Yeah OK. I've fixed that. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > As it stands, this will allow "reverse continue to a breakpoint", right? Using rr as the backend you can reverse-continue to any stop, including signals, watchpoints and the "history boundary" i.e. start of time. I expect the other stop types don't work well yet. I plan to work on them next. We can delay adding the CLI for reverse-continue until they work adequately. > But once "in the past" you wouldn't be able to do either forward or reverse > steps, you are just going to navigate by breakpoint? After reverse-continue you can do any kind of forward execution you want. With LLDB + rr, you're always "in the past" since during debugging rr always/only navigates history; when you're at a certain point in time the state of LLDB and rr is independent of whether you got there by forward or reverse execution. And LLDB + rr is pretty much fully functional already --- except for the absence of reverse-execution commands. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > Is there a notion of "reverse stepping" like "take me to the line that > preceded this one in execution history", and if so what contains the logic > that does that? rr supports the "bs" gdbserver packet to reverse-step a single instruction (and so does the test proxy I'm adding here). To "reverse-next one line" we will need to implement a thread plan that uses a combination of reverse-step-instruction and reverse-continue-to-breakpoint. That's future work. It may be difficult, and it's also not very high priority because it tends not to get used very much by gdb users. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: @clayborg as far as I can tell, the ball is currently in your court to respond to @jimingham ... thanks in advance https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > > @clayborg as far as I can tell, the ball is currently in your court to > > respond to @jimingham ... thanks in advance > > Sounds like Jim is on the fence with a SetDirection + existing APIs and > adding a direction to the calls. I am fine with either approach as long as > Jim is ok with it because Jim is the code owner of the thread plans so he has > better knowledge. Let me know if I missed any comment I should respond to > other than this. The initial disagreement here was that you advocated for a `ReverseContinue()` function (etc) while Jim didn't want to add `Reverse` versions of functions. It sounds like you're on board with the latter now, so thanks for that. So now the question is whether to expose a persistent "current direction" flag or pass the direction as a parameter (defaulting to "forward") to each call to a function that advances execution. > It really comes down to how the GUI and command line commands work for > reverse debugging. So a few questions: > > * Do GUI debuggers have different buttons for reverse stepping and > running? Or is there a direction button and then the existing process control > buttons remain the same (reverse continue, reverse step in/out/over) I've only seen them use separate buttons, see e.g. [CLion + UndoDB](https://blog.jetbrains.com/clion/2016/09/undo-for-clion/). > * For command line do we have different comments for forward and reverse, > or a direction command followed by normal commands? GDB [supports both](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Reverse-Execution.html). However, in practice I've never seen anyone use `set exec-direction`. My LLDB CLI patch adds a `-R` option to `thread continue`. > If the GUI and command line have separate buttons and commands, then we > should probably go with adding the direction to each API. OK, then I believe my current code is satisfactory. > I could see us adding more options to the `SBThreadStepOptions` API in the > future and then our public API for `SBThread::StepOver` doesn't need to > change. Sure. My current code doesn't support reverse stepping and the number of options to the `Continue()` APIs is small (zero currently for `SBProcess::Continue()`) so this isn't an issue yet. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 52b133ee9fda7b6cc3b6300756e7b8ec82a6a9bf Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 20 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 78 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 11 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 23 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 974 insertions(+), 41 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 778be795839901..ba069014defd24 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 cf16fbc812aa48..5fa6d54838f8c8 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { Status error; -error.SetErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); +if (direction == lldb::RunDirection::eRunForward) { + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); +} else { + error.SetErrorStringWithFormatv( + "error: {0} does not support reverse execution of processes", GetPluginName()); +} return error; } @@ -2373,6 +2378,8 @@ class Proc
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 3aa5a6f08487314f12b7b0d2d13ccd20f306f16c Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 20 +- lldb/include/lldb/Target/StopInfo.h | 3 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 78 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 11 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 975 insertions(+), 42 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 778be795839901..ba069014defd24 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 cf16fbc812aa48..5fa6d54838f8c8 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { Status error; -error.SetErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); +if (direction == lldb::RunDirection::eRunForward) { + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); +} else { + error.SetErrorStringWithFormatv( + "error: {0} does not support reverse execution of processes", GetPluginName()); +} return error; } @@ -2373,6 +2378,8 @@ class Proc
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: @clayborg @jimingham I think the issues you have raised so far are satisfactorily addressed by the current code. Can you confirm that is true? And if so, can we proceed with the actual code review? Thanks. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From c373425ab4be848bb376d2710e13efafb6058d11 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 23 +- lldb/include/lldb/Target/StopInfo.h | 6 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 179 +++ .../Python/lldbsuite/test/lldbreverse.py | 444 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 10 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 38 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 123 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 1035 insertions(+), 50 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..8b8ed830b54cc0 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..6efeb0d3694a6a 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -857,10 +857,11 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, + lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1104,9 +1105,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} }
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > added @skipIfDarwin markers to the TestReverseContinueBreakpoints.py and > TestReverseContinueNotSupported.py API tests because lldb-server is not > supported in gdbserver mode on Darwin systems So there is no LLDB-based daemon that implements the gdbserver protocol on Darwin systems? https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: > @rocallahan does rr work on Mac? No, it doesn't. It does work on Linux AAarch64 though. > This didn't work because we also build lldb-server on macOS. Hmm, so lldb-server is built on macOS but we're not supposed to use it? https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: I'd like the tests to work on Mac. I'm getting some assistance and we'll report back in a few days. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > @rocallahan Let me know if you need me to merge this on your behalf. Please do! Thanks! https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: I don't know what your normal protocol is but maybe you should revert it while I debug the failure? The last successful CI run in this PR was from September 25. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From bb96e6ddd2d6448be01b1965591cf8ee77e14569 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 23 +- lldb/include/lldb/Target/StopInfo.h | 6 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 178 +++ .../Python/lldbsuite/test/lldbreverse.py | 445 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 38 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 123 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 1034 insertions(+), 50 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..8b8ed830b54cc0 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..6efeb0d3694a6a 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -857,10 +857,11 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, + lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1104,9 +1105,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} }
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan created https://github.com/llvm/llvm-project/pull/112079 This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. >From 6bd33589417195eafe945f2d2f57b01352f56568 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 21 +- lldb/include/lldb/Target/StopInfo.h | 6 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 77 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 9 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 29 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 978 insertions(+), 44 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..8b8ed830b54cc0 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..fe7fbc50fd5770 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, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1104,9 +1104,14 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: I have created a new PR #112079 to continue work on this. Is there a way to run the full post-merge CI test suite against a Github PR? https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan edited https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From 9f33f8e5e0efb74772022c4ffadb65a6aefedf55 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 23 +- lldb/include/lldb/Target/StopInfo.h | 6 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 179 +++ .../Python/lldbsuite/test/lldbreverse.py | 444 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 10 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 38 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 123 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 1035 insertions(+), 50 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..8b8ed830b54cc0 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..6efeb0d3694a6a 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -857,10 +857,11 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, + lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1104,9 +1105,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} }
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: I adapted the code from here https://github.com/llvm/llvm-project/blob/a62768c427ec1f34d7c3823021a6c5a794709103/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py#L516 into `lldbgdbproxy.py`: ``` +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"] ``` That's supposed to select `debugserver` when `lldb_server` is not available. I guess that isn't working. Should it work? https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: > I'd say that this is failing because macos generates slightly different > packet sequences, and the test is not expecting those. Makes sense. But given Mac tests don't run against PRs, and I don't have a Mac, how am I supposed to debug this? https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: > My notion was that when you push a plan that has an intention to run in a > direction, if the plan above it on the stack was going in the opposite > direction, it has to be popped. That's in the current code in this PR but I agree that was the wrong direction. My experimental [reverse-continue-thread-plan](https://github.com/rocallahan/llvm-project/tree/reverse-continue-thread-plan) branch doesn't do this. > After all, you might be doing a backwards direction next, but hit a > breakpoint while doing that. You then want to step FORWARDS from that > breakpoint to check something out. Right. > Then if stepping backwards and forwards were working like lldb stepping > currently works, you'd expect "continue" to return control to the backwards > next to finish out the operation. There's a UX issue here: in the scenario you describe (hit breakpoint during reverse-next, step forward, continue) *should* the reverse-step be resumed? Personally I think not. I think it's very confusing if "continue" ever causes reverse execution (and likewise if "reverse-continue" ever causes forward execution). So in this case I would say "reverse-continue" should resume the reverse-next but "continue" should pop it. This is helpful discussion but it doesn't directly address my question in https://github.com/llvm/llvm-project/pull/112079#issuecomment-2468857787. Can we focus on that? https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: Giving ThreadPlans a direction gets complicated when there are multiple runnable threads, because the topmost plans for different runnable threads could disagree about the execution direction, which is obviously unworkable. In my experimental branch I linked above, I resolve this by defaulting to forward execution if there's a disagreement and popping reverse-execution plans from runnable threads until all the topmost plans agree on forward execution. But this means that reverse-continue has to push a `ThreadPlanReverseContinue` onto all threads' plan stacks. So when the reverse-continue is over we really need to pop those `ThreadPlanReverseContinue`s from all threads. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: The approach I implemented fails when evaluating a breakpoint condition requires running a function in the target process, e.g. evaluating a breakpoint condition that's a function call, or calling `mmap()` to allocate memory for JITted code. That pushes a `ThreadPlanCallFunction` onto the plan stack and resumes the target in the forward direction. With my code as-is, switching directions discards all thread plans before resuming, so we discard the `ThreadPlanCallFunction` and everything breaks. In this case we need the `ThreadPlanCallFunction` to complete normally and then when the breakpoint condition has finished evaluating to false, resume execution in the reverse direction. So it seems like we should use the thread plan stack --- associate a direction with each thread plan, so `ThreadPlanCallFunction` executes forward and completes, but after it has been popped, the thread plan below it will tell us to execute in reverse. So I tried adding a virtual function `ThreadPlan::GetDirection()` and [introducing `ThreadPlanReverseContinue`](https://github.com/rocallahan/llvm-project/tree/reverse-continue-thread-plan) which executes in reverse. `SBProcess::ReverseContinue()` pushes a `ThreadPlanReverseContinue` onto the plan stack and resumes. There is big question about when/how this plan should be removed. In principle we should remove it when a stop is reported to the user. I tried making `ThreadPlanReverseContinue::MischiefManaged()` always return true. That doesn't work because it makes us pop the `ThreadPlanReverseContinue` before the breakpoint condition is even evaluated. So what would be a good way to pop `ThreadPlanReverseContinue`? An alternative approach would be to store a "current direction" in `ThreadPlanBase` and have `SBProcess::Continue/ReverseContinue` both set it. But that is kind of scary because any execution command that doesn't go through `SBProcess::Continue/ReverseContinue` will resume in the last-used direction. But let me know if that sounds better. @jimingham this all sounds like your territory. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: Thanks, that sounds OK but I don't see how it would help with my main question right now: > So what would be a good way to pop `ThreadPlanReverseContinue`? Put it another way: if we change the plan stack state to request reverse execution (push a `ThreadPlanReverseContinue`, or change some state on `ThreadPlanBase`), when/how would be the right place in the code to undo that change? It has to happen before any user-initiated forward-execution command resumes the target, but it must not happen when we stop for a breakpoint whose condition turns out to be false. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: > I worry that in a situation like this where there's a pending task people > will go the wrong way and lose important state because they forgot that > "continue" doesn't mean "continue what I was doing" - which is what it > currently means in lldb I don't know of any other debugger that supports the equivalent of a thread plan stack, and even though I've been neck-deep in debuggers for a long time I didn't know about this LLDB feature until I started working on this PR, so TBH I think most users will assume "continue" works like any other debugger and just resumes execution forwards, and are surprised (hopefully in a good way) if/when they discover it's more complicated than that. And therefore will be surprised in a bad way if/when they discover that "continue" runs backwards in some situations. > I think ultimately I'm arguing against requiring: "we either have all forward > or all backwards plans on any given thread plan stack" because I don't think > that is flexible enough to support all the use cases we want to support. I agree and as I said above, I've already removed that requirement in my experimental branch. I haven't added a notion of "no-direction-opinion" plans yet, but most of what you said above makes sense even if we don't have that. Let's consider a really simple case where the user does a reverse-continue, hits an unconditional breakpoint, and then wants to execute forwards. One question is, what command should they use to execute forwards? I've been assuming that they would just use `process continue`, but if you really want `process continue` to resume the reverse-continue and we should have a separate command or flag to switch to forwards, we can do that. We should probably settle this now because it's quite fundamental. The other question is, what should the thread plan stacks look like during this scenario? https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: @clayborg @jimingham Can I please have some love? I don't want to keep telling users "you should be using GDB" and I've done a significant amount of work here. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -142,6 +142,9 @@ class StopInfo : public std::enable_shared_from_this { static lldb::StopInfoSP CreateStopReasonProcessorTrace(Thread &thread, const char *description); + static lldb::StopInfoSP rocallahan wrote: Adding a comment. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -510,8 +510,9 @@ def start(self): self._thread.start() def stop(self): -self._thread.join() -self._thread = None +if self._thread is not None: rocallahan wrote: This is not an LLDB stop or an LLDB thread. `thread_` is the `MockGdbServer`'s Python worker thread, and `stop()` is the method you call to shut down the server. I'm making this method work in the case where you call `stop()` before `start()` has been called, in the `GDBProxyTestBase.tearDown()` test scaffolding. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3271,6 +3273,11 @@ Status Process::PrivateResume() { if (!GetModID().IsLastResumeForUserExpression()) ResetExtendedCrashInfoDict(); + if (m_last_run_direction != direction) { rocallahan wrote: Done. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan edited https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan edited https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: > Ack, sorry I'm bad at the formalities. No problem. Thank you for your time. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -158,7 +158,7 @@ class LLDB_API SBProcess { lldb::SBError Destroy(); - lldb::SBError Continue(); + lldb::SBError Continue(RunDirection direction = RunDirection::eRunForward); rocallahan wrote: I have made this change. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -203,11 +203,17 @@ ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, return error; } -Status ProcessWindows::DoResume() { +Status ProcessWindows::DoResume(RunDirection direction) { Log *log = GetLog(WindowsLog::Process); llvm::sys::ScopedLock lock(m_mutex); Status error; + if (direction == RunDirection::eRunReverse) { rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3139,6 +3146,7 @@ void PruneThreadPlans(); // m_currently_handling_do_on_removals are true, // Resume will only request a resume, using this // flag to check. + lldb::RunDirection m_last_run_direction; rocallahan wrote: Jim indicated that he doesn't want it initialized inline here. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -402,9 +402,16 @@ lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { Status ProcessKDP::WillResume() { return Status(); } -Status ProcessKDP::DoResume() { +Status ProcessKDP::DoResume(RunDirection direction) { rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan edited https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -874,10 +874,10 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -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() override; + Status DoResume(lldb::RunDirection direction) override; rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -52,7 +52,7 @@ class ScriptedProcess : public Process { void DidResume() override; - Status DoResume() override; + Status DoResume(lldb::RunDirection direction) override; rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -90,7 +90,7 @@ class ProcessKDP : public lldb_private::Process { // Process Control lldb_private::Status WillResume() override; - lldb_private::Status DoResume() override; + lldb_private::Status DoResume(lldb::RunDirection direction) override; rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -111,7 +111,7 @@ class ProcessGDBRemote : public Process, // Process Control Status WillResume() override; - Status DoResume() override; + Status DoResume(lldb::RunDirection direction) override; rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -182,10 +182,17 @@ void ScriptedProcess::DidResume() { m_pid = GetInterface().GetProcessID(); } -Status ScriptedProcess::DoResume() { +Status ScriptedProcess::DoResume(RunDirection direction) { rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3169,6 +3176,7 @@ void PruneThreadPlans(); // m_currently_handling_do_on_removals are true, // Resume will only request a resume, using this // flag to check. + lldb::RunDirection m_last_run_direction; rocallahan wrote: Ah I see. @clayborg suggested I initialize `m_last_run_direction` inline but fortunately I never got around to doing that :-). https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -1129,10 +1129,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { + virtual Status DoResume(lldb::RunDirection direction) { rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -203,11 +203,17 @@ ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, return error; } -Status ProcessWindows::DoResume() { +Status ProcessWindows::DoResume(RunDirection direction) { rocallahan wrote: The decision was to use a direction flag. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
@@ -3169,6 +3176,7 @@ void PruneThreadPlans(); // m_currently_handling_do_on_removals are true, // Resume will only request a resume, using this // flag to check. + lldb::RunDirection m_last_run_direction; rocallahan wrote: > This should have a doc string. OK, will do. > So I personally wouldn't initialize this one here, Maybe I'm misunderstanding you, but I'm not initializing `m_last_run_direction` here. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/99736 >From 4bc3e8453a2fffa7c444ed9aa4bdc51e8e54569f Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ReverseContinue()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. So, for testing purposes, `lldbreverse.py` wraps `lldb-server` with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 21 +- lldb/include/lldb/Target/StopInfo.h | 6 + lldb/include/lldb/lldb-enumerations.h | 6 + .../Python/lldbsuite/test/gdbclientutils.py | 5 +- .../Python/lldbsuite/test/lldbgdbproxy.py | 175 .../Python/lldbsuite/test/lldbreverse.py | 418 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + lldb/source/API/SBProcess.cpp | 8 +- lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 8 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 77 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 9 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 29 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 8 +- .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 115 + .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 32 files changed, 978 insertions(+), 44 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..8b8ed830b54cc0 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..fe7fbc50fd5770 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, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - Status Resume(); + Status Resume(lldb::RunDirection direction = lldb::eRunForward); /// Resume a process, and wait for it to stop. - Status ResumeSynchronous(Stream *stream); + Status ResumeSynchronous(Stream *stream, lldb::RunDirection direction = lldb::eRunForward); /// Halts a running process. /// @@ -1104,9 +1104,14 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} } /// Called after resuming a process. @
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #99736)
rocallahan wrote: I see @clayborg still has a "change requested" hold on this PR. As far as I can tell all his comments have been addressed. https://github.com/llvm/llvm-project/pull/99736 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
rocallahan wrote: In any case I am OOO and mostly offline until Nov 26. Rob https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From 6d8f3ccf7b30334853e07e141f41545d68870bb8 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ContinueInDirection()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 18 +- lldb/include/lldb/Target/StopInfo.h | 7 + lldb/include/lldb/Target/Thread.h | 12 +- lldb/include/lldb/Target/ThreadList.h | 6 +- lldb/include/lldb/Target/ThreadPlan.h | 2 + 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 | 184 +++ .../Python/lldbsuite/test/lldbreverse.py | 480 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + .../tools/lldb-server/lldbgdbserverutils.py | 15 +- lldb/source/API/SBProcess.cpp | 8 + lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 33 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 13 +- lldb/source/Target/ThreadList.cpp | 62 ++- lldb/source/Target/ThreadPlanBase.cpp | 4 + .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 151 ++ .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 39 files changed, 1176 insertions(+), 76 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..882b8bd837131d 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..7b8ec7ae39f2b7 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1104,9 +1104,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} } /// Called after resuming a process. @@ -2674,6 +2680,11 @@ void PruneThreadPlans(); const AddressRange &range, size_t alignment,
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From 91d40f5e331b97a202208c221ef6b11784dc8ca2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ContinueInDirection()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 16 +- lldb/include/lldb/Target/StopInfo.h | 7 + lldb/include/lldb/Target/Thread.h | 12 +- lldb/include/lldb/Target/ThreadList.h | 6 +- lldb/include/lldb/Target/ThreadPlan.h | 4 + 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 | 184 +++ .../Python/lldbsuite/test/lldbreverse.py | 480 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + .../tools/lldb-server/lldbgdbserverutils.py | 15 +- lldb/source/API/SBProcess.cpp | 8 + lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 13 +- lldb/source/Target/ThreadList.cpp | 62 ++- lldb/source/Target/ThreadPlanBase.cpp | 4 + .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 151 ++ .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 39 files changed, 1173 insertions(+), 71 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..882b8bd837131d 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..80663d6b1fddcb 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1104,9 +1104,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} } /// Called after resuming a process. @@ -2674,6 +2680,9 @@ void PruneThreadPlans(); const AddressRange &range, size_t alignment,
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From c0904fed59e42d957e2b40698c4343fdb5582b21 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Jul 2024 22:46:42 +1200 Subject: [PATCH] [lldb] Implement basic support for reverse-continue This commit only adds support for the `SBProcess::ContinueInDirection()` API. A user-accessible command for this will follow in a later commit. This feature depends on a gdbserver implementation (e.g. `rr`) providing support for the `bc` and `bs` packets. `lldb-server` does not support those packets, and there is no plan to change that. with a Python implementation of *very limited* record-and-replay functionality. --- lldb/include/lldb/API/SBProcess.h | 1 + lldb/include/lldb/Target/Process.h| 16 +- lldb/include/lldb/Target/StopInfo.h | 7 + lldb/include/lldb/Target/Thread.h | 12 +- lldb/include/lldb/Target/ThreadList.h | 6 +- lldb/include/lldb/Target/ThreadPlan.h | 4 + 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 | 185 +++ .../Python/lldbsuite/test/lldbreverse.py | 489 ++ .../Python/lldbsuite/test/lldbtest.py | 2 + .../tools/lldb-server/lldbgdbserverutils.py | 15 +- lldb/source/API/SBProcess.cpp | 8 + lldb/source/API/SBThread.cpp | 2 + .../source/Interpreter/CommandInterpreter.cpp | 3 +- .../Process/Linux/NativeThreadLinux.cpp | 3 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 9 +- .../Process/MacOSX-Kernel/ProcessKDP.h| 2 +- .../Process/Windows/Common/ProcessWindows.cpp | 9 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../GDBRemoteCommunicationClient.cpp | 22 + .../gdb-remote/GDBRemoteCommunicationClient.h | 6 + .../GDBRemoteCommunicationServerLLGS.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 88 +++- .../Process/gdb-remote/ProcessGDBRemote.h | 2 +- .../Process/scripted/ScriptedProcess.cpp | 10 +- .../Process/scripted/ScriptedProcess.h| 2 +- lldb/source/Target/Process.cpp| 25 +- lldb/source/Target/StopInfo.cpp | 29 ++ lldb/source/Target/Thread.cpp | 13 +- lldb/source/Target/ThreadList.cpp | 62 ++- lldb/source/Target/ThreadPlanBase.cpp | 4 + .../reverse-execution/Makefile| 3 + .../TestReverseContinueBreakpoints.py | 151 ++ .../TestReverseContinueNotSupported.py| 30 ++ .../functionalities/reverse-execution/main.c | 14 + lldb/tools/lldb-dap/JSONUtils.cpp | 3 + lldb/tools/lldb-dap/LLDBUtils.cpp | 1 + 39 files changed, 1183 insertions(+), 71 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/lldbgdbproxy.py create mode 100644 lldb/packages/Python/lldbsuite/test/lldbreverse.py create mode 100644 lldb/test/API/functionalities/reverse-execution/Makefile create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueBreakpoints.py create mode 100644 lldb/test/API/functionalities/reverse-execution/TestReverseContinueNotSupported.py create 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 1624e02070b1b2..882b8bd837131d 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -159,6 +159,7 @@ 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 b8c53a474ba6b9..80663d6b1fddcb 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1104,9 +1104,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} } /// Called after resuming a process. @@ -2674,6 +2680,9 @@ void PruneThreadPlans(); const AddressRange &range, size_t alignment,
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
rocallahan wrote: Ok, tell me what you think of this proposal: 1) Each thread plan has a virtual `GetDirection()` method returning `RunDirection`. Existing plans other than `ThreadBasePlan` return `eRunForward`. 2) There is a per-process `base direction` flag. `ThreadBasePlan::GetDirection()` returns the value of that flag. Defaults to `eRunForward`. 3) There is a new `SBProcess::ContinueInDirection(direction)` method. This method updates the "process base direction" flag. For simplicity, for now, _if the base direction changed_, pop all plans on all threads. 4) `SBProcess::Continue()` is unchanged, i.e. preserves the base direction. 5) When we resume execution: 5a) If we choose to resume a single runnable thread whose current plan has `StopOthers()` , just resume using that plan's direction. 5b) Otherwise use the process base direction, and before resuming, pop plans until all threads' current plans match that direction. I think this is fairly simple while behaving much like what you suggest. It doesn't require introducing a new kind of `ThreadPlan` which is good. I think it can extend cleanly to support reverse-step etc. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Reland "[lldb] Implement basic support for reverse-continue" (#123906)" (PR #123945)
rocallahan wrote: @adrian-prantl can we have that help please? Also, is that link supposed to be accessible to the public? Because it's 404 for me. https://github.com/llvm/llvm-project/pull/123945 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add support for gdb-style 'x' packet (PR #124733)
rocallahan wrote: It sounds fine. rr HEAD uses the Gdb flavour for GDB and the old-LLDB flavor for LLDB. After a decent amount of time has passed I will update to the new regime. https://github.com/llvm/llvm-project/pull/124733 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add support for gdb-style 'x' packet (PR #124733)
rocallahan wrote: And thanks! https://github.com/llvm/llvm-project/pull/124733 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From b021a56268c74010eae017d2d1169ab8b79978b3 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:40:34 + Subject: [PATCH 1/9] [lldb] Move thread-notification setup to happen later This lets us check `run_me_only_list.GetSize()` instead of `wants_solo_run`. --- lldb/source/Target/ThreadList.cpp | 28 ++-- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 1a2d7dd61c778f..b44e53e0673b47 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -540,20 +540,6 @@ bool ThreadList::WillResume() { } } - if (wants_solo_run) { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning on notification of new threads while single " - "stepping a thread."); -m_process.StartNoticingNewThreads(); - } else { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning off notification of new threads while single " - "stepping a thread."); -m_process.StopNoticingNewThreads(); - } - // 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 @@ -607,6 +593,20 @@ bool ThreadList::WillResume() { } } + if (run_me_only_list.GetSize(false) == 0) { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning on notification of new threads while single " + "stepping a thread."); +m_process.StartNoticingNewThreads(); + } else { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning off notification of new threads while single " + "stepping a thread."); +m_process.StopNoticingNewThreads(); + } + bool need_to_resume = true; if (run_me_only_list.GetSize(false) == 0) { >From 5164b418ea8e606729b24d0705f70e040aed8757 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:46:01 + Subject: [PATCH 2/9] [lldb] Make `Thread::WillResume()` report whether it pushed a `ThreadPlanStepOverBreakpoint` We'll need this later to determine whether we need to account for the newly-pushed `ThreadPlanStepOverBreakpoint`. --- lldb/include/lldb/Target/Thread.h | 13 - lldb/source/Target/Thread.cpp | 6 -- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 38b65b2bc58490..ef66fa11574db9 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -200,11 +200,14 @@ class Thread : public std::enable_shared_from_this, ///The User resume state for this thread. lldb::StateType GetResumeState() const { return m_resume_state; } - // 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. - void SetupForResume(); + /// 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 SetupForResume(); // Do not override this function, it is for thread plan logic only bool ShouldResume(lldb::StateType resume_state); diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index a6130f6b925bbf..b5261310970611 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -617,7 +617,7 @@ void Thread::WillStop() { current_plan->WillStop(); } -void Thread::SetupForResume() { +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 @@ -625,7 +625,7 @@ void Thread::SetupForResume() { // without actually running this thread. In that case, for this thread we // shouldn't push a step over breakpoint plan or do that work. if (GetCurrentPlan()->IsVirtualStep()) - return; + return false; // If we're at a breakpoint push the step-over breakpoint plan. Do this // before telling the current plan it will resume, since we might change @@ -663,11 +663,13 @@ void Thread::SetupForResume() { step_bp_plan->SetAutoContinue(true);
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -115,14 +115,18 @@ 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, ///\b false means start & stopped events will be generated, but ///the process will not actually run. The thread must then return ///the correct StopInfo when asked. /// - bool WillResume(); + bool WillResume(lldb::RunDirection *direction); rocallahan wrote: Made it a reference. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -1104,9 +1104,15 @@ class Process : public std::enable_shared_from_this, /// \see Thread:Resume() /// \see Thread:Step() /// \see Thread:Suspend() - virtual Status DoResume() { -return Status::FromErrorStringWithFormatv( -"error: {0} does not support resuming processes", GetPluginName()); + 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()); +} rocallahan wrote: Done. I fixed this everywhere in the PR. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -583,6 +583,14 @@ SBError SBProcess::Continue() { return sb_error; } +SBError SBProcess::ContinueInDirection(RunDirection direction) { + ProcessSP process_sp(GetSP()); + if (process_sp) { +process_sp->SetBaseDirection(direction); + } rocallahan wrote: It needs to be `if (ProcessSP process_sp = GetSP())`. Done. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -0,0 +1,185 @@ +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") +_validate_checksums = True + +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) + +if lldbplatformutil.getPlatform() == "macosx": +self.debug_monitor_exe = lldbgdbserverutils.get_debugserver_exe() +self.debug_monitor_extra_args = [] +# debugserver does not produce correct checksums +self._validate_checksums = False +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 get_next_port(self): +return 12000 + random.randint(0, 3999) rocallahan wrote: Removed. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -0,0 +1,185 @@ +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") +_validate_checksums = True + +def setUpBaseLogging(self): +self.logger = logging.getLogger(__name__) + +if len(self.logger.handlers) > 0: +return # We have set up this handler already + rocallahan wrote: Removed this. I had copied it from `gdbremote_testcase.py`; it seems to be unnecessary there too. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From 0c9f80e8d0e925cc75e6ef2696955e2a60782689 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:40:34 + Subject: [PATCH 1/9] Move thread-notification setup to happen later and check run_me_only_list instead of wants_solo_run --- lldb/source/Target/ThreadList.cpp | 28 ++-- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 1a2d7dd61c778f..b44e53e0673b47 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -540,20 +540,6 @@ bool ThreadList::WillResume() { } } - if (wants_solo_run) { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning on notification of new threads while single " - "stepping a thread."); -m_process.StartNoticingNewThreads(); - } else { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning off notification of new threads while single " - "stepping a thread."); -m_process.StopNoticingNewThreads(); - } - // 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 @@ -607,6 +593,20 @@ bool ThreadList::WillResume() { } } + if (run_me_only_list.GetSize(false) == 0) { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning on notification of new threads while single " + "stepping a thread."); +m_process.StartNoticingNewThreads(); + } else { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning off notification of new threads while single " + "stepping a thread."); +m_process.StopNoticingNewThreads(); + } + bool need_to_resume = true; if (run_me_only_list.GetSize(false) == 0) { >From f5d538f5a4088a792a1e3d47eeaef9390d1ace2e Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:46:01 + Subject: [PATCH 2/9] Make Thread::WillResume report whether it pushed a ThreadPlanStepOverBreakpoint --- lldb/include/lldb/Target/Thread.h | 13 - lldb/source/Target/Thread.cpp | 6 -- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 38b65b2bc58490..ef66fa11574db9 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -200,11 +200,14 @@ class Thread : public std::enable_shared_from_this, ///The User resume state for this thread. lldb::StateType GetResumeState() const { return m_resume_state; } - // 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. - void SetupForResume(); + /// 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 SetupForResume(); // Do not override this function, it is for thread plan logic only bool ShouldResume(lldb::StateType resume_state); diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index a6130f6b925bbf..b5261310970611 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -617,7 +617,7 @@ void Thread::WillStop() { current_plan->WillStop(); } -void Thread::SetupForResume() { +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 @@ -625,7 +625,7 @@ void Thread::SetupForResume() { // without actually running this thread. In that case, for this thread we // shouldn't push a step over breakpoint plan or do that work. if (GetCurrentPlan()->IsVirtualStep()) - return; + return false; // If we're at a breakpoint push the step-over breakpoint plan. Do this // before telling the current plan it will resume, since we might change @@ -663,11 +663,13 @@ void Thread::SetupForResume() { step_bp_plan->SetAutoContinue(true); } QueueThreadPlan(step_bp_plan_sp, false); +return true; } } } } } + return false; }
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -608,19 +594,47 @@ bool ThreadList::WillResume() { } bool need_to_resume = true; - if (run_me_only_list.GetSize(false) == 0) { +*direction = m_process.GetBaseDirection(); +// We've determined the direction so now we can determine which +// threads need to step over breakpoints. +for (pos = m_threads.begin(); pos != end; ++pos) { + if ((*pos)->GetResumeState() != eStateSuspended && + (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) { +if ((*pos)->IsOperatingSystemPluginThread() && +!(*pos)->GetBackingThread()) + continue; +if ((*pos)->SetupToStepOverBreakpointIfNeeded(*direction)) { + run_me_only_list.AddThread(*pos); + break; +} + } +} + } // else we'll set *direction to the direction of the chosen thread later + if (run_me_only_list.GetSize(false) == 0) { +// *direction has been set to m_process.GetBaseDirection(). // Everybody runs as they wish: for (pos = m_threads.begin(); pos != end; ++pos) { ThreadSP thread_sp(*pos); StateType run_state; - if (thread_sp->GetResumeState() != eStateSuspended) + if (thread_sp->GetResumeState() != eStateSuspended) { rocallahan wrote: Done. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -0,0 +1,151 @@ +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 rocallahan wrote: Done. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -199,6 +199,20 @@ 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(); + } rocallahan wrote: Fixed this everywhere it occurred in my PR. https://github.com/llvm/llvm-project/pull/112079 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
https://github.com/rocallahan updated https://github.com/llvm/llvm-project/pull/112079 >From 0c9f80e8d0e925cc75e6ef2696955e2a60782689 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:40:34 + Subject: [PATCH 1/9] Move thread-notification setup to happen later and check run_me_only_list instead of wants_solo_run --- lldb/source/Target/ThreadList.cpp | 28 ++-- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 1a2d7dd61c778f..b44e53e0673b47 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -540,20 +540,6 @@ bool ThreadList::WillResume() { } } - if (wants_solo_run) { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning on notification of new threads while single " - "stepping a thread."); -m_process.StartNoticingNewThreads(); - } else { -Log *log = GetLog(LLDBLog::Step); -if (log && log->GetVerbose()) - LLDB_LOGF(log, "Turning off notification of new threads while single " - "stepping a thread."); -m_process.StopNoticingNewThreads(); - } - // 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 @@ -607,6 +593,20 @@ bool ThreadList::WillResume() { } } + if (run_me_only_list.GetSize(false) == 0) { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning on notification of new threads while single " + "stepping a thread."); +m_process.StartNoticingNewThreads(); + } else { +Log *log = GetLog(LLDBLog::Step); +if (log && log->GetVerbose()) + LLDB_LOGF(log, "Turning off notification of new threads while single " + "stepping a thread."); +m_process.StopNoticingNewThreads(); + } + bool need_to_resume = true; if (run_me_only_list.GetSize(false) == 0) { >From f5d538f5a4088a792a1e3d47eeaef9390d1ace2e Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 17 Dec 2024 23:46:01 + Subject: [PATCH 2/9] Make Thread::WillResume report whether it pushed a ThreadPlanStepOverBreakpoint --- lldb/include/lldb/Target/Thread.h | 13 - lldb/source/Target/Thread.cpp | 6 -- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 38b65b2bc58490..ef66fa11574db9 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -200,11 +200,14 @@ class Thread : public std::enable_shared_from_this, ///The User resume state for this thread. lldb::StateType GetResumeState() const { return m_resume_state; } - // 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. - void SetupForResume(); + /// 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 SetupForResume(); // Do not override this function, it is for thread plan logic only bool ShouldResume(lldb::StateType resume_state); diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index a6130f6b925bbf..b5261310970611 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -617,7 +617,7 @@ void Thread::WillStop() { current_plan->WillStop(); } -void Thread::SetupForResume() { +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 @@ -625,7 +625,7 @@ void Thread::SetupForResume() { // without actually running this thread. In that case, for this thread we // shouldn't push a step over breakpoint plan or do that work. if (GetCurrentPlan()->IsVirtualStep()) - return; + return false; // If we're at a breakpoint push the step-over breakpoint plan. Do this // before telling the current plan it will resume, since we might change @@ -663,11 +663,13 @@ void Thread::SetupForResume() { step_bp_plan->SetAutoContinue(true); } QueueThreadPlan(step_bp_plan_sp, false); +return true; } } } } } + return false; }
[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
@@ -0,0 +1,185 @@ +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") +_validate_checksums = True + +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) + +if lldbplatformutil.getPlatform() == "macosx": +self.debug_monitor_exe = lldbgdbserverutils.get_debugserver_exe() +self.debug_monitor_extra_args = [] +# debugserver does not produce correct checksums +self._validate_checksums = False +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 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()) +