diff options
author | Steve Pucci <spucci@google.com> | 2014-01-25 05:46:51 +0000 |
---|---|---|
committer | Steve Pucci <spucci@google.com> | 2014-01-25 05:46:51 +0000 |
commit | 5ae54ae6cd5fcc3b4b6f2d0a606896ba9b2a38ed (patch) | |
tree | ae7327268ab6590169a9a36ae185fbea4660fd2b /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | |
parent | 5f730e8ef10e19b55180972befd0cb4a4a23656d (diff) | |
download | bcm5719-llvm-5ae54ae6cd5fcc3b4b6f2d0a606896ba9b2a38ed.tar.gz bcm5719-llvm-5ae54ae6cd5fcc3b4b6f2d0a606896ba9b2a38ed.zip |
Support for debugging against a remote stock gdbserver.
There are a couple of pieces:
* some lazy-evaluation members that store info listed in a qSupported response
* new method SendPacketsAndConcatenateResponses which is used for
fetching fixed-size objects from the remote gdbserver by using multiple
packets if necessary (first use will be to fetch shared-library XML files).
llvm-svn: 200072
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 147 |
1 files changed, 146 insertions, 1 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index aae3aaafa33..4ec8df86c11 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -66,6 +66,9 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_prepare_for_reg_writing_reply (eLazyBoolCalculate), m_supports_p (eLazyBoolCalculate), m_supports_QSaveRegisterState (eLazyBoolCalculate), + m_supports_qXfer_libraries_read (eLazyBoolCalculate), + m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate), + m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate), m_supports_qProcessInfoPID (true), m_supports_qfProcessInfo (true), m_supports_qUserName (true), @@ -96,7 +99,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_os_build (), m_os_kernel (), m_hostname (), - m_default_packet_timeout (0) + m_default_packet_timeout (0), + m_max_packet_size (0) { } @@ -149,6 +153,46 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) } bool +GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported () +{ + if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) + { + GetRemoteQSupported(); + } + return (m_supports_augmented_libraries_svr4_read == eLazyBoolYes); +} + +bool +GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported () +{ + if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) + { + GetRemoteQSupported(); + } + return (m_supports_qXfer_libraries_svr4_read == eLazyBoolYes); +} + +bool +GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported () +{ + if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) + { + GetRemoteQSupported(); + } + return (m_supports_qXfer_libraries_read == eLazyBoolYes); +} + +uint64_t +GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() +{ + if (m_max_packet_size == 0) + { + GetRemoteQSupported(); + } + return m_max_packet_size; +} + +bool GDBRemoteCommunicationClient::QueryNoAckModeSupported () { if (m_supports_not_sending_acks == eLazyBoolCalculate) @@ -245,6 +289,9 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_memory_region_info = eLazyBoolCalculate; m_prepare_for_reg_writing_reply = eLazyBoolCalculate; m_attach_or_wait_reply = eLazyBoolCalculate; + m_supports_qXfer_libraries_read = eLazyBoolCalculate; + m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; + m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; m_supports_qProcessInfoPID = true; m_supports_qfProcessInfo = true; @@ -260,8 +307,50 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_QEnvironmentHexEncoded = true; m_host_arch.Clear(); m_process_arch.Clear(); + + m_max_packet_size = 0; } +void +GDBRemoteCommunicationClient::GetRemoteQSupported () +{ + // Clear out any capabilities we expect to see in the qSupported response + m_supports_qXfer_libraries_svr4_read = eLazyBoolNo; + m_supports_qXfer_libraries_read = eLazyBoolNo; + m_supports_augmented_libraries_svr4_read = eLazyBoolNo; + m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse("qSupported", + response, + /*send_async=*/false) == PacketResult::Success) + { + const char *response_cstr = response.GetStringRef().c_str(); + if (::strstr (response_cstr, "qXfer:libraries-svr4:read+")) + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; + if (::strstr (response_cstr, "augmented-libraries-svr4-read")) + { + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied + m_supports_augmented_libraries_svr4_read = eLazyBoolYes; + } + if (::strstr (response_cstr, "qXfer:libraries:read+")) + m_supports_qXfer_libraries_read = eLazyBoolYes; + + const char *packet_size_str = ::strstr (response_cstr, "PacketSize="); + if (packet_size_str) + { + StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize=")); + m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); + if (m_max_packet_size == 0) + { + m_max_packet_size = UINT64_MAX; // Must have been a garbled response + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); + if (log) + log->Printf ("Garbled PacketSize spec in qSupported response"); + } + } + } +} bool GDBRemoteCommunicationClient::GetThreadSuffixSupported () @@ -364,6 +453,62 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid) } GDBRemoteCommunicationClient::PacketResult +GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses +( + const char *payload_prefix, + std::string &response_string +) +{ + Mutex::Locker locker; + if (!GetSequenceMutex(locker, + "ProcessGDBRemote::SendPacketsAndConcatenateResponses() failed due to not getting the sequence mutex")) + { + Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); + if (log) + log->Printf("error: failed to get packet sequence mutex, not sending packets with prefix '%s'", + payload_prefix); + return PacketResult::ErrorNoSequenceLock; + } + + response_string = ""; + std::string payload_prefix_str(payload_prefix); + unsigned int response_size = 0x1000; + if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet + response_size = GetRemoteMaxPacketSize(); + } + + for (unsigned int offset = 0; true; offset += response_size) + { + StringExtractorGDBRemote this_response; + // Construct payload + char sizeDescriptor[128]; + snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, response_size); + PacketResult result = SendPacketAndWaitForResponse((payload_prefix_str + sizeDescriptor).c_str(), + this_response, + /*send_async=*/false); + if (result != PacketResult::Success) + return result; + + const std::string &this_string = this_response.GetStringRef(); + + // Check for m or l as first character; l seems to mean this is the last chunk + char first_char = *this_string.c_str(); + if (first_char != 'm' && first_char != 'l') + { + return PacketResult::ErrorReplyInvalid; + } + // Skip past m or l + const char *s = this_string.c_str() + 1; + + // Concatenate the result so far + response_string += s; + if (first_char == 'l') + // We're done + return PacketResult::Success; + } +} + +GDBRemoteCommunicationClient::PacketResult GDBRemoteCommunicationClient::SendPacketAndWaitForResponse ( const char *payload, |