forked from OSchip/llvm-project
Added a new packet to our GDB remote protocol:
QListThreadsInStopReply This GDB remote query command can enable added a "threads" key/value pair to all stop reply packets so that we always get a list of all threads in each stop reply packet. It increases performance if enabled (the reply to the "QListThreadsInStopReply" is "OK") by saving us from sending to command/reply pairs (the "qfThreadInfo" and "qsThreadInfo" packets), and also helps us keep the current process state up to date. llvm-svn: 154380
This commit is contained in:
parent
0752624970
commit
4463399b0d
|
@ -38,6 +38,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
|
|||
GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet", is_platform),
|
||||
m_supports_not_sending_acks (eLazyBoolCalculate),
|
||||
m_supports_thread_suffix (eLazyBoolCalculate),
|
||||
m_supports_threads_in_stop_reply (eLazyBoolCalculate),
|
||||
m_supports_vCont_all (eLazyBoolCalculate),
|
||||
m_supports_vCont_any (eLazyBoolCalculate),
|
||||
m_supports_vCont_c (eLazyBoolCalculate),
|
||||
|
@ -113,11 +114,29 @@ GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported ()
|
||||
{
|
||||
if (m_supports_threads_in_stop_reply == eLazyBoolCalculate)
|
||||
{
|
||||
m_supports_threads_in_stop_reply = eLazyBoolNo;
|
||||
|
||||
StringExtractorGDBRemote response;
|
||||
if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false))
|
||||
{
|
||||
if (response.IsOKResponse())
|
||||
m_supports_threads_in_stop_reply = eLazyBoolYes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GDBRemoteCommunicationClient::ResetDiscoverableSettings()
|
||||
{
|
||||
m_supports_not_sending_acks = eLazyBoolCalculate;
|
||||
m_supports_thread_suffix = eLazyBoolCalculate;
|
||||
m_supports_threads_in_stop_reply = eLazyBoolCalculate;
|
||||
m_supports_vCont_c = eLazyBoolCalculate;
|
||||
m_supports_vCont_C = eLazyBoolCalculate;
|
||||
m_supports_vCont_s = eLazyBoolCalculate;
|
||||
|
|
|
@ -71,6 +71,9 @@ public:
|
|||
void
|
||||
QueryNoAckModeSupported ();
|
||||
|
||||
void
|
||||
GetListThreadsInStopReplySupported ();
|
||||
|
||||
bool
|
||||
SendAsyncSignal (int signo);
|
||||
|
||||
|
@ -335,6 +338,7 @@ protected:
|
|||
//------------------------------------------------------------------
|
||||
lldb_private::LazyBool m_supports_not_sending_acks;
|
||||
lldb_private::LazyBool m_supports_thread_suffix;
|
||||
lldb_private::LazyBool m_supports_threads_in_stop_reply;
|
||||
lldb_private::LazyBool m_supports_vCont_all;
|
||||
lldb_private::LazyBool m_supports_vCont_any;
|
||||
lldb_private::LazyBool m_supports_vCont_c;
|
||||
|
|
|
@ -704,6 +704,7 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
|
|||
m_gdb_comm.ResetDiscoverableSettings();
|
||||
m_gdb_comm.QueryNoAckModeSupported ();
|
||||
m_gdb_comm.GetThreadSuffixSupported ();
|
||||
m_gdb_comm.GetListThreadsInStopReplySupported ();
|
||||
m_gdb_comm.GetHostInfo ();
|
||||
m_gdb_comm.GetVContSupported ('c');
|
||||
return error;
|
||||
|
@ -1262,8 +1263,9 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
|
|||
{
|
||||
Mutex::Locker locker(m_thread_ids_mutex);
|
||||
m_thread_ids.clear();
|
||||
// A comma separated list of all threads in the current process including
|
||||
// the thread for this stop reply packet
|
||||
// A comma separated list of all threads in the current
|
||||
// process that includes the thread for this stop reply
|
||||
// packet
|
||||
size_t comma_pos;
|
||||
lldb::tid_t tid;
|
||||
while ((comma_pos = value.find(',')) != std::string::npos)
|
||||
|
|
|
@ -76,8 +76,9 @@ RNBRemote::RNBRemote () :
|
|||
m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
|
||||
m_extended_mode(false),
|
||||
m_noack_mode(false),
|
||||
m_use_native_regs (false),
|
||||
m_thread_suffix_supported (false),
|
||||
m_use_native_regs (false)
|
||||
m_list_threads_in_stop_reply (false)
|
||||
{
|
||||
DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
|
||||
CreatePacketTable ();
|
||||
|
@ -183,6 +184,7 @@ RNBRemote::CreatePacketTable ()
|
|||
t.push_back (Packet (set_stdout, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet"));
|
||||
t.push_back (Packet (set_stderr, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet"));
|
||||
t.push_back (Packet (set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet"));
|
||||
t.push_back (Packet (set_list_threads_in_stop_reply,&RNBRemote::HandlePacket_QListThreadsInStopReply , NULL, "QListThreadsInStopReply", "Set if the 'threads' key should be added to the stop reply packets with a list of all thread IDs."));
|
||||
// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
|
||||
t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
|
||||
t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
|
||||
|
@ -1128,12 +1130,12 @@ RNBRemote::NotifyThatProcessStopped (void)
|
|||
}
|
||||
|
||||
|
||||
/* `A arglen,argnum,arg,...'
|
||||
/* 'A arglen,argnum,arg,...'
|
||||
Update the inferior context CTX with the program name and arg
|
||||
list.
|
||||
The documentation for this packet is underwhelming but my best reading
|
||||
of this is that it is a series of (len, position #, arg)'s, one for
|
||||
each argument with "arg" ``hex encoded'' (two 0-9a-f chars?).
|
||||
each argument with "arg" hex encoded (two 0-9a-f chars?).
|
||||
Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
|
||||
is sufficient to get around the "," position separator escape issue.
|
||||
|
||||
|
@ -1223,7 +1225,7 @@ RNBRemote::HandlePacket_A (const char *p)
|
|||
return rnb_success;
|
||||
}
|
||||
|
||||
/* `H c t'
|
||||
/* 'H c t'
|
||||
Set the thread for subsequent actions; 'c' for step/continue ops,
|
||||
'g' for other ops. -1 means all threads, 0 means any thread. */
|
||||
|
||||
|
@ -1868,6 +1870,28 @@ RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
|
|||
return SendPacket ("E60"); // Already had a process, too late to set working dir
|
||||
}
|
||||
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p)
|
||||
{
|
||||
// If this packet is received, it allows us to send an extra key/value
|
||||
// pair in the stop reply packets where we will list all of the thread IDs
|
||||
// separated by commas:
|
||||
//
|
||||
// "threads:10a,10b,10c;"
|
||||
//
|
||||
// This will get included in the stop reply packet as something like:
|
||||
//
|
||||
// "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
|
||||
//
|
||||
// This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
|
||||
// speed things up a bit.
|
||||
//
|
||||
// Send the OK packet first so the correct checksum is appended...
|
||||
rnb_err_t result = SendPacket ("OK");
|
||||
m_list_threads_in_stop_reply = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
|
||||
|
@ -2118,6 +2142,33 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
|
|||
if (thread_ident_info.dispatch_qaddr != 0)
|
||||
ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
|
||||
}
|
||||
|
||||
// If a 'QListThreadsInStopReply' was sent to enable this feature, we
|
||||
// will send all thread IDs back in the "threads" key whose value is
|
||||
// a listc of hex thread IDs separated by commas:
|
||||
// "threads:10a,10b,10c;"
|
||||
// This will save the debugger from having to send a pair of qfThreadInfo
|
||||
// and qsThreadInfo packets, but it also might take a lot of room in the
|
||||
// stop reply packet, so it must be enabled only on systems where there
|
||||
// are no limits on packet lengths.
|
||||
|
||||
if (m_list_threads_in_stop_reply)
|
||||
{
|
||||
const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
|
||||
if (numthreads > 0)
|
||||
{
|
||||
ostrm << std::hex << "threads:";
|
||||
for (nub_size_t i = 0; i < numthreads; ++i)
|
||||
{
|
||||
nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
|
||||
if (i > 0)
|
||||
ostrm << ',';
|
||||
ostrm << std::hex << th;
|
||||
}
|
||||
ostrm << ';';
|
||||
}
|
||||
}
|
||||
|
||||
if (g_num_reg_entries == 0)
|
||||
InitializeRegisters ();
|
||||
|
||||
|
@ -2145,7 +2196,7 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
|
|||
return SendPacket("E51");
|
||||
}
|
||||
|
||||
/* `?'
|
||||
/* '?'
|
||||
The stop reply packet - tell gdb what the status of the inferior is.
|
||||
Often called the questionmark_packet. */
|
||||
|
||||
|
@ -2401,7 +2452,7 @@ RNBRemote::HandlePacket_X (const char *p)
|
|||
return SendPacket ("OK");
|
||||
}
|
||||
|
||||
/* `g' -- read registers
|
||||
/* 'g' -- read registers
|
||||
Get the contents of the registers for the current thread,
|
||||
send them to gdb.
|
||||
Should the setting of the Hg packet determine which thread's registers
|
||||
|
@ -2449,7 +2500,7 @@ RNBRemote::HandlePacket_g (const char *p)
|
|||
return SendPacket (ostrm.str ());
|
||||
}
|
||||
|
||||
/* `G XXX...' -- write registers
|
||||
/* 'G XXX...' -- write registers
|
||||
How is the thread for these specified, beyond "the current thread"?
|
||||
Does gdb actually use the Hg packet to set this? */
|
||||
|
||||
|
@ -2809,7 +2860,7 @@ RNBRemote::HandlePacket_v (const char *p)
|
|||
return HandlePacket_UNIMPLEMENTED(p);
|
||||
}
|
||||
|
||||
/* `T XX' -- status of thread
|
||||
/* 'T XX' -- status of thread
|
||||
Check if the specified thread is alive.
|
||||
The thread number is in hex? */
|
||||
|
||||
|
@ -3082,7 +3133,7 @@ RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
|
|||
|
||||
}
|
||||
|
||||
/* `p XX'
|
||||
/* 'p XX'
|
||||
print the contents of register X */
|
||||
|
||||
rnb_err_t
|
||||
|
@ -3147,7 +3198,7 @@ RNBRemote::HandlePacket_p (const char *p)
|
|||
return SendPacket (ostrm.str());
|
||||
}
|
||||
|
||||
/* `Pnn=rrrrr'
|
||||
/* 'Pnn=rrrrr'
|
||||
Set register number n to value r.
|
||||
n and r are hex strings. */
|
||||
|
||||
|
@ -3212,7 +3263,7 @@ RNBRemote::HandlePacket_P (const char *p)
|
|||
return SendPacket ("OK");
|
||||
}
|
||||
|
||||
/* `c [addr]'
|
||||
/* 'c [addr]'
|
||||
Continue, optionally from a specified address. */
|
||||
|
||||
rnb_err_t
|
||||
|
@ -3311,7 +3362,7 @@ RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
|
|||
}
|
||||
|
||||
|
||||
/* `C sig [;addr]'
|
||||
/* 'C sig [;addr]'
|
||||
Resume with signal sig, optionally at address addr. */
|
||||
|
||||
rnb_err_t
|
||||
|
@ -3365,7 +3416,7 @@ RNBRemote::HandlePacket_D (const char *p)
|
|||
return rnb_success;
|
||||
}
|
||||
|
||||
/* `k'
|
||||
/* 'k'
|
||||
Kill the inferior process. */
|
||||
|
||||
rnb_err_t
|
||||
|
@ -3387,7 +3438,7 @@ RNBRemote::HandlePacket_stop_process (const char *p)
|
|||
return rnb_success;
|
||||
}
|
||||
|
||||
/* `s'
|
||||
/* 's'
|
||||
Step the inferior process. */
|
||||
|
||||
rnb_err_t
|
||||
|
@ -3416,7 +3467,7 @@ RNBRemote::HandlePacket_s (const char *p)
|
|||
return rnb_success;
|
||||
}
|
||||
|
||||
/* `S sig [;addr]'
|
||||
/* 'S sig [;addr]'
|
||||
Step with signal sig, optionally at address addr. */
|
||||
|
||||
rnb_err_t
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
set_stdout, // 'QSetSTDOUT:'
|
||||
set_stderr, // 'QSetSTDERR:'
|
||||
set_working_dir, // 'QSetWorkingDir:'
|
||||
set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:'
|
||||
memory_region_info, // 'qMemoryRegionInfo:'
|
||||
allocate_memory, // '_M'
|
||||
deallocate_memory, // '_m'
|
||||
|
@ -177,6 +178,7 @@ public:
|
|||
rnb_err_t HandlePacket_QEnvironment (const char *p);
|
||||
rnb_err_t HandlePacket_QEnvironmentHexEncoded (const char *p);
|
||||
rnb_err_t HandlePacket_QLaunchArch (const char *p);
|
||||
rnb_err_t HandlePacket_QListThreadsInStopReply (const char *p);
|
||||
rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p);
|
||||
rnb_err_t HandlePacket_last_signal (const char *p);
|
||||
rnb_err_t HandlePacket_m (const char *p);
|
||||
|
@ -328,15 +330,15 @@ protected:
|
|||
BreakpointMap m_breakpoints;
|
||||
BreakpointMap m_watchpoints;
|
||||
uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb
|
||||
bool m_extended_mode:1, // are we in extended mode?
|
||||
m_noack_mode:1, // are we in no-ack mode?
|
||||
m_noack_mode_just_enabled:1, // Did we just enable this and need to compute one more checksum?
|
||||
m_use_native_regs:1, // Use native registers by querying DNB layer for register definitions?
|
||||
m_thread_suffix_supported:1; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon:
|
||||
bool m_extended_mode; // are we in extended mode?
|
||||
bool m_noack_mode; // are we in no-ack mode?
|
||||
bool m_use_native_regs; // Use native registers by querying DNB layer for register definitions?
|
||||
bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon:
|
||||
// "$pRR;thread:TTTT;" instead of "$pRR"
|
||||
// "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV"
|
||||
// "$g;thread:TTTT" instead of "$g"
|
||||
// "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV"
|
||||
bool m_list_threads_in_stop_reply;
|
||||
};
|
||||
|
||||
/* We translate the /usr/include/mach/exception_types.h exception types
|
||||
|
|
Loading…
Reference in New Issue