mgorny created this revision.
mgorny added reviewers: labath, emaste, krytarowski.
mgorny requested review of this revision.

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.


https://reviews.llvm.org/D100261

Files:
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -90,6 +90,7 @@
   const NativeProcessProtocol::Factory &m_process_factory;
   lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
   lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
+  lldb::pid_t m_current_pid = LLDB_INVALID_PROCESS_ID;
   std::recursive_mutex m_debugged_process_mutex;
   std::unique_ptr<NativeProcessProtocol> m_debugged_process_up;
   std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>>
@@ -233,9 +234,17 @@
 
   // Verify and get the process instance selected by the client.
   // If run is true, the process selected by "Hc" packet will be returned,
-  // otherwise the one selected by "Hg" will be used.  Returns nullptr if there
-  // is no process debugged.
-  NativeProcessProtocol *GetCurrentProcess(bool run) const;
+  // otherwise the one selected by "Hg" will be used.
+  //
+  // If allow_subprocess is true, a subprocess instance may be returned.
+  // Otherwise, only the main process can be returned and the function will
+  // return nullptr if a subprocess is selected.
+  //
+  // Returns nullptr if there is no process debugged.
+  NativeProcessProtocol *GetCurrentProcess(bool run,
+                                           bool allow_subprocess = false) const;
+
+  void SetCurrentProcessID(lldb::pid_t pid, lldb::tid_t tid);
 
 private:
   llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml();
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
@@ -1624,6 +1624,9 @@
   m_current_tid = tid;
   if (m_debugged_process_up)
     m_debugged_process_up->SetCurrentThreadID(m_current_tid);
+
+  // Reset subprocess support
+  m_current_pid = LLDB_INVALID_PROCESS_ID;
 }
 
 void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
@@ -2081,12 +2084,32 @@
   }
 
   // Parse out the thread number.
-  llvm::Expected<lldb::tid_t> tid_ret =
-      ReadTid(packet, /*run=*/h_variant == 'c', /*allow_all=*/true);
-  if (!tid_ret)
-    return SendErrorResponse(tid_ret.takeError());
+  auto *process = GetCurrentProcess(h_variant == 'c', true);
+  auto pid_tid =
+      packet.GetPidTid(process ? 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 != m_debugged_process_up->GetID()) {
+    // Is it a subprocess?
+    if (m_additional_processes.find(pid) == m_additional_processes.end())
+      return SendErrorResponse(llvm::make_error<StringError>(
+          inconvertibleErrorCode(),
+          llvm::formatv("PID {0} not debugged", pid)));
+    if (h_variant != 'g')
+      return SendUnimplementedResponse(
+          "Hc packet for subprocess not supported");
+
+    SetCurrentProcessID(pid, tid);
+    return SendOKResponse();
+  }
 
-  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) {
@@ -2622,7 +2645,7 @@
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
   // Ensure we have a process.
-  auto *process = GetCurrentProcess(false);
+  auto *process = GetCurrentProcess(false, true);
   if (!process) {
     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
     LLDB_LOG(log, "failed, no process available");
@@ -3622,12 +3645,33 @@
                    "Enabling protocol extensions failed: {0}");
 }
 
-NativeProcessProtocol *
-GDBRemoteCommunicationServerLLGS::GetCurrentProcess(bool run) const {
+NativeProcessProtocol *GDBRemoteCommunicationServerLLGS::GetCurrentProcess(
+    bool run, bool allow_subprocess) const {
   // Fail if we don't have a current process.
   if (!m_debugged_process_up ||
       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
     return nullptr;
 
+  // Check if another process was selected via Hg.
+  if (!run && m_current_pid != LLDB_INVALID_PROCESS_ID &&
+      m_current_pid != m_debugged_process_up->GetID()) {
+    if (!allow_subprocess)
+      return nullptr;
+
+    auto it = m_additional_processes.find(m_current_pid);
+    if (it == m_additional_processes.end())
+      return nullptr;
+    return it->second.get();
+  }
+
   return m_debugged_process_up.get();
 }
+
+void GDBRemoteCommunicationServerLLGS::SetCurrentProcessID(lldb::pid_t pid,
+                                                           lldb::tid_t tid) {
+  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+  LLDB_LOG(log, "setting current subprocess to {0}, thread id {1}", pid, tid);
+
+  m_current_pid = pid;
+  m_current_tid = tid;
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to