diff options
5 files changed, 100 insertions, 22 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 4fbfa982e0d..16a339c86c2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -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), @@ -114,10 +115,28 @@ 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; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 92f90c63702..c7ac21d83ad 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -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; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index e207ebd9153..035c6128db9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -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) diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index ef4a26683f2..e776cef689e 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -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 diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 25d04a35eeb..489a025fe60 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -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 |