Author: ewancrawford Date: Wed May 13 04:18:18 2015 New Revision: 237239 URL: http://llvm.org/viewvc/llvm-project?rev=237239&view=rev Log: Remote Non-Stop Support Summary: This patch is the beginnings of support for Non-stop mode in the remote protocol. Letting a user examine stopped threads, while other threads execute freely.
Non-stop mode is enabled using the setting target.non-stop-mode, which sends a QNonStop packet when establishing the remote connection. Changes are also made to treat the '?' stop reply packet differently in non-stop mode, according to spec https://sourceware.org/gdb/current/onlinedocs/gdb/Remote-Non_002dStop.html#Remote-Non_002dStop. A setting for querying the remote for default thread on setup is also included. Handling of '%' async notification packets will be added next. Reviewers: clayborg Subscribers: lldb-commits, ADodds, ted, deepak2427 Differential Revision: http://reviews.llvm.org/D9656 Modified: lldb/trunk/include/lldb/Target/Target.h lldb/trunk/source/Commands/CommandObjectThread.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h lldb/trunk/source/Target/Target.cpp lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp lldb/trunk/source/Utility/StringExtractorGDBRemote.h Modified: lldb/trunk/include/lldb/Target/Target.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Target.h (original) +++ lldb/trunk/include/lldb/Target/Target.h Wed May 13 04:18:18 2015 @@ -189,6 +189,9 @@ public: void SetUserSpecifiedTrapHandlerNames (const Args &args); + + bool + GetNonStopModeEnabled () const; bool GetDisplayRuntimeSupportValues () const; Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectThread.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectThread.cpp Wed May 13 04:18:18 2015 @@ -433,6 +433,12 @@ public: m_step_in_avoid_no_debug = eLazyBoolCalculate; m_step_out_avoid_no_debug = eLazyBoolCalculate; m_run_mode = eOnlyDuringStepping; + + // Check if we are in Non-Stop mode + lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); + if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled()) + m_run_mode = eOnlyThisThread; + m_avoid_regexp.clear(); m_step_in_target.clear(); m_class_name.clear(); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Wed May 13 04:18:18 2015 @@ -424,6 +424,7 @@ GDBRemoteCommunication::CheckForPacket ( content_length = total_length = 1; // The command is one byte long... break; + case '%': // Async notify packet case '$': // Look for a standard gdb packet? { @@ -466,6 +467,7 @@ GDBRemoteCommunication::CheckForPacket ( case '+': case '-': case '\x03': + case '%': case '$': done = true; break; @@ -586,7 +588,7 @@ GDBRemoteCommunication::CheckForPacket ( } } - if (m_bytes[0] == '$') + if (m_bytes[0] == '$' || m_bytes[0] == '%') { assert (checksum_idx < m_bytes.size()); if (::isxdigit (m_bytes[checksum_idx+0]) || Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Wed May 13 04:18:18 2015 @@ -1621,6 +1621,22 @@ GDBRemoteCommunicationClient::GetGDBServ } bool +GDBRemoteCommunicationClient::GetDefaultThreadId (lldb::tid_t &tid) +{ + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qC",response,false) != PacketResult::Success) + return false; + + if (!response.IsNormalResponse()) + return false; + + if (response.GetChar() == 'Q' && response.GetChar() == 'C') + tid = response.GetHexMaxU32(true, -1); + + return true; +} + +bool GDBRemoteCommunicationClient::GetHostInfo (bool force) { Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS)); @@ -2759,6 +2775,25 @@ GDBRemoteCommunicationClient::GetGroupNa return false; } +bool +GDBRemoteCommunicationClient::SetNonStopMode (const bool enable) +{ + // Form non-stop packet request + char packet[32]; + const int packet_len = ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable); + assert(packet_len < (int)sizeof(packet)); + + StringExtractorGDBRemote response; + // Send to target + if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) + if (response.IsOKResponse()) + return true; + + // Failed or not supported + return false; + +} + void GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets) { Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Wed May 13 04:18:18 2015 @@ -318,6 +318,9 @@ public: bool GetHostInfo (bool force = false); + + bool + GetDefaultThreadId (lldb::tid_t &tid); bool GetOSVersion (uint32_t &major, @@ -393,6 +396,9 @@ public: lldb::addr_t addr, // Address of breakpoint or watchpoint uint32_t length); // Byte Size of breakpoint or watchpoint + bool + SetNonStopMode (const bool enable); + void TestPacketSpeed (const uint32_t num_packets); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Wed May 13 04:18:18 2015 @@ -391,7 +391,8 @@ ProcessGDBRemote::ProcessGDBRemote(Targe m_waiting_for_attach (false), m_destroy_tried_resuming (false), m_command_sp (), - m_breakpoint_pc_offset (0) + m_breakpoint_pc_offset (0), + m_initial_tid (LLDB_INVALID_THREAD_ID) { m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue"); @@ -769,8 +770,13 @@ ProcessGDBRemote::DoConnectRemote (Strea // We have a valid process SetID (pid); GetThreadList(); - if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false) == GDBRemoteCommunication::PacketResult::Success) + if (m_gdb_comm.GetStopReply(m_last_stop_packet)) { + + // '?' Packets must be handled differently in non-stop mode + if (GetTarget().GetNonStopModeEnabled()) + HandleStopReplySequence(); + if (!m_target.GetArchitecture().IsValid()) { if (m_gdb_comm.GetProcessArchitecture().IsValid()) @@ -1052,8 +1058,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_ return error; } - if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false) == GDBRemoteCommunication::PacketResult::Success) + if (m_gdb_comm.GetStopReply(m_last_stop_packet)) { + + // '?' Packets must be handled differently in non-stop mode + if (GetTarget().GetNonStopModeEnabled()) + HandleStopReplySequence(); + const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture(); if (process_arch.IsValid()) @@ -1153,12 +1164,22 @@ ProcessGDBRemote::ConnectToDebugserver ( error.SetErrorString("not connected to remote gdb server"); return error; } + + // Send $QNonStop:1 packet on startup if required + if (GetTarget().GetNonStopModeEnabled()) + m_gdb_comm.SetNonStopMode(true); + m_gdb_comm.GetThreadSuffixSupported (); m_gdb_comm.GetListThreadsInStopReplySupported (); m_gdb_comm.GetHostInfo (); m_gdb_comm.GetVContSupported ('c'); m_gdb_comm.GetVAttachOrWaitSupported(); - + + // Ask the remote server for the default thread id + if (GetTarget().GetNonStopModeEnabled()) + m_gdb_comm.GetDefaultThreadId(m_initial_tid); + + size_t num_cmds = GetExtraStartupCommands().GetArgumentCount(); for (size_t idx = 0; idx < num_cmds; idx++) { @@ -1430,11 +1451,12 @@ ProcessGDBRemote::DoResume () bool continue_packet_error = false; if (m_gdb_comm.HasAnyVContSupport ()) { - if (m_continue_c_tids.size() == num_threads || + if (!GetTarget().GetNonStopModeEnabled() && + (m_continue_c_tids.size() == num_threads || (m_continue_c_tids.empty() && m_continue_C_tids.empty() && m_continue_s_tids.empty() && - m_continue_S_tids.empty())) + m_continue_S_tids.empty()))) { // All threads are continuing, just send a "c" packet continue_packet.PutCString ("c"); @@ -1662,6 +1684,27 @@ ProcessGDBRemote::DoResume () } void +ProcessGDBRemote::HandleStopReplySequence () +{ + while(true) + { + // Send vStopped + StringExtractorGDBRemote response; + m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); + + // OK represents end of signal list + if (response.IsOKResponse()) + break; + + // If not OK or a normal packet we have a problem + if (!response.IsNormalResponse()) + break; + + SetLastStopPacket(response); + } +} + +void ProcessGDBRemote::ClearThreadIDList () { Mutex::Locker locker(m_thread_list_real.GetMutex()); @@ -2095,6 +2138,13 @@ ProcessGDBRemote::RefreshStateAfterStop UpdateThreadIDList(); } + // If we have queried for a default thread id + if (m_initial_tid != LLDB_INVALID_THREAD_ID) + { + m_thread_list.SetSelectedThreadByID(m_initial_tid); + m_initial_tid = LLDB_INVALID_THREAD_ID; + } + // Let all threads recover from stopping and do any clean up based // on the previous thread state (if any). m_thread_list_real.RefreshStateAfterStop(); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Wed May 13 04:18:18 2015 @@ -358,6 +358,7 @@ protected: bool m_destroy_tried_resuming; lldb::CommandObjectSP m_command_sp; int64_t m_breakpoint_pc_offset; + lldb::tid_t m_initial_tid; // The inital thread ID, given by stub on attach bool StartAsyncThread (); @@ -379,6 +380,9 @@ protected: SetThreadStopInfo (StringExtractor& stop_packet); void + HandleStopReplySequence (); + + void ClearThreadIDList (); bool Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Wed May 13 04:18:18 2015 @@ -2978,6 +2978,7 @@ g_properties[] = { "display-expression-in-crashlogs" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true." }, { "trap-handler-names" , OptionValue::eTypeArray , true, OptionValue::eTypeString, NULL, NULL, "A list of trap handler function names, e.g. a common Unix user process one is _sigtramp." }, { "display-runtime-support-values" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "If true, LLDB will show variables that are meant to support the operation of a language's runtime support." }, + { "non-stop-mode" , OptionValue::eTypeBoolean , false, 0, NULL, NULL, "Disable lock-step debugging, instead control threads independently." }, { NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL } }; @@ -3016,7 +3017,8 @@ enum ePropertyMemoryModuleLoadLevel, ePropertyDisplayExpressionsInCrashlogs, ePropertyTrapHandlerNames, - ePropertyDisplayRuntimeSupportValues + ePropertyDisplayRuntimeSupportValues, + ePropertyNonStopModeEnabled }; @@ -3515,6 +3517,13 @@ TargetProperties::SetDisplayRuntimeSuppo m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); } +bool +TargetProperties::GetNonStopModeEnabled () const +{ + const uint32_t idx = ePropertyNonStopModeEnabled; + return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, false); +} + const ProcessLaunchInfo & TargetProperties::GetProcessLaunchInfo () { Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp (original) +++ lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp Wed May 13 04:18:18 2015 @@ -64,6 +64,10 @@ StringExtractorGDBRemote::GetServerPacke const char *packet_cstr = m_packet.c_str(); switch (m_packet[0]) { + + case '%': + return eServerPacketType_notify; + case '\x03': if (packet_size == 1) return eServerPacketType_interrupt; break; Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.h?rev=237239&r1=237238&r2=237239&view=diff ============================================================================== --- lldb/trunk/source/Utility/StringExtractorGDBRemote.h (original) +++ lldb/trunk/source/Utility/StringExtractorGDBRemote.h Wed May 13 04:18:18 2015 @@ -145,6 +145,7 @@ public: eServerPacketType__M, eServerPacketType__m, + eServerPacketType_notify, // '%' notification }; ServerPacketType _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits