[Lldb-commits] [lldb] r279040 - gdb-remote: Centralize thread specific packet handling

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 18 01:30:03 PDT 2016


Author: labath
Date: Thu Aug 18 03:30:03 2016
New Revision: 279040

URL: http://llvm.org/viewvc/llvm-project?rev=279040&view=rev
Log:
gdb-remote: Centralize thread specific packet handling

Summary:
Before this, each function had a copy of the code which handled appending of the thread suffix to
the packet (or using $Hg instead). I have moved that code into a single function and made
everyone else use that. The function takes the partial packet as a StreamString rvalue reference,
to avoid a copy and to remind the users that the packet will have undeterminate contents after
the call.

This also fixes the incorrect formatting of the QRestoreRegisterState packet in case thread
suffix is not supported.

Reviewers: clayborg

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D23604

Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
    lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp

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=279040&r1=279039&r2=279040&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Thu Aug 18 03:30:03 2016
@@ -574,6 +574,31 @@ GDBRemoteCommunicationClient::GetVContSu
     return false;
 }
 
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(lldb::tid_t tid, StreamString &&payload,
+                                                                         StringExtractorGDBRemote &response,
+                                                                         bool send_async)
+{
+    Lock lock(*this, send_async);
+    if (!lock)
+    {
+        if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
+            log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for %s packet.", __FUNCTION__,
+                        payload.GetString().c_str());
+        return PacketResult::ErrorNoSequenceLock;
+    }
+
+    if (GetThreadSuffixSupported())
+        payload.Printf(";thread:%4.4" PRIx64 ";", tid);
+    else
+    {
+        if (!SetCurrentThread(tid))
+            return PacketResult::ErrorSendFailed;
+    }
+
+    return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
+}
+
 // Check if the target supports 'p' packet. It sends out a 'p'
 // packet and checks the response. A normal packet will tell us
 // that support is available.
@@ -584,18 +609,15 @@ GDBRemoteCommunicationClient::GetpPacket
 {
     if (m_supports_p == eLazyBoolCalculate)
     {
-        StringExtractorGDBRemote response;
         m_supports_p = eLazyBoolNo;
-        char packet[256];
-        if (GetThreadSuffixSupported())
-            snprintf(packet, sizeof(packet), "p0;thread:%" PRIx64 ";", tid);
-        else
-            snprintf(packet, sizeof(packet), "p0");
-        
-        if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
+        StreamString payload;
+        payload.PutCString("p0");
+        StringExtractorGDBRemote response;
+        if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
+                PacketResult::Success &&
+            response.IsNormalResponse())
         {
-            if (response.IsNormalResponse())
-                m_supports_p = eLazyBoolYes;
+            m_supports_p = eLazyBoolYes;
         }
     }
     return m_supports_p;
@@ -3473,108 +3495,42 @@ GDBRemoteCommunicationClient::AvoidGPack
 bool
 GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
 {
-    Lock lock(*this, false);
-    if (lock)
-    {
-        const bool thread_suffix_supported = GetThreadSuffixSupported();
-        
-        if (thread_suffix_supported || SetCurrentThread(tid))
-        {
-            char packet[64];
-            int packet_len = 0;
-            if (thread_suffix_supported)
-                packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, tid);
-            else
-                packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
-            assert (packet_len < ((int)sizeof(packet) - 1));
-            return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
-        }
-    }
-    else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-    {
-        log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for p packet.", __FUNCTION__);
-    }
-    return false;
-
+    StreamString payload;
+    payload.Printf("p%x", reg);
+    return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
+           PacketResult::Success;
 }
 
 
 bool
 GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractorGDBRemote &response)
 {
-    Lock lock(*this, false);
-    if (lock)
-    {
-        const bool thread_suffix_supported = GetThreadSuffixSupported();
-
-        if (thread_suffix_supported || SetCurrentThread(tid))
-        {
-            char packet[64];
-            int packet_len = 0;
-            // Get all registers in one packet
-            if (thread_suffix_supported)
-                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", tid);
-            else
-                packet_len = ::snprintf (packet, sizeof(packet), "g");
-            assert (packet_len < ((int)sizeof(packet) - 1));
-            return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
-        }
-    }
-    else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-    {
-        log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for g packet.", __FUNCTION__);
-    }
-    return false;
+    StreamString payload;
+    payload.PutChar('g');
+    return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
+           PacketResult::Success;
 }
 
 bool
 GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::StringRef data)
 {
-    Lock lock(*this, false);
-    if (!lock)
-    {
-        if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-            log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for P packet.", __FUNCTION__);
-        return false;
-    }
-
-    const bool thread_suffix_supported = GetThreadSuffixSupported();
-    if (!thread_suffix_supported && !SetCurrentThread(tid))
-        return false;
-
-    StreamString packet;
-    packet.Printf("P%x=", reg_num);
-    packet.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder());
-    if (thread_suffix_supported)
-        packet.Printf(";thread:%4.4" PRIx64 ";", tid);
+    StreamString payload;
+    payload.Printf("P%x=", reg_num);
+    payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder());
     StringExtractorGDBRemote response;
-    return SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success &&
-           response.IsOKResponse();
+    return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
+           PacketResult::Success;
 }
 
 bool
 GDBRemoteCommunicationClient::WriteAllRegisters(lldb::tid_t tid, llvm::StringRef data)
 {
-    Lock lock(*this, false);
-    if (!lock)
-    {
-        if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-            log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for G packet.", __FUNCTION__);
-        return false;
-    }
-
-    const bool thread_suffix_supported = GetThreadSuffixSupported();
-    if (!thread_suffix_supported && !SetCurrentThread(tid))
-        return false;
-
-    StreamString packet;
-    packet.PutChar('G');
-    packet.Write(data.data(), data.size());
-    if (thread_suffix_supported)
-        packet.Printf(";thread:%4.4" PRIx64 ";", tid);
+    StreamString payload;
+    payload.PutChar('G');
+    payload.Write(data.data(), data.size());
     StringExtractorGDBRemote response;
-    return SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success &&
-           response.IsOKResponse();
+    return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
+           PacketResult::Success;
 }
 
 bool
@@ -3585,43 +3541,21 @@ GDBRemoteCommunicationClient::SaveRegist
         return false;
     
     m_supports_QSaveRegisterState = eLazyBoolYes;
-    Lock lock(*this, false);
-    if (lock)
-    {
-        const bool thread_suffix_supported = GetThreadSuffixSupported();
-        if (thread_suffix_supported || SetCurrentThread(tid))
-        {
-            char packet[256];
-            if (thread_suffix_supported)
-                ::snprintf (packet, sizeof(packet), "QSaveRegisterState;thread:%4.4" PRIx64 ";", tid);
-            else
-                ::snprintf(packet, sizeof(packet), "QSaveRegisterState");
-            
-            StringExtractorGDBRemote response;
+    StreamString payload;
+    payload.PutCString("QSaveRegisterState");
+    StringExtractorGDBRemote response;
+    if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success)
+        return false;
 
-            if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
-            {
-                if (response.IsUnsupportedResponse())
-                {
-                    // This packet isn't supported, don't try calling it again
-                    m_supports_QSaveRegisterState = eLazyBoolNo;
-                }
-                    
-                const uint32_t response_save_id = response.GetU32(0);
-                if (response_save_id != 0)
-                {
-                    save_id = response_save_id;
-                    return true;
-                }
-            }
-        }
-    }
-    else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-    {
-        log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for QSaveRegisterState packet.",
-                    __FUNCTION__);
-    }
-    return false;
+    if (response.IsUnsupportedResponse())
+        m_supports_QSaveRegisterState = eLazyBoolNo;
+
+    const uint32_t response_save_id = response.GetU32(0);
+    if (response_save_id == 0)
+        return false;
+
+    save_id = response_save_id;
+    return true;
 }
 
 bool
@@ -3633,40 +3567,17 @@ GDBRemoteCommunicationClient::RestoreReg
     if (m_supports_QSaveRegisterState == eLazyBoolNo)
         return false;
 
-    Lock lock(*this, false);
-    if (lock)
-    {
-        const bool thread_suffix_supported = GetThreadSuffixSupported();
-        if (thread_suffix_supported || SetCurrentThread(tid))
-        {
-            char packet[256];
-            if (thread_suffix_supported)
-                ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u;thread:%4.4" PRIx64 ";", save_id, tid);
-            else
-                ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u" PRIx64 ";", save_id);
-            
-            StringExtractorGDBRemote response;
-            
-            if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
-            {
-                if (response.IsOKResponse())
-                {
-                    return true;
-                }
-                else if (response.IsUnsupportedResponse())
-                {
-                    // This packet isn't supported, don't try calling this packet or
-                    // QSaveRegisterState again...
-                    m_supports_QSaveRegisterState = eLazyBoolNo;
-                }
-            }
-        }
-    }
-    else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
-    {
-        log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex for QRestoreRegisterState packet.",
-                    __FUNCTION__);
-    }
+    StreamString payload;
+    payload.Printf("QRestoreRegisterState:%u", save_id);
+    StringExtractorGDBRemote response;
+    if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success)
+        return false;
+
+    if (response.IsOKResponse())
+        return true;
+
+    if (response.IsUnsupportedResponse())
+        m_supports_QSaveRegisterState = eLazyBoolNo;
     return false;
 }
 

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=279040&r1=279039&r2=279040&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Thu Aug 18 03:30:03 2016
@@ -633,6 +633,10 @@ protected:
     void
     OnRunPacketSent(bool first) override;
 
+    PacketResult
+    SendThreadSpecificPacketAndWaitForResponse(lldb::tid_t tid, StreamString &&payload,
+                                               StringExtractorGDBRemote &response, bool send_async);
+
 private:
     DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);
 };

Modified: lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp?rev=279040&r1=279039&r2=279040&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp (original)
+++ lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp Thu Aug 18 03:30:03 2016
@@ -54,6 +54,8 @@ HandlePacket(MockServer &server, llvm::S
     ASSERT_EQ(PacketResult::Success, server.SendPacket(response));
 }
 
+const char all_registers[] = "404142434445464748494a4b4c4d4e4f";
+
 } // end anonymous namespace
 
 class GDBRemoteCommunicationClientTest : public GDBRemoteTest
@@ -78,10 +80,9 @@ TEST_F(GDBRemoteCommunicationClientTest,
     HandlePacket(server, "P4=41424344;thread:0047;", "OK");
     ASSERT_TRUE(write_result.get());
 
-    write_result = std::async(std::launch::async,
-                              [&] { return client.WriteAllRegisters(tid, "404142434445464748494a4b4c4d4e4f"); });
+    write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); });
 
-    HandlePacket(server, "G404142434445464748494a4b4c4d4e4f;thread:0047;", "OK");
+    HandlePacket(server, std::string("G") + all_registers + ";thread:0047;", "OK");
     ASSERT_TRUE(write_result.get());
 }
 
@@ -103,9 +104,58 @@ TEST_F(GDBRemoteCommunicationClientTest,
     HandlePacket(server, "P4=41424344", "OK");
     ASSERT_TRUE(write_result.get());
 
-    write_result = std::async(std::launch::async,
-                              [&] { return client.WriteAllRegisters(tid, "404142434445464748494a4b4c4d4e4f"); });
+    write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); });
 
-    HandlePacket(server, "G404142434445464748494a4b4c4d4e4f", "OK");
+    HandlePacket(server, std::string("G") + all_registers, "OK");
     ASSERT_TRUE(write_result.get());
 }
+
+TEST_F(GDBRemoteCommunicationClientTest, ReadRegister)
+{
+    TestClient client;
+    MockServer server;
+    Connect(client, server);
+    if (HasFailure())
+        return;
+
+    const lldb::tid_t tid = 0x47;
+    const uint32_t reg_num = 4;
+    std::future<bool> async_result = std::async(std::launch::async, [&] { return client.GetpPacketSupported(tid); });
+    Handle_QThreadSuffixSupported(server, true);
+    HandlePacket(server, "p0;thread:0047;", "41424344");
+    ASSERT_TRUE(async_result.get());
+
+    StringExtractorGDBRemote response;
+    async_result = std::async(std::launch::async, [&] { return client.ReadRegister(tid, reg_num, response); });
+    HandlePacket(server, "p4;thread:0047;", "41424344");
+    ASSERT_TRUE(async_result.get());
+    ASSERT_EQ("41424344", response.GetStringRef());
+
+    async_result = std::async(std::launch::async, [&] { return client.ReadAllRegisters(tid, response); });
+    HandlePacket(server, "g;thread:0047;", all_registers);
+    ASSERT_TRUE(async_result.get());
+    ASSERT_EQ(all_registers, response.GetStringRef());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix)
+{
+    TestClient client;
+    MockServer server;
+    Connect(client, server);
+    if (HasFailure())
+        return;
+
+    const lldb::tid_t tid = 0x47;
+    uint32_t save_id;
+    std::future<bool> async_result =
+        std::async(std::launch::async, [&] { return client.SaveRegisterState(tid, save_id); });
+    Handle_QThreadSuffixSupported(server, false);
+    HandlePacket(server, "Hg47", "OK");
+    HandlePacket(server, "QSaveRegisterState", "1");
+    ASSERT_TRUE(async_result.get());
+    EXPECT_EQ(1u, save_id);
+
+    async_result = std::async(std::launch::async, [&] { return client.RestoreRegisterState(tid, save_id); });
+    HandlePacket(server, "QRestoreRegisterState:1", "OK");
+    ASSERT_TRUE(async_result.get());
+}




More information about the lldb-commits mailing list