Author: Michał Górny Date: 2022-08-01T18:52:47+02:00 New Revision: f8603c1f6d9eb90bc6a674111bd3441458006601
URL: https://github.com/llvm/llvm-project/commit/f8603c1f6d9eb90bc6a674111bd3441458006601 DIFF: https://github.com/llvm/llvm-project/commit/f8603c1f6d9eb90bc6a674111bd3441458006601.diff LOG: [lldb] [llgs] Support resuming multiple processes via vCont w/ nonstop Support using the vCont packet to resume multiple processes simultaneously when in non-stop mode. The new logic now assumes that: - actions without a thread-id or with process id of "p-1" apply to all debugged processes - actions with a thread-id without process id apply to the current process (m_continue_process) As with the other continue packets, it is only possible to resume processes that are currently stopped (or stop these that are running). It is unsupported to resume or stop individual threads of a running process. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.llvm.org/D128989 Added: Modified: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py Removed: ################################################################################ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 20650b5c8820d..d1b30f74f0bfb 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1762,6 +1762,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( break; } + // If there's no thread-id (e.g. "vCont;c"), it's "p-1.-1". lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses; lldb::tid_t tid = StringExtractorGDBRemote::AllThreads; @@ -1770,7 +1771,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( // Consume the separator. packet.GetChar(); - auto pid_tid = packet.GetPidTid(StringExtractorGDBRemote::AllProcesses); + auto pid_tid = packet.GetPidTid(LLDB_INVALID_PROCESS_ID); if (!pid_tid) return SendIllFormedResponse(packet, "Malformed thread-id"); @@ -1784,29 +1785,35 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( packet, "'t' action not supported for individual threads"); } - if (pid == StringExtractorGDBRemote::AllProcesses) { - if (m_debugged_processes.size() > 1) - return SendIllFormedResponse( - packet, "Resuming multiple processes not supported yet"); + // If we get TID without PID, it's the current process. + if (pid == LLDB_INVALID_PROCESS_ID) { if (!m_continue_process) { - LLDB_LOG(log, "no debugged process"); + LLDB_LOG(log, "no process selected via Hc"); return SendErrorResponse(0x36); } pid = m_continue_process->GetID(); } + assert(pid != LLDB_INVALID_PROCESS_ID); if (tid == StringExtractorGDBRemote::AllThreads) tid = LLDB_INVALID_THREAD_ID; - thread_action.tid = tid; - thread_actions[pid].Append(thread_action); + if (pid == StringExtractorGDBRemote::AllProcesses) { + if (tid != LLDB_INVALID_THREAD_ID) + return SendIllFormedResponse( + packet, "vCont: p-1 is not valid with a specific tid"); + for (auto &process_it : m_debugged_processes) + thread_actions[process_it.first].Append(thread_action); + } else + thread_actions[pid].Append(thread_action); } assert(thread_actions.size() >= 1); - if (thread_actions.size() > 1) + if (thread_actions.size() > 1 && !m_non_stop) return SendIllFormedResponse( - packet, "Resuming multiple processes not supported yet"); + packet, + "Resuming multiple processes is supported in non-stop mode only"); for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) { auto process_it = m_debugged_processes.find(x.first); diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py index daaa15e86ab4a..3714789d22337 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py @@ -150,3 +150,55 @@ def test_c_both_nonstop(self): self.assertEqual(output.count(b"PID: "), 2) self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(), output) self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), output) + + @add_test_categories(["fork"]) + def test_vCont_both_nonstop(self): + lock1 = self.getBuildArtifact("lock1") + lock2 = self.getBuildArtifact("lock2") + parent_pid, parent_tid, child_pid, child_tid = ( + self.start_fork_test(["fork", "process:sync:" + lock1, "print-pid", + "process:sync:" + lock2, "stop"], + nonstop=True)) + + self.test_sequence.add_log_lines([ + "read packet: $vCont;c:p{}.{};c:p{}.{}#00".format( + parent_pid, parent_tid, child_pid, child_tid), + "send packet: $OK#00", + {"direction": "send", "regex": "%Stop:T.*"}, + ], True) + self.expect_gdbremote_sequence() + + output = self.get_all_output_via_vStdio( + lambda output: output.count(b"PID: ") >= 2) + self.assertEqual(output.count(b"PID: "), 2) + self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(), output) + self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), output) + + def vCont_both_nonstop_test(self, vCont_packet): + lock1 = self.getBuildArtifact("lock1") + lock2 = self.getBuildArtifact("lock2") + parent_pid, parent_tid, child_pid, child_tid = ( + self.start_fork_test(["fork", "process:sync:" + lock1, "print-pid", + "process:sync:" + lock2, "stop"], + nonstop=True)) + + self.test_sequence.add_log_lines([ + "read packet: ${}#00".format(vCont_packet), + "send packet: $OK#00", + {"direction": "send", "regex": "%Stop:T.*"}, + ], True) + self.expect_gdbremote_sequence() + + output = self.get_all_output_via_vStdio( + lambda output: output.count(b"PID: ") >= 2) + self.assertEqual(output.count(b"PID: "), 2) + self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(), output) + self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), output) + + @add_test_categories(["fork"]) + def test_vCont_both_implicit_nonstop(self): + self.vCont_both_nonstop_test("vCont;c") + + @add_test_categories(["fork"]) + def test_vCont_both_minus_one_nonstop(self): + self.vCont_both_nonstop_test("vCont;c:p-1.-1") _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits