[lldb-dev] [PATCH] new utility methods in GDBRemoteCommunicationClient

Steve Pucci spucci at google.com
Thu Jan 23 13:03:49 PST 2014


I'm working on better support for debugging against a remote stock
gdbserver, and these are some new support methods I'm using.  I'm sending
this separately for easier digestion.

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).

Thanks,
   Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140123/6df29d24/attachment.html>
-------------- next part --------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index dcf638b..2026e50 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -58,6 +58,21 @@ public:
                                   StringExtractorGDBRemote &response,
                                   bool send_async);
 
+    // For packets which specify a range of output to be returned,
+    // return all of the output via a series of packets of the form
+    // <prefix>:000,<size>
+    // <prefix>:<size>,<size>
+    // <prefix>:<size>*2,<size>
+    // <prefix>:<size>*3,<size>
+    // ...
+    // until a "$l..." packet is received, indicating the end.
+    // Concatenate the results together and return in response.
+    // If any packet fails, the response indicates that failure
+    // and the returned string value is undefined.
+    PacketResult
+    SendPacketsAndConcatenateResponses (const char *send_payload_prefix,
+                                        std::string &response_string);
+
     lldb::StateType
     SendContinuePacketAndWaitForResponse (ProcessGDBRemote *process,
                                           const char *packet_payload,
@@ -248,6 +263,9 @@ public:
     const lldb_private::ArchSpec &
     GetProcessArchitecture ();
 
+    void
+    GetRemoteQSupported();
+
     bool
     GetVContSupported (char flavor);
 
@@ -359,6 +377,18 @@ public:
     bool
     SetCurrentThreadForRun (uint64_t tid);
 
+    bool
+    GetQXferLibrariesReadSupported ();
+
+    bool
+    GetQXferLibrariesSVR4ReadSupported ();
+
+    uint64_t
+    GetRemoteMaxPacketSize();
+
+    bool
+    GetAugmentedLibrariesSVR4ReadSupported ();
+
     lldb_private::LazyBool
     SupportsAllocDeallocMemory () // const
     {
@@ -489,7 +519,10 @@ protected:
     lldb_private::LazyBool m_prepare_for_reg_writing_reply;
     lldb_private::LazyBool m_supports_p;
     lldb_private::LazyBool m_supports_QSaveRegisterState;
-    
+    lldb_private::LazyBool m_supports_qXfer_libraries_read;
+    lldb_private::LazyBool m_supports_qXfer_libraries_svr4_read;
+    lldb_private::LazyBool m_supports_augmented_libraries_svr4_read;
+
     bool
         m_supports_qProcessInfoPID:1,
         m_supports_qfProcessInfo:1,
@@ -532,6 +565,7 @@ protected:
     std::string m_os_kernel;
     std::string m_hostname;
     uint32_t m_default_packet_timeout;
+    uint64_t m_max_packet_size;  // as returned by qSupported
     
     bool
     DecodeProcessInfoResponse (StringExtractorGDBRemote &response, 
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index aae3aaa..9f591c8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/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,51 @@ 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);
+            printf("max packet size %lu\n", (unsigned long)m_max_packet_size);
+            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 +454,51 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
 }
 
 GDBRemoteCommunicationClient::PacketResult
+GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses
+(
+    const char *payload_prefix,
+    std::string &response_string
+)
+{
+    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,


More information about the lldb-dev mailing list