[lldb] [gdb-remote client] Support switching PID along with TID

Extend the SetCurrentThread() method to support specifying an alternate
PID to switch to.  This makes it possible to issue requests to forked
processes.

Differential Revision: https://reviews.llvm.org/D100262
This commit is contained in:
Michał Górny 2021-04-11 13:04:54 +02:00
parent 0111da2ef8
commit aa319f544a
2 changed files with 57 additions and 27 deletions

View File

@ -713,7 +713,8 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
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 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
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 @@ bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
// 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 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
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 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
return false;
}
llvm::Optional<uint64_t>
llvm::Optional<PidTid>
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 @@ GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid,
* 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<uint64_t> ret = SendSetCurrentThreadPacket(tid, 'g');
if (ret.hasValue())
m_curr_tid = ret.getValue();
llvm::Optional<PidTid> 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<uint64_t> ret = SendSetCurrentThreadPacket(tid, 'c');
if (ret.hasValue())
m_curr_tid_run = ret.getValue();
llvm::Optional<PidTid> 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();
}

View File

@ -49,6 +49,12 @@ inline bool operator==(const QOffsets &a, const QOffsets &b) {
}
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 @@ public:
// and response times.
bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size);
llvm::Optional<uint64_t> SendSetCurrentThreadPacket(uint64_t tid, char op);
llvm::Optional<PidTid>
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 @@ protected:
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;