mgorny created this revision. mgorny added reviewers: labath, emaste, krytarowski, jingham. Herald added a subscriber: arichardson. Herald added a project: All. mgorny requested review of this revision.
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 https://reviews.llvm.org/D128989 Files: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
Index: lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py =================================================================== --- lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py +++ lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py @@ -137,3 +137,55 @@ ret["O_content"]) self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), ret["O_content"]) + + @add_test_categories(["fork"]) + def test_vCont_both_nonstop(self): + parent_pid, parent_tid, child_pid, child_tid = ( + self.start_fork_test(["fork", "process:sync", "print-pid", + "process:sync", "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.*"}, + # see the comment in TestNonStop.py, test_stdio + "read packet: $vStdio#00", + "read packet: $vStdio#00", + "send packet: $OK#00", + ], True) + ret = self.expect_gdbremote_sequence() + self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(), + ret["O_content"]) + self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), + ret["O_content"]) + + def vCont_both_nonstop_test(self, vCont_packet): + parent_pid, parent_tid, child_pid, child_tid = ( + self.start_fork_test(["fork", "process:sync", "print-pid", + "process:sync", "stop"], + nonstop=True)) + + self.test_sequence.add_log_lines([ + "read packet: ${}#00".format(vCont_packet), + "send packet: $OK#00", + {"direction": "send", "regex": "%Stop:T.*"}, + # see the comment in TestNonStop.py, test_stdio + "read packet: $vStdio#00", + "read packet: $vStdio#00", + "send packet: $OK#00", + ], True) + ret = self.expect_gdbremote_sequence() + self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(), + ret["O_content"]) + self.assertIn("PID: {}".format(int(child_pid, 16)).encode(), + ret["O_content"]) + + @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") Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1751,6 +1751,7 @@ 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; @@ -1759,37 +1760,40 @@ // 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"); pid = pid_tid->first; tid = pid_tid->second; - } - if (pid == StringExtractorGDBRemote::AllProcesses) { - if (m_debugged_processes.size() > 1) - return SendIllFormedResponse( - packet, "Resuming multiple processes not supported yet"); - if (!m_continue_process) { - LLDB_LOG(log, "no debugged process"); - return SendErrorResponse(0x36); + // 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 process selected via Hc"); + return SendErrorResponse(0x36); + } + pid = m_continue_process->GetID(); } - 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) { + 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);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits