[Lldb-commits] [lldb] b7c1403 - [lldb] [gdb-remote server] Support selecting process via Hg
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 2 01:23:30 PDT 2021
Author: Michał Górny
Date: 2021-07-02T10:23:11+02:00
New Revision: b7c140335beb11bcbb2abe51222d7a300cd365e5
URL: https://github.com/llvm/llvm-project/commit/b7c140335beb11bcbb2abe51222d7a300cd365e5
DIFF: https://github.com/llvm/llvm-project/commit/b7c140335beb11bcbb2abe51222d7a300cd365e5.diff
LOG: [lldb] [gdb-remote server] Support selecting process via Hg
Support using the extended thread-id syntax with Hg packet to select
a subprocess. This makes it possible to start providing support for
running some of the debugger packets against another subprocesses.
Differential Revision: https://reviews.llvm.org/D100261
Added:
Modified:
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 000d0249cea91..f6c3ba46bb515 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2088,16 +2088,6 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Fail if we don't have a current process.
- if (!m_current_process ||
- (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
// Parse out which variant of $H is requested.
packet.SetFilePos(strlen("H"));
if (packet.GetBytesLeft() < 1) {
@@ -2109,14 +2099,14 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
const char h_variant = packet.GetChar();
- lldb::pid_t default_pid;
+ NativeProcessProtocol *default_process;
switch (h_variant) {
case 'g':
- default_pid = m_current_process->GetID();
+ default_process = m_current_process;
break;
case 'c':
- default_pid = m_continue_process->GetID();
+ default_process = m_continue_process;
break;
default:
@@ -2129,16 +2119,32 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
// Parse out the thread number.
- llvm::Expected<lldb::tid_t> tid_ret =
- ReadTid(packet, /*allow_all=*/true, default_pid);
- if (!tid_ret)
- return SendErrorResponse(tid_ret.takeError());
+ auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
+ : LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "Malformed thread-id"));
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return SendUnimplementedResponse("Selecting all processes not supported");
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "No current process and no PID provided"));
+
+ // Check the process ID and find respective process instance.
+ auto new_process_it = m_debugged_processes.find(pid);
+ if (new_process_it == m_debugged_processes.end())
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("No process with PID {0} debugged", pid)));
- lldb::tid_t tid = tid_ret.get();
// Ensure we have the given thread when not specifying -1 (all threads) or 0
// (any thread).
if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
- NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid);
+ NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid);
if (!thread) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
@@ -2148,13 +2154,15 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
}
}
- // Now switch the given thread type.
+ // Now switch the given process and thread type.
switch (h_variant) {
case 'g':
+ m_current_process = new_process_it->second.get();
SetCurrentThreadID(tid);
break;
case 'c':
+ m_continue_process = new_process_it->second.get();
SetContinueThreadID(tid);
break;
diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
index af39dbbb188b2..bcf728c34b797 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
@@ -16,7 +16,7 @@ def fork_and_detach_test(self, variant):
self.reset_test_sequence()
# continue and expect fork
- fork_regex = "[$]T.*;{}:p([0-9a-f]*)[.]([0-9a-f]*).*".format(variant)
+ fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant)
self.test_sequence.add_log_lines([
"read packet: $c#00",
{"direction": "send", "regex": fork_regex,
@@ -57,3 +57,137 @@ def test_vfork(self):
{"direction": "send", "regex": r"[$]W00#.*"},
], True)
self.expect_gdbremote_sequence()
+
+ def fork_and_follow_test(self, variant):
+ self.build()
+ self.prep_debug_monitor_and_inferior(inferior_args=[variant])
+ self.add_qSupported_packets(["multiprocess+",
+ "{}-events+".format(variant)])
+ ret = self.expect_gdbremote_sequence()
+ self.assertIn("{}-events+".format(variant), ret["qSupported_response"])
+ self.reset_test_sequence()
+
+ # continue and expect fork
+ procinfo_regex = "[$]pid:([0-9a-f]+);.*"
+ fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant)
+ self.test_sequence.add_log_lines([
+ "read packet: $qProcessInfo#00",
+ {"direction": "send", "regex": procinfo_regex,
+ "capture": {1: "parent_pid"}},
+ "read packet: $c#00",
+ {"direction": "send", "regex": fork_regex,
+ "capture": {1: "pid", 2: "tid"}},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ parent_pid, pid, tid = (int(ret[x], 16) for x
+ in ("parent_pid", "pid", "tid"))
+ self.reset_test_sequence()
+
+ # switch to the forked child
+ self.test_sequence.add_log_lines([
+ "read packet: $Hgp{:x}.{:x}#00".format(pid, tid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ "read packet: $Hcp{:x}.{:x}#00".format(pid, tid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ ], True)
+
+ # detach the parent
+ self.test_sequence.add_log_lines([
+ "read packet: $D;{:x}#00".format(parent_pid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ self.reset_test_sequence()
+
+ # resume the child
+ self.test_sequence.add_log_lines([
+ "read packet: $c#00",
+ {"direction": "send", "regex": r"[$]W00#.*"},
+ ], True)
+ self.expect_gdbremote_sequence()
+
+ @add_test_categories(["fork"])
+ def test_fork_follow(self):
+ self.fork_and_follow_test("fork")
+
+ @add_test_categories(["fork"])
+ def test_vfork_follow(self):
+ self.fork_and_follow_test("vfork")
+
+ @add_test_categories(["fork"])
+ def test_select_wrong_pid(self):
+ self.build()
+ self.prep_debug_monitor_and_inferior()
+ self.add_qSupported_packets(["multiprocess+"])
+ ret = self.expect_gdbremote_sequence()
+ self.assertIn("multiprocess+", ret["qSupported_response"])
+ self.reset_test_sequence()
+
+ # get process pid
+ procinfo_regex = "[$]pid:([0-9a-f]+);.*"
+ self.test_sequence.add_log_lines([
+ "read packet: $qProcessInfo#00",
+ {"direction": "send", "regex": procinfo_regex,
+ "capture": {1: "pid"}},
+ "read packet: $qC#00",
+ {"direction": "send", "regex": "[$]QC([0-9a-f]+)#.*",
+ "capture": {1: "tid"}},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ pid, tid = (int(ret[x], 16) for x in ("pid", "tid"))
+ self.reset_test_sequence()
+
+ # try switching to correct pid
+ self.test_sequence.add_log_lines([
+ "read packet: $Hgp{:x}.{:x}#00".format(pid, tid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ "read packet: $Hcp{:x}.{:x}#00".format(pid, tid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+
+ # try switching to invalid tid
+ self.test_sequence.add_log_lines([
+ "read packet: $Hgp{:x}.{:x}#00".format(pid, tid+1),
+ {"direction": "send", "regex": r"[$]E15#.*"},
+ "read packet: $Hcp{:x}.{:x}#00".format(pid, tid+1),
+ {"direction": "send", "regex": r"[$]E15#.*"},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+
+ # try switching to invalid pid
+ self.test_sequence.add_log_lines([
+ "read packet: $Hgp{:x}.{:x}#00".format(pid+1, tid),
+ {"direction": "send", "regex": r"[$]Eff#.*"},
+ "read packet: $Hcp{:x}.{:x}#00".format(pid+1, tid),
+ {"direction": "send", "regex": r"[$]Eff#.*"},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+
+ def test_detach_current(self):
+ self.build()
+ self.prep_debug_monitor_and_inferior()
+ self.add_qSupported_packets(["multiprocess+"])
+ ret = self.expect_gdbremote_sequence()
+ self.assertIn("multiprocess+", ret["qSupported_response"])
+ self.reset_test_sequence()
+
+ # get process pid
+ procinfo_regex = "[$]pid:([0-9a-f]+);.*"
+ self.test_sequence.add_log_lines([
+ "read packet: $qProcessInfo#00",
+ {"direction": "send", "regex": procinfo_regex,
+ "capture": {1: "pid"}},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ pid = int(ret["pid"], 16)
+ self.reset_test_sequence()
+
+ # detach the process
+ self.test_sequence.add_log_lines([
+ "read packet: $D;{:x}#00".format(pid),
+ {"direction": "send", "regex": r"[$]OK#.*"},
+ "read packet: $qC#00",
+ {"direction": "send", "regex": r"[$]E44#.*"},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
More information about the lldb-commits
mailing list