diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -49,6 +49,12 @@ } llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets); +// A trivial struct used to return a pair of PID and TID. +struct PidTid { + uint64_t pid; + uint64_t tid; +}; + class GDBRemoteCommunicationClient : public GDBRemoteClientBase { public: GDBRemoteCommunicationClient(); @@ -336,11 +342,14 @@ // and response times. bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size); - llvm::Optional SendSetCurrentThreadPacket(uint64_t tid, char op); + llvm::Optional + SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, char op); - bool SetCurrentThread(uint64_t tid); + bool SetCurrentThread(uint64_t tid, + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); - bool SetCurrentThreadForRun(uint64_t tid); + bool SetCurrentThreadForRun(uint64_t tid, + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); bool GetQXferAuxvReadSupported(); @@ -576,13 +585,14 @@ m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1, m_supports_jModulesInfo : 1; + /// Current gdb remote protocol process identifier for all other operations lldb::pid_t m_curr_pid = LLDB_INVALID_PROCESS_ID; - lldb::tid_t m_curr_tid = - LLDB_INVALID_THREAD_ID; // Current gdb remote protocol thread index for - // all other operations - lldb::tid_t m_curr_tid_run = - LLDB_INVALID_THREAD_ID; // Current gdb remote protocol thread index for - // continue, step, etc + /// Current gdb remote protocol process identifier for continue, step, etc + lldb::pid_t m_curr_pid_run = LLDB_INVALID_PROCESS_ID; + /// Current gdb remote protocol thread identifier for all other operations + lldb::tid_t m_curr_tid = LLDB_INVALID_THREAD_ID; + /// Current gdb remote protocol thread identifier for continue, step, etc + lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID; uint32_t m_num_supported_hardware_watchpoints = 0; uint32_t m_addressing_bits = 0; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -713,7 +713,8 @@ PacketResult::Success) { if (response.GetChar() == 'Q') { if (response.GetChar() == 'C') { - m_curr_pid = response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID); + m_curr_pid_run = m_curr_pid = + response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID); if (m_curr_pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; @@ -729,10 +730,10 @@ auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable); if (!ids.empty() && !sequence_mutex_unavailable) { // If server returned an explicit PID, use that. - m_curr_pid = ids.front().first; + m_curr_pid_run = m_curr_pid = ids.front().first; // Otherwise, use the TID of the first thread (Linux hack). if (m_curr_pid == LLDB_INVALID_PROCESS_ID) - m_curr_pid = ids.front().second; + m_curr_pid_run = m_curr_pid = ids.front().second; m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; } @@ -1123,7 +1124,7 @@ // if we get pid as well, update m_curr_pid if (pid != 0) { - m_curr_pid = pid; + m_curr_pid_run = m_curr_pid = pid; m_curr_pid_is_valid = eLazyBoolYes; } tid = pid_tid->second; @@ -2137,7 +2138,7 @@ m_qProcessInfo_is_valid = eLazyBoolYes; if (pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; - m_curr_pid = pid; + m_curr_pid_run = m_curr_pid = pid; } // Set the ArchSpec from the triple if we have it. @@ -2639,21 +2640,30 @@ return false; } -llvm::Optional +llvm::Optional GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid, + uint64_t pid, char op) { lldb_private::StreamString packet; packet.PutChar('H'); packet.PutChar(op); + + if (pid != LLDB_INVALID_PROCESS_ID) { + packet.PutChar('p'); + packet.PutHex64(pid); + packet.PutChar('.'); + } + if (tid == UINT64_MAX) packet.PutCString("-1"); else packet.PutHex64(tid); + StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) - return tid; + return {{pid, tid}}; /* * Connected bare-iron target (like YAMON gdb-stub) may not have support for @@ -2663,28 +2673,38 @@ * give us pid and/or tid. Assume pid=tid=1 in such cases. */ if (response.IsUnsupportedResponse() && IsConnected()) - return 1; + return {{1, 1}}; } return llvm::None; } -bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) { - if (m_curr_tid == tid) +bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid, + uint64_t pid) { + if (m_curr_tid == tid && + (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid)) return true; - llvm::Optional ret = SendSetCurrentThreadPacket(tid, 'g'); - if (ret.hasValue()) - m_curr_tid = ret.getValue(); + llvm::Optional ret = SendSetCurrentThreadPacket(tid, pid, 'g'); + if (ret.hasValue()) { + if (ret->pid != LLDB_INVALID_PROCESS_ID) + m_curr_pid = ret->pid; + m_curr_tid = ret->tid; + } return ret.hasValue(); } -bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) { - if (m_curr_tid_run == tid) +bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid, + uint64_t pid) { + if (m_curr_tid_run == tid && + (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid)) return true; - llvm::Optional ret = SendSetCurrentThreadPacket(tid, 'c'); - if (ret.hasValue()) - m_curr_tid_run = ret.getValue(); + llvm::Optional ret = SendSetCurrentThreadPacket(tid, pid, 'c'); + if (ret.hasValue()) { + if (ret->pid != LLDB_INVALID_PROCESS_ID) + m_curr_pid_run = ret->pid; + m_curr_tid_run = ret->tid; + } return ret.hasValue(); }