[Lldb-commits] [lldb] f8603c1 - [lldb] [llgs] Support resuming multiple processes via vCont w/ nonstop

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Mon Aug 1 09:52:54 PDT 2022


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")


        


More information about the lldb-commits mailing list