Author: labath Date: Thu Jul 23 04:09:29 2015 New Revision: 242997 URL: http://llvm.org/viewvc/llvm-project?rev=242997&view=rev Log: Add jstopinfo support to llgs
Summary: This adds support for jstopinfo field of stop-reply packets. This field enables us to avoid querying full thread stop data on most stops (see r242593 for more details). Reviewers: ovyalov, clayborg Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D11415 Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=242997&r1=242996&r2=242997&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Jul 23 04:09:29 2015 @@ -1492,7 +1492,7 @@ NativeProcessLinux::MonitorSignal(const if (m_pending_notification_up && m_pending_notification_up->triggering_tid == pid) linux_thread_sp->SetStoppedBySignal(SIGSTOP, info); else - linux_thread_sp->SetStoppedBySignal(0); + linux_thread_sp->SetStoppedWithNoReason(); SetCurrentThreadID (thread_sp->GetID ()); ThreadDidStop (thread_sp->GetID (), true); Modified: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp?rev=242997&r1=242996&r2=242997&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp Thu Jul 23 04:09:29 2015 @@ -362,14 +362,14 @@ NativeThreadLinux::SetStoppedByTrace () } void -NativeThreadLinux::SetSuspended () +NativeThreadLinux::SetStoppedWithNoReason () { - const StateType new_state = StateType::eStateSuspended; + const StateType new_state = StateType::eStateStopped; MaybeLogStateChange (new_state); m_state = new_state; - // FIXME what makes sense here? Do we need a suspended StopReason? m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_info.details.signal.signo = 0; } void Modified: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h?rev=242997&r1=242996&r2=242997&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h Thu Jul 23 04:09:29 2015 @@ -87,10 +87,7 @@ namespace process_linux { SetStoppedByTrace (); void - SetCrashedWithException (const siginfo_t& info); - - void - SetSuspended (); + SetStoppedWithNoReason (); void SetExited (); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=242997&r1=242996&r2=242997&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Thu Jul 23 04:09:29 2015 @@ -537,6 +537,86 @@ GetStopReasonString(StopReason stop_reas return nullptr; } +static JSONArray::SP +GetJSONThreadsInfo(NativeProcessProtocol &process, bool threads_with_valid_stop_info_only) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + + JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + + // Ensure we can get info on the given thread. + uint32_t thread_idx = 0; + for ( NativeThreadProtocolSP thread_sp; + (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; + ++thread_idx) + { + + lldb::tid_t tid = thread_sp->GetID(); + + // Grab the reason this thread stopped. + struct ThreadStopInfo tid_stop_info; + std::string description; + if (!thread_sp->GetStopReason (tid_stop_info, description)) + return nullptr; + + const int signum = tid_stop_info.details.signal.signo; + if (log) + { + log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + __FUNCTION__, + process.GetID (), + tid, + signum, + tid_stop_info.reason, + tid_stop_info.details.exception.type); + } + + if (threads_with_valid_stop_info_only && tid_stop_info.reason == eStopReasonNone) + continue; // No stop reason, skip this thread completely. + + JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); + threads_array_sp->AppendObject(thread_obj_sp); + + thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); + if (signum != 0) + thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(uint64_t(signum))); + + const std::string thread_name = thread_sp->GetName (); + if (! thread_name.empty()) + thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); + + if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) + thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str)); + + if (! description.empty()) + thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description)); + + if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) + { + thread_obj_sp->SetObject("metype", + std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); + + JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); + for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) + { + medata_array_sp->AppendObject(std::make_shared<JSONNumber>( + tid_stop_info.details.exception.data[i])); + } + thread_obj_sp->SetObject("medata", medata_array_sp); + } + + if (threads_with_valid_stop_info_only) + continue; // Only send the abridged stop info. + + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) + thread_obj_sp->SetObject("registers", registers_sp); + + // TODO: Expedite interesting regions of inferior memory + } + + return threads_array_sp; +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid) { @@ -630,6 +710,31 @@ GDBRemoteCommunicationServerLLGS::SendSt response.Printf ("%" PRIx64, listed_thread_sp->GetID ()); } response.PutChar (';'); + + // Include JSON info that describes the stop reason for any threads + // that actually have stop reasons. We use the new "jstopinfo" key + // whose values is hex ascii JSON that contains the thread IDs + // thread stop info only for threads that have stop reasons. Only send + // this if we have more than one thread otherwise this packet has all + // the info it needs. + if (thread_index > 0) + { + const bool threads_with_valid_stop_info_only = true; + JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp, + threads_with_valid_stop_info_only); + if (threads_info_sp) + { + response.PutCString("jstopinfo:"); + StreamString unescaped_response; + threads_info_sp->Write(unescaped_response); + response.PutCStringAsRawHex8(unescaped_response.GetData()); + response.PutChar(';'); + } + else if (log) + log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); + + } } // @@ -2719,74 +2824,20 @@ GDBRemoteCommunicationServerLLGS::Handle log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); - JSONArray threads_array; - // Ensure we can get info on the given thread. - uint32_t thread_idx = 0; - for ( NativeThreadProtocolSP thread_sp; - (thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_idx)) != nullptr; - ++thread_idx) + StreamString response; + const bool threads_with_valid_stop_info_only = false; + JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp, + threads_with_valid_stop_info_only); + if (! threads_array_sp) { - - JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); - - lldb::tid_t tid = thread_sp->GetID(); - - // Grab the reason this thread stopped. - struct ThreadStopInfo tid_stop_info; - std::string description; - if (!thread_sp->GetStopReason (tid_stop_info, description)) - return SendErrorResponse (52); - - const int signum = tid_stop_info.details.signal.signo; if (log) - { - log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, - __FUNCTION__, - m_debugged_process_sp->GetID (), - tid, - signum, - tid_stop_info.reason, - tid_stop_info.details.exception.type); - } - - thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); - if (signum != LLDB_INVALID_SIGNAL_NUMBER) - thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(uint64_t(signum))); - - const std::string thread_name = thread_sp->GetName (); - if (! thread_name.empty()) - thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); - - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) - thread_obj_sp->SetObject("registers", registers_sp); - - if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) - thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str)); - - if (! description.empty()) - thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description)); - - if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) - { - thread_obj_sp->SetObject("metype", - std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); - - JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); - for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) - { - medata_array_sp->AppendObject(std::make_shared<JSONNumber>( - tid_stop_info.details.exception.data[i])); - } - thread_obj_sp->SetObject("medata", medata_array_sp); - } - - threads_array.AppendObject(thread_obj_sp); + log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64, + __FUNCTION__, m_debugged_process_sp->GetID()); + return SendErrorResponse(52); } - // TODO: Expedite interesting regions of inferior memory - StreamString response; - threads_array.Write(response); + threads_array_sp->Write(response); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize()); _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits