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 m_debugged_process_up; std::unordered_map> @@ -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> 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 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( + 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( + 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; +}