diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 1897 |
1 files changed, 0 insertions, 1897 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp deleted file mode 100644 index a31f48af1f73..000000000000 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ /dev/null @@ -1,1897 +0,0 @@ -//===-- GDBRemoteCommunicationClient.cpp ------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#include "GDBRemoteCommunicationClient.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "llvm/ADT/Triple.h" -#include "lldb/Interpreter/Args.h" -#include "lldb/Core/ConnectionFileDescriptor.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/Endian.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/TimeValue.h" - -// Project includes -#include "Utility/StringExtractorGDBRemote.h" -#include "ProcessGDBRemote.h" -#include "ProcessGDBRemoteLog.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// GDBRemoteCommunicationClient constructor -//---------------------------------------------------------------------- -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), - m_supports_vCont_C (eLazyBoolCalculate), - m_supports_vCont_s (eLazyBoolCalculate), - m_supports_vCont_S (eLazyBoolCalculate), - m_qHostInfo_is_valid (eLazyBoolCalculate), - m_supports_alloc_dealloc_memory (eLazyBoolCalculate), - m_supports_memory_region_info (eLazyBoolCalculate), - m_supports_qProcessInfoPID (true), - m_supports_qfProcessInfo (true), - m_supports_qUserName (true), - m_supports_qGroupName (true), - m_supports_qThreadStopInfo (true), - m_supports_z0 (true), - m_supports_z1 (true), - m_supports_z2 (true), - m_supports_z3 (true), - m_supports_z4 (true), - m_curr_tid (LLDB_INVALID_THREAD_ID), - m_curr_tid_run (LLDB_INVALID_THREAD_ID), - m_async_mutex (Mutex::eMutexTypeRecursive), - m_async_packet_predicate (false), - m_async_packet (), - m_async_response (), - m_async_signal (-1), - m_host_arch(), - m_os_version_major (UINT32_MAX), - m_os_version_minor (UINT32_MAX), - m_os_version_update (UINT32_MAX) -{ -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() -{ - if (IsConnected()) - Disconnect(); -} - -bool -GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) -{ - // Start the read thread after we send the handshake ack since if we - // fail to send the handshake ack, there is no reason to continue... - if (SendAck()) - return true; - - if (error_ptr) - error_ptr->SetErrorString("failed to send the handshake ack"); - return false; -} - -void -GDBRemoteCommunicationClient::QueryNoAckModeSupported () -{ - if (m_supports_not_sending_acks == eLazyBoolCalculate) - { - m_send_acks = true; - m_supports_not_sending_acks = eLazyBoolNo; - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false)) - { - if (response.IsOKResponse()) - { - m_send_acks = false; - m_supports_not_sending_acks = eLazyBoolYes; - } - } - } -} - -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; - m_supports_vCont_S = eLazyBoolCalculate; - m_qHostInfo_is_valid = eLazyBoolCalculate; - m_supports_alloc_dealloc_memory = eLazyBoolCalculate; - m_supports_memory_region_info = eLazyBoolCalculate; - - m_supports_qProcessInfoPID = true; - m_supports_qfProcessInfo = true; - m_supports_qUserName = true; - m_supports_qGroupName = true; - m_supports_qThreadStopInfo = true; - m_supports_z0 = true; - m_supports_z1 = true; - m_supports_z2 = true; - m_supports_z3 = true; - m_supports_z4 = true; - m_host_arch.Clear(); -} - - -bool -GDBRemoteCommunicationClient::GetThreadSuffixSupported () -{ - if (m_supports_thread_suffix == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_thread_suffix = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false)) - { - if (response.IsOKResponse()) - m_supports_thread_suffix = eLazyBoolYes; - } - } - return m_supports_thread_suffix; -} -bool -GDBRemoteCommunicationClient::GetVContSupported (char flavor) -{ - if (m_supports_vCont_c == eLazyBoolCalculate) - { - StringExtractorGDBRemote response; - m_supports_vCont_any = eLazyBoolNo; - m_supports_vCont_all = eLazyBoolNo; - m_supports_vCont_c = eLazyBoolNo; - m_supports_vCont_C = eLazyBoolNo; - m_supports_vCont_s = eLazyBoolNo; - m_supports_vCont_S = eLazyBoolNo; - if (SendPacketAndWaitForResponse("vCont?", response, false)) - { - const char *response_cstr = response.GetStringRef().c_str(); - if (::strstr (response_cstr, ";c")) - m_supports_vCont_c = eLazyBoolYes; - - if (::strstr (response_cstr, ";C")) - m_supports_vCont_C = eLazyBoolYes; - - if (::strstr (response_cstr, ";s")) - m_supports_vCont_s = eLazyBoolYes; - - if (::strstr (response_cstr, ";S")) - m_supports_vCont_S = eLazyBoolYes; - - if (m_supports_vCont_c == eLazyBoolYes && - m_supports_vCont_C == eLazyBoolYes && - m_supports_vCont_s == eLazyBoolYes && - m_supports_vCont_S == eLazyBoolYes) - { - m_supports_vCont_all = eLazyBoolYes; - } - - if (m_supports_vCont_c == eLazyBoolYes || - m_supports_vCont_C == eLazyBoolYes || - m_supports_vCont_s == eLazyBoolYes || - m_supports_vCont_S == eLazyBoolYes) - { - m_supports_vCont_any = eLazyBoolYes; - } - } - } - - switch (flavor) - { - case 'a': return m_supports_vCont_any; - case 'A': return m_supports_vCont_all; - case 'c': return m_supports_vCont_c; - case 'C': return m_supports_vCont_C; - case 's': return m_supports_vCont_s; - case 'S': return m_supports_vCont_S; - default: break; - } - return false; -} - - -size_t -GDBRemoteCommunicationClient::SendPacketAndWaitForResponse -( - const char *payload, - StringExtractorGDBRemote &response, - bool send_async -) -{ - return SendPacketAndWaitForResponse (payload, - ::strlen (payload), - response, - send_async); -} - -size_t -GDBRemoteCommunicationClient::SendPacketAndWaitForResponse -( - const char *payload, - size_t payload_length, - StringExtractorGDBRemote &response, - bool send_async -) -{ - Mutex::Locker locker; - LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - size_t response_len = 0; - if (GetSequenceMutex (locker)) - { - if (SendPacketNoLock (payload, payload_length)) - response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()); - else - { - if (log) - log->Printf("error: failed to send '%*s'", (int) payload_length, payload); - } - } - else - { - if (send_async) - { - Mutex::Locker async_locker (m_async_mutex); - m_async_packet.assign(payload, payload_length); - m_async_packet_predicate.SetValue (true, eBroadcastNever); - - if (log) - log->Printf ("async: async packet = %s", m_async_packet.c_str()); - - bool timed_out = false; - if (SendInterrupt(locker, 2, timed_out)) - { - if (m_interrupt_sent) - { - TimeValue timeout_time; - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds (m_packet_timeout); - - if (log) - log->Printf ("async: sent interrupt"); - - if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out)) - { - if (log) - log->Printf ("async: got response"); - - // Swap the response buffer to avoid malloc and string copy - response.GetStringRef().swap (m_async_response.GetStringRef()); - response_len = response.GetStringRef().size(); - } - else - { - if (log) - log->Printf ("async: timed out waiting for response"); - } - - // Make sure we wait until the continue packet has been sent again... - if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out)) - { - if (log) - { - if (timed_out) - log->Printf ("async: timed out waiting for process to resume, but process was resumed"); - else - log->Printf ("async: async packet sent"); - } - } - else - { - if (log) - log->Printf ("async: timed out waiting for process to resume"); - } - } - else - { - // We had a racy condition where we went to send the interrupt - // yet we were able to get the lock, so the process must have - // just stopped? - if (log) - log->Printf ("async: got lock without sending interrupt"); - // Send the packet normally since we got the lock - if (SendPacketNoLock (payload, payload_length)) - response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()); - else - { - if (log) - log->Printf("error: failed to send '%*s'", (int) payload_length, payload); - } - } - } - else - { - if (log) - log->Printf ("async: failed to interrupt"); - } - } - else - { - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload); - } - } - if (response_len == 0) - { - if (log) - log->Printf("error: failed to get response for '%*s'", (int) payload_length, payload); - } - return response_len; -} - -StateType -GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse -( - ProcessGDBRemote *process, - const char *payload, - size_t packet_length, - StringExtractorGDBRemote &response -) -{ - LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__); - - Mutex::Locker locker(m_sequence_mutex); - StateType state = eStateRunning; - - BroadcastEvent(eBroadcastBitRunPacketSent, NULL); - m_public_is_running.SetValue (true, eBroadcastNever); - // Set the starting continue packet into "continue_packet". This packet - // make change if we are interrupted and we continue after an async packet... - std::string continue_packet(payload, packet_length); - - bool got_stdout = false; - - while (state == eStateRunning) - { - if (!got_stdout) - { - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str()); - if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) == 0) - state = eStateInvalid; - - m_private_is_running.SetValue (true, eBroadcastAlways); - } - - got_stdout = false; - - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str()); - - if (WaitForPacketWithTimeoutMicroSecondsNoLock(response, UINT32_MAX)) - { - if (response.Empty()) - state = eStateInvalid; - else - { - const char stop_type = response.GetChar(); - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str()); - switch (stop_type) - { - case 'T': - case 'S': - { - if (process->GetStopID() == 0) - { - if (process->GetID() == LLDB_INVALID_PROCESS_ID) - { - lldb::pid_t pid = GetCurrentProcessID (); - if (pid != LLDB_INVALID_PROCESS_ID) - process->SetID (pid); - } - process->BuildDynamicRegisterInfo (true); - } - - // Privately notify any internal threads that we have stopped - // in case we wanted to interrupt our process, yet we might - // send a packet and continue without returning control to the - // user. - m_private_is_running.SetValue (false, eBroadcastAlways); - - const uint8_t signo = response.GetHexU8 (UINT8_MAX); - - bool continue_after_aync = false; - if (m_async_signal != -1 || m_async_packet_predicate.GetValue()) - { - continue_after_aync = true; - // We sent an interrupt packet to stop the inferior process - // for an async signal or to send an async packet while running - // but we might have been single stepping and received the - // stop packet for the step instead of for the interrupt packet. - // Typically when an interrupt is sent a SIGINT or SIGSTOP - // is used, so if we get anything else, we need to try and - // get another stop reply packet that may have been sent - // due to sending the interrupt when the target is stopped - // which will just re-send a copy of the last stop reply - // packet. If we don't do this, then the reply for our - // async packet will be the repeat stop reply packet and cause - // a lot of trouble for us! - if (signo != SIGINT && signo != SIGSTOP) - { - continue_after_aync = false; - - // We didn't get a a SIGINT or SIGSTOP, so try for a - // very brief time (1 ms) to get another stop reply - // packet to make sure it doesn't get in the way - StringExtractorGDBRemote extra_stop_reply_packet; - uint32_t timeout_usec = 1000; - if (WaitForPacketWithTimeoutMicroSecondsNoLock (extra_stop_reply_packet, timeout_usec)) - { - switch (extra_stop_reply_packet.GetChar()) - { - case 'T': - case 'S': - // We did get an extra stop reply, which means - // our interrupt didn't stop the target so we - // shouldn't continue after the async signal - // or packet is sent... - continue_after_aync = false; - break; - } - } - } - } - - if (m_async_signal != -1) - { - if (log) - log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal)); - - // Save off the async signal we are supposed to send - const int async_signal = m_async_signal; - // Clear the async signal member so we don't end up - // sending the signal multiple times... - m_async_signal = -1; - // Check which signal we stopped with - if (signo == async_signal) - { - if (log) - log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo)); - - // We already stopped with a signal that we wanted - // to stop with, so we are done - } - else - { - // We stopped with a different signal that the one - // we wanted to stop with, so now we must resume - // with the signal we want - char signal_packet[32]; - int signal_packet_len = 0; - signal_packet_len = ::snprintf (signal_packet, - sizeof (signal_packet), - "C%2.2x", - async_signal); - - if (log) - log->Printf ("async: stopped with signal %s, resume with %s", - Host::GetSignalAsCString (signo), - Host::GetSignalAsCString (async_signal)); - - // Set the continue packet to resume even if the - // interrupt didn't cause our stop (ignore continue_after_aync) - continue_packet.assign(signal_packet, signal_packet_len); - continue; - } - } - else if (m_async_packet_predicate.GetValue()) - { - LogSP packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); - - // We are supposed to send an asynchronous packet while - // we are running. - m_async_response.Clear(); - if (m_async_packet.empty()) - { - if (packet_log) - packet_log->Printf ("async: error: empty async packet"); - - } - else - { - if (packet_log) - packet_log->Printf ("async: sending packet"); - - SendPacketAndWaitForResponse (&m_async_packet[0], - m_async_packet.size(), - m_async_response, - false); - } - // Let the other thread that was trying to send the async - // packet know that the packet has been sent and response is - // ready... - m_async_packet_predicate.SetValue(false, eBroadcastAlways); - - if (packet_log) - packet_log->Printf ("async: sent packet, continue_after_aync = %i", continue_after_aync); - - // Set the continue packet to resume if our interrupt - // for the async packet did cause the stop - if (continue_after_aync) - { - continue_packet.assign (1, 'c'); - continue; - } - } - // Stop with signal and thread info - state = eStateStopped; - } - break; - - case 'W': - case 'X': - // process exited - state = eStateExited; - break; - - case 'O': - // STDOUT - { - got_stdout = true; - std::string inferior_stdout; - inferior_stdout.reserve(response.GetBytesLeft () / 2); - char ch; - while ((ch = response.GetHexU8()) != '\0') - inferior_stdout.append(1, ch); - process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size()); - } - break; - - case 'E': - // ERROR - state = eStateInvalid; - break; - - default: - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__); - state = eStateInvalid; - break; - } - } - } - else - { - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__); - state = eStateInvalid; - } - } - if (log) - log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state)); - response.SetFilePos(0); - m_private_is_running.SetValue (false, eBroadcastAlways); - m_public_is_running.SetValue (false, eBroadcastAlways); - return state; -} - -bool -GDBRemoteCommunicationClient::SendAsyncSignal (int signo) -{ - Mutex::Locker async_locker (m_async_mutex); - m_async_signal = signo; - bool timed_out = false; - Mutex::Locker locker; - if (SendInterrupt (locker, 1, timed_out)) - return true; - m_async_signal = -1; - return false; -} - -// This function takes a mutex locker as a parameter in case the GetSequenceMutex -// actually succeeds. If it doesn't succeed in acquiring the sequence mutex -// (the expected result), then it will send the halt packet. If it does succeed -// then the caller that requested the interrupt will want to keep the sequence -// locked down so that no one else can send packets while the caller has control. -// This function usually gets called when we are running and need to stop the -// target. It can also be used when we are running and and we need to do something -// else (like read/write memory), so we need to interrupt the running process -// (gdb remote protocol requires this), and do what we need to do, then resume. - -bool -GDBRemoteCommunicationClient::SendInterrupt -( - Mutex::Locker& locker, - uint32_t seconds_to_wait_for_stop, - bool &timed_out -) -{ - m_interrupt_sent = false; - timed_out = false; - LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - - if (IsRunning()) - { - // Only send an interrupt if our debugserver is running... - if (GetSequenceMutex (locker)) - { - if (log) - log->Printf ("SendInterrupt () - got sequence mutex without having to interrupt"); - } - else - { - // Someone has the mutex locked waiting for a response or for the - // inferior to stop, so send the interrupt on the down low... - char ctrl_c = '\x03'; - ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = Write (&ctrl_c, 1, status, NULL); - if (log) - log->PutCString("send packet: \\x03"); - if (bytes_written > 0) - { - m_interrupt_sent = true; - if (seconds_to_wait_for_stop) - { - TimeValue timeout; - if (seconds_to_wait_for_stop) - { - timeout = TimeValue::Now(); - timeout.OffsetWithSeconds (seconds_to_wait_for_stop); - } - if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out)) - { - if (log) - log->PutCString ("SendInterrupt () - sent interrupt, private state stopped"); - return true; - } - else - { - if (log) - log->Printf ("SendInterrupt () - sent interrupt, timed out wating for async thread resume"); - } - } - else - { - if (log) - log->Printf ("SendInterrupt () - sent interrupt, not waiting for stop..."); - return true; - } - } - else - { - if (log) - log->Printf ("SendInterrupt () - failed to write interrupt"); - } - return false; - } - } - else - { - if (log) - log->Printf ("SendInterrupt () - not running"); - } - return true; -} - -lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID () -{ - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false)) - { - if (response.GetChar() == 'Q') - if (response.GetChar() == 'C') - return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID); - } - return LLDB_INVALID_PROCESS_ID; -} - -bool -GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str) -{ - error_str.clear(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false)) - { - if (response.IsOKResponse()) - return true; - if (response.GetChar() == 'E') - { - // A string the describes what failed when launching... - error_str = response.GetStringRef().substr(1); - } - else - { - error_str.assign ("unknown error occurred launching process"); - } - } - else - { - error_str.assign ("failed to send the qLaunchSuccess packet"); - } - return false; -} - -int -GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[]) -{ - if (argv && argv[0]) - { - StreamString packet; - packet.PutChar('A'); - const char *arg; - for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i) - { - const int arg_len = strlen(arg); - if (i > 0) - packet.PutChar(','); - packet.Printf("%i,%i,", arg_len * 2, i); - packet.PutBytesAsRawHex8 (arg, arg_len); - } - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value) -{ - if (name_equal_value && name_equal_value[0]) - { - StreamString packet; - packet.Printf("QEnvironment:%s", name_equal_value); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch) -{ - if (arch && arch[0]) - { - StreamString packet; - packet.Printf("QLaunchArch:%s", arch); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -bool -GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major, - uint32_t &minor, - uint32_t &update) -{ - if (GetHostInfo ()) - { - if (m_os_version_major != UINT32_MAX) - { - major = m_os_version_major; - minor = m_os_version_minor; - update = m_os_version_update; - return true; - } - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetOSBuildString (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_os_build.empty()) - { - s = m_os_build; - return true; - } - } - s.clear(); - return false; -} - - -bool -GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_os_kernel.empty()) - { - s = m_os_kernel; - return true; - } - } - s.clear(); - return false; -} - -bool -GDBRemoteCommunicationClient::GetHostname (std::string &s) -{ - if (GetHostInfo ()) - { - if (!m_hostname.empty()) - { - s = m_hostname; - return true; - } - } - s.clear(); - return false; -} - -ArchSpec -GDBRemoteCommunicationClient::GetSystemArchitecture () -{ - if (GetHostInfo ()) - return m_host_arch; - return ArchSpec(); -} - - -bool -GDBRemoteCommunicationClient::GetHostInfo (bool force) -{ - if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) - { - m_qHostInfo_is_valid = eLazyBoolNo; - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse ("qHostInfo", response, false)) - { - if (response.IsNormalResponse()) - { - std::string name; - std::string value; - uint32_t cpu = LLDB_INVALID_CPUTYPE; - uint32_t sub = 0; - std::string arch_name; - std::string os_name; - std::string vendor_name; - std::string triple; - uint32_t pointer_byte_size = 0; - StringExtractor extractor; - ByteOrder byte_order = eByteOrderInvalid; - uint32_t num_keys_decoded = 0; - while (response.GetNameColonValue(name, value)) - { - if (name.compare("cputype") == 0) - { - // exception type in big endian hex - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); - if (cpu != LLDB_INVALID_CPUTYPE) - ++num_keys_decoded; - } - else if (name.compare("cpusubtype") == 0) - { - // exception count in big endian hex - sub = Args::StringToUInt32 (value.c_str(), 0, 0); - if (sub != 0) - ++num_keys_decoded; - } - else if (name.compare("arch") == 0) - { - arch_name.swap (value); - ++num_keys_decoded; - } - else if (name.compare("triple") == 0) - { - // The triple comes as ASCII hex bytes since it contains '-' chars - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (triple); - ++num_keys_decoded; - } - else if (name.compare("os_build") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_os_build); - ++num_keys_decoded; - } - else if (name.compare("hostname") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_hostname); - ++num_keys_decoded; - } - else if (name.compare("os_kernel") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_os_kernel); - ++num_keys_decoded; - } - else if (name.compare("ostype") == 0) - { - os_name.swap (value); - ++num_keys_decoded; - } - else if (name.compare("vendor") == 0) - { - vendor_name.swap(value); - ++num_keys_decoded; - } - else if (name.compare("endian") == 0) - { - ++num_keys_decoded; - if (value.compare("little") == 0) - byte_order = eByteOrderLittle; - else if (value.compare("big") == 0) - byte_order = eByteOrderBig; - else if (value.compare("pdp") == 0) - byte_order = eByteOrderPDP; - else - --num_keys_decoded; - } - else if (name.compare("ptrsize") == 0) - { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); - if (pointer_byte_size != 0) - ++num_keys_decoded; - } - else if (name.compare("os_version") == 0) - { - Args::StringToVersion (value.c_str(), - m_os_version_major, - m_os_version_minor, - m_os_version_update); - if (m_os_version_major != UINT32_MAX) - ++num_keys_decoded; - } - } - - if (num_keys_decoded > 0) - m_qHostInfo_is_valid = eLazyBoolYes; - - if (triple.empty()) - { - if (arch_name.empty()) - { - if (cpu != LLDB_INVALID_CPUTYPE) - { - m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - if (!vendor_name.empty()) - m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); - if (!os_name.empty()) - m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); - - } - } - else - { - std::string triple; - triple += arch_name; - triple += '-'; - if (vendor_name.empty()) - triple += "unknown"; - else - triple += vendor_name; - triple += '-'; - if (os_name.empty()) - triple += "unknown"; - else - triple += os_name; - m_host_arch.SetTriple (triple.c_str(), NULL); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - - } - } - else - { - m_host_arch.SetTriple (triple.c_str(), NULL); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - } - } - } - } - return m_qHostInfo_is_valid == eLazyBoolYes; -} - -int -GDBRemoteCommunicationClient::SendAttach -( - lldb::pid_t pid, - StringExtractorGDBRemote& response -) -{ - if (pid != LLDB_INVALID_PROCESS_ID) - { - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%llx", pid); - assert (packet_len < sizeof(packet)); - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (response.IsErrorResponse()) - return response.GetError(); - return 0; - } - } - return -1; -} - -const lldb_private::ArchSpec & -GDBRemoteCommunicationClient::GetHostArchitecture () -{ - if (m_qHostInfo_is_valid == eLazyBoolCalculate) - GetHostInfo (); - return m_host_arch; -} - -addr_t -GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions) -{ - if (m_supports_alloc_dealloc_memory != eLazyBoolNo) - { - m_supports_alloc_dealloc_memory = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size, - permissions & lldb::ePermissionsReadable ? "r" : "", - permissions & lldb::ePermissionsWritable ? "w" : "", - permissions & lldb::ePermissionsExecutable ? "x" : ""); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (!response.IsErrorResponse()) - return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - } - else - { - m_supports_alloc_dealloc_memory = eLazyBoolNo; - } - } - return LLDB_INVALID_ADDRESS; -} - -bool -GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr) -{ - if (m_supports_alloc_dealloc_memory != eLazyBoolNo) - { - m_supports_alloc_dealloc_memory = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (response.IsOKResponse()) - return true; - } - else - { - m_supports_alloc_dealloc_memory = eLazyBoolNo; - } - } - return false; -} - -bool -GDBRemoteCommunicationClient::Detach () -{ - return SendPacket ("D", 1) > 0; -} - -Error -GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, - lldb_private::MemoryRegionInfo ®ion_info) -{ - Error error; - region_info.Clear(); - - if (m_supports_memory_region_info != eLazyBoolNo) - { - m_supports_memory_region_info = eLazyBoolYes; - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%llx", (uint64_t)addr); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - std::string name; - std::string value; - addr_t addr_value; - bool success = true; - bool saw_permissions = false; - while (success && response.GetNameColonValue(name, value)) - { - if (name.compare ("start") == 0) - { - addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); - if (success) - region_info.GetRange().SetRangeBase(addr_value); - } - else if (name.compare ("size") == 0) - { - addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success); - if (success) - region_info.GetRange().SetByteSize (addr_value); - } - else if (name.compare ("permissions") == 0 && region_info.GetRange().IsValid()) - { - saw_permissions = true; - if (region_info.GetRange().Contains (addr)) - { - if (value.find('r') != std::string::npos) - region_info.SetReadable (MemoryRegionInfo::eYes); - else - region_info.SetReadable (MemoryRegionInfo::eNo); - - if (value.find('w') != std::string::npos) - region_info.SetWritable (MemoryRegionInfo::eYes); - else - region_info.SetWritable (MemoryRegionInfo::eNo); - - if (value.find('x') != std::string::npos) - region_info.SetExecutable (MemoryRegionInfo::eYes); - else - region_info.SetExecutable (MemoryRegionInfo::eNo); - } - else - { - // The reported region does not contain this address -- we're looking at an unmapped page - region_info.SetReadable (MemoryRegionInfo::eNo); - region_info.SetWritable (MemoryRegionInfo::eNo); - region_info.SetExecutable (MemoryRegionInfo::eNo); - } - } - else if (name.compare ("error") == 0) - { - StringExtractorGDBRemote name_extractor; - // Swap "value" over into "name_extractor" - name_extractor.GetStringRef().swap(value); - // Now convert the HEX bytes into a string value - name_extractor.GetHexByteString (value); - error.SetErrorString(value.c_str()); - } - } - - // We got a valid address range back but no permissions -- which means this is an unmapped page - if (region_info.GetRange().IsValid() && saw_permissions == false) - { - region_info.SetReadable (MemoryRegionInfo::eNo); - region_info.SetWritable (MemoryRegionInfo::eNo); - region_info.SetExecutable (MemoryRegionInfo::eNo); - } - } - else - { - m_supports_memory_region_info = eLazyBoolNo; - } - } - - if (m_supports_memory_region_info == eLazyBoolNo) - { - error.SetErrorString("qMemoryRegionInfo is not supported"); - } - if (error.Fail()) - region_info.Clear(); - return error; - -} - - -int -GDBRemoteCommunicationClient::SetSTDIN (char const *path) -{ - if (path && path[0]) - { - StreamString packet; - packet.PutCString("QSetSTDIN:"); - packet.PutBytesAsRawHex8(path, strlen(path)); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetSTDOUT (char const *path) -{ - if (path && path[0]) - { - StreamString packet; - packet.PutCString("QSetSTDOUT:"); - packet.PutBytesAsRawHex8(path, strlen(path)); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetSTDERR (char const *path) -{ - if (path && path[0]) - { - StreamString packet; - packet.PutCString("QSetSTDERR:"); - packet.PutBytesAsRawHex8(path, strlen(path)); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetWorkingDir (char const *path) -{ - if (path && path[0]) - { - StreamString packet; - packet.PutCString("QSetWorkingDir:"); - packet.PutBytesAsRawHex8(path, strlen(path)); - - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - } - return -1; -} - -int -GDBRemoteCommunicationClient::SetDisableASLR (bool enable) -{ - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } - return -1; -} - -bool -GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) -{ - if (response.IsNormalResponse()) - { - std::string name; - std::string value; - StringExtractor extractor; - - while (response.GetNameColonValue(name, value)) - { - if (name.compare("pid") == 0) - { - process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); - } - else if (name.compare("ppid") == 0) - { - process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); - } - else if (name.compare("uid") == 0) - { - process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); - } - else if (name.compare("euid") == 0) - { - process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); - } - else if (name.compare("gid") == 0) - { - process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); - } - else if (name.compare("egid") == 0) - { - process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); - } - else if (name.compare("triple") == 0) - { - // The triple comes as ASCII hex bytes since it contains '-' chars - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (value); - process_info.GetArchitecture ().SetTriple (value.c_str(), NULL); - } - else if (name.compare("name") == 0) - { - StringExtractor extractor; - // The the process name from ASCII hex bytes since we can't - // control the characters in a process name - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (value); - process_info.GetExecutableFile().SetFile (value.c_str(), false); - } - } - - if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) - return true; - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) -{ - process_info.Clear(); - - if (m_supports_qProcessInfoPID) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%llu", pid); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - return DecodeProcessInfoResponse (response, process_info); - } - else - { - m_supports_qProcessInfoPID = false; - return false; - } - } - return false; -} - -uint32_t -GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) -{ - process_infos.Clear(); - - if (m_supports_qfProcessInfo) - { - StreamString packet; - packet.PutCString ("qfProcessInfo"); - if (!match_info.MatchAllProcesses()) - { - packet.PutChar (':'); - const char *name = match_info.GetProcessInfo().GetName(); - bool has_name_match = false; - if (name && name[0]) - { - has_name_match = true; - NameMatchType name_match_type = match_info.GetNameMatchType(); - switch (name_match_type) - { - case eNameMatchIgnore: - has_name_match = false; - break; - - case eNameMatchEquals: - packet.PutCString ("name_match:equals;"); - break; - - case eNameMatchContains: - packet.PutCString ("name_match:contains;"); - break; - - case eNameMatchStartsWith: - packet.PutCString ("name_match:starts_with;"); - break; - - case eNameMatchEndsWith: - packet.PutCString ("name_match:ends_with;"); - break; - - case eNameMatchRegularExpression: - packet.PutCString ("name_match:regex;"); - break; - } - if (has_name_match) - { - packet.PutCString ("name:"); - packet.PutBytesAsRawHex8(name, ::strlen(name)); - packet.PutChar (';'); - } - } - - if (match_info.GetProcessInfo().ProcessIDIsValid()) - packet.Printf("pid:%llu;",match_info.GetProcessInfo().GetProcessID()); - if (match_info.GetProcessInfo().ParentProcessIDIsValid()) - packet.Printf("parent_pid:%llu;",match_info.GetProcessInfo().GetParentProcessID()); - if (match_info.GetProcessInfo().UserIDIsValid()) - packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID()); - if (match_info.GetProcessInfo().GroupIDIsValid()) - packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID()); - if (match_info.GetProcessInfo().EffectiveUserIDIsValid()) - packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0); - if (match_info.GetProcessInfo().GetArchitecture().IsValid()) - { - const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); - const llvm::Triple &triple = match_arch.GetTriple(); - packet.PutCString("triple:"); - packet.PutCStringAsRawHex8(triple.getTriple().c_str()); - packet.PutChar (';'); - } - } - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) - { - do - { - ProcessInstanceInfo process_info; - if (!DecodeProcessInfoResponse (response, process_info)) - break; - process_infos.Append(process_info); - response.GetStringRef().clear(); - response.SetFilePos(0); - } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false)); - } - else - { - m_supports_qfProcessInfo = false; - return 0; - } - } - return process_infos.GetSize(); - -} - -bool -GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name) -{ - if (m_supports_qUserName) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (response.IsNormalResponse()) - { - // Make sure we parsed the right number of characters. The response is - // the hex encoded user name and should make up the entire packet. - // If there are any non-hex ASCII bytes, the length won't match below.. - if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) - return true; - } - } - else - { - m_supports_qUserName = false; - return false; - } - } - return false; - -} - -bool -GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name) -{ - if (m_supports_qGroupName) - { - char packet[32]; - const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) - { - if (response.IsNormalResponse()) - { - // Make sure we parsed the right number of characters. The response is - // the hex encoded group name and should make up the entire packet. - // If there are any non-hex ASCII bytes, the length won't match below.. - if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) - return true; - } - } - else - { - m_supports_qGroupName = false; - return false; - } - } - return false; -} - -void -GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets) -{ - uint32_t i; - TimeValue start_time, end_time; - uint64_t total_time_nsec; - float packets_per_second; - if (SendSpeedTestPacket (0, 0)) - { - for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2) - { - for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2) - { - start_time = TimeValue::Now(); - for (i=0; i<num_packets; ++i) - { - SendSpeedTestPacket (send_size, recv_size); - } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %llu.%9.9llu sec for %f packets/sec.\n", - num_packets, - send_size, - recv_size, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second); - if (recv_size == 0) - recv_size = 32; - } - if (send_size == 0) - send_size = 32; - } - } - else - { - start_time = TimeValue::Now(); - for (i=0; i<num_packets; ++i) - { - GetCurrentProcessID (); - } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - printf ("%u 'qC' packets packets in 0x%llu%9.9llu sec for %f packets/sec.\n", - num_packets, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second); - } -} - -bool -GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size) -{ - StreamString packet; - packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); - uint32_t bytes_left = send_size; - while (bytes_left > 0) - { - if (bytes_left >= 26) - { - packet.PutCString("abcdefghijklmnopqrstuvwxyz"); - bytes_left -= 26; - } - else - { - packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); - bytes_left = 0; - } - } - - StringExtractorGDBRemote response; - return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) > 0; - return false; -} - -uint16_t -GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort () -{ - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false)) - { - std::string name; - std::string value; - uint16_t port = 0; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - while (response.GetNameColonValue(name, value)) - { - if (name.size() == 4 && name.compare("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); - if (name.size() == 3 && name.compare("pid") == 0) - pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); - } - return port; - } - return 0; -} - -bool -GDBRemoteCommunicationClient::SetCurrentThread (int tid) -{ - if (m_curr_tid == tid) - return true; - - char packet[32]; - int packet_len; - if (tid <= 0) - packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid); - else - packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid); - assert (packet_len + 1 < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false)) - { - if (response.IsOKResponse()) - { - m_curr_tid = tid; - return true; - } - } - return false; -} - -bool -GDBRemoteCommunicationClient::SetCurrentThreadForRun (int tid) -{ - if (m_curr_tid_run == tid) - return true; - - char packet[32]; - int packet_len; - if (tid <= 0) - packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid); - else - packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid); - - assert (packet_len + 1 < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, false)) - { - if (response.IsOKResponse()) - { - m_curr_tid_run = tid; - return true; - } - } - return false; -} - -bool -GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response) -{ - if (SendPacketAndWaitForResponse("?", 1, response, false)) - return response.IsNormalResponse(); - return false; -} - -bool -GDBRemoteCommunicationClient::GetThreadStopInfo (uint32_t tid, StringExtractorGDBRemote &response) -{ - if (m_supports_qThreadStopInfo) - { - char packet[256]; - int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", tid); - assert (packet_len < sizeof(packet)); - if (SendPacketAndWaitForResponse(packet, packet_len, response, false)) - { - if (response.IsNormalResponse()) - return true; - else - return false; - } - else - { - m_supports_qThreadStopInfo = false; - } - } -// if (SetCurrentThread (tid)) -// return GetStopReply (response); - return false; -} - - -uint8_t -GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length) -{ - switch (type) - { - case eBreakpointSoftware: if (!m_supports_z0) return UINT8_MAX; break; - case eBreakpointHardware: if (!m_supports_z1) return UINT8_MAX; break; - case eWatchpointWrite: if (!m_supports_z2) return UINT8_MAX; break; - case eWatchpointRead: if (!m_supports_z3) return UINT8_MAX; break; - case eWatchpointReadWrite: if (!m_supports_z4) return UINT8_MAX; break; - default: return UINT8_MAX; - } - - char packet[64]; - const int packet_len = ::snprintf (packet, - sizeof(packet), - "%c%i,%llx,%x", - insert ? 'Z' : 'z', - type, - addr, - length); - - assert (packet_len + 1 < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, packet_len, response, true)) - { - if (response.IsOKResponse()) - return 0; - else if (response.IsErrorResponse()) - return response.GetError(); - } - else - { - switch (type) - { - case eBreakpointSoftware: m_supports_z0 = false; break; - case eBreakpointHardware: m_supports_z1 = false; break; - case eWatchpointWrite: m_supports_z2 = false; break; - case eWatchpointRead: m_supports_z3 = false; break; - case eWatchpointReadWrite: m_supports_z4 = false; break; - default: break; - } - } - - return UINT8_MAX; -} - -size_t -GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids, - bool &sequence_mutex_unavailable) -{ - Mutex::Locker locker; - thread_ids.clear(); - - if (GetSequenceMutex (locker)) - { - sequence_mutex_unavailable = false; - StringExtractorGDBRemote response; - - for (SendPacketNoLock ("qfThreadInfo", strlen("qfThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()); - response.IsNormalResponse(); - SendPacketNoLock ("qsThreadInfo", strlen("qsThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ())) - { - char ch = response.GetChar(); - if (ch == 'l') - break; - if (ch == 'm') - { - do - { - tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); - - if (tid != LLDB_INVALID_THREAD_ID) - { - thread_ids.push_back (tid); - } - ch = response.GetChar(); // Skip the command separator - } while (ch == ','); // Make sure we got a comma separator - } - } - } - else - { - LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'"); - sequence_mutex_unavailable = true; - } - return thread_ids.size(); -} - -lldb::addr_t -GDBRemoteCommunicationClient::GetShlibInfoAddr() -{ - if (!IsRunning()) - { - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false)) - { - if (response.IsNormalResponse()) - return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - } - } - return LLDB_INVALID_ADDRESS; -} - |
