[Lldb-commits] [lldb] r217549 - llgs: implement qThreadStopInfo.

Todd Fiala todd.fiala at gmail.com
Wed Sep 10 14:28:38 PDT 2014


Author: tfiala
Date: Wed Sep 10 16:28:38 2014
New Revision: 217549

URL: http://llvm.org/viewvc/llvm-project?rev=217549&view=rev
Log:
llgs: implement qThreadStopInfo.

This change implements this ticket:
http://llvm.org/bugs/show_bug.cgi?id=20899

Adds the qThreadStopInfo RSP command for llgs and includes a test that
verifies both debugserver and llgs respond with something reasonable
on a multithreaded app.

Added:
    lldb/trunk/test/tools/lldb-gdbserver/TestGdbRemote_qThreadStopInfo.py
Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=217549&r1=217548&r2=217549&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Wed Sep 10 16:28:38 2014
@@ -429,6 +429,10 @@ GDBRemoteCommunicationServer::GetPacketA
         case StringExtractorGDBRemote::eServerPacketType_vAttach:
             packet_result = Handle_vAttach (packet);
             break;
+
+        case StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo:
+            packet_result = Handle_qThreadStopInfo (packet);
+            break;
         }
     }
     else
@@ -2378,8 +2382,6 @@ GDBRemoteCommunicationServer::Handle_vCo
         return SendUnimplementedResponse (packet.GetStringRef().c_str());
     }
 
-    // We handle $vCont messages for c.
-    // TODO add C, s and S.
     StreamString response;
     response.Printf("vCont;c;C;s;S");
 
@@ -4181,6 +4183,26 @@ GDBRemoteCommunicationServer::Handle_vAt
     return PacketResult::Success;
 }
 
+GDBRemoteCommunicationServer::PacketResult
+GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet)
+{
+    Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+    // We don't support if we're not llgs.
+    if (!IsGdbServer())
+        return SendUnimplementedResponse ("only supported for lldb-gdbserver");
+
+    packet.SetFilePos (strlen("qThreadStopInfo"));
+    const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID);
+    if (tid == LLDB_INVALID_THREAD_ID)
+    {
+        if (log)
+            log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
+        return SendErrorResponse (0x15);
+    }
+    return SendStopReplyPacketForThread (tid);
+}
+
 void
 GDBRemoteCommunicationServer::FlushInferiorOutput ()
 {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h?rev=217549&r1=217548&r2=217549&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h Wed Sep 10 16:28:38 2014
@@ -463,6 +463,9 @@ protected:
     PacketResult
     Handle_vAttach (StringExtractorGDBRemote &packet);
 
+    PacketResult
+    Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
+
     void
     SetCurrentThreadID (lldb::tid_t tid);
 

Added: lldb/trunk/test/tools/lldb-gdbserver/TestGdbRemote_qThreadStopInfo.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-gdbserver/TestGdbRemote_qThreadStopInfo.py?rev=217549&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/TestGdbRemote_qThreadStopInfo.py (added)
+++ lldb/trunk/test/tools/lldb-gdbserver/TestGdbRemote_qThreadStopInfo.py Wed Sep 10 16:28:38 2014
@@ -0,0 +1,87 @@
+import unittest2
+
+import gdbremote_testcase
+from lldbtest import *
+
+class TestGdbRemote_qThreadStopInfo(gdbremote_testcase.GdbRemoteTestCaseBase):
+
+    def gather_stop_replies_via_qThreadStopInfo(self, thread_count):
+        # Set up the inferior args.
+        inferior_args=[]
+        for i in range(thread_count - 1):
+            inferior_args.append("thread:new")
+        inferior_args.append("sleep:10")
+        procs = self.prep_debug_monitor_and_inferior(inferior_args=inferior_args)
+
+        # Assumes test_sequence has anything added needed to setup the initial state.
+        # (Like optionally enabling QThreadsInStopReply.)
+        self.test_sequence.add_log_lines([
+            "read packet: $c#00"
+            ], True)
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        # Give threads time to start up, then break.
+        time.sleep(1)
+        self.reset_test_sequence()
+        self.test_sequence.add_log_lines([
+            "read packet: {}".format(chr(03)),
+            {"direction":"send", "regex":r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$", "capture":{1:"stop_result", 2:"key_vals_text"} },
+            ], True)
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+        # Wait until all threads have started.
+        threads = self.wait_for_thread_count(thread_count, timeout_seconds=3)
+        self.assertIsNotNone(threads)
+        self.assertEquals(len(threads), thread_count)
+
+        # Grab stop reply for each thread via qThreadStopInfo{tid:hex}.
+        for thread in threads:
+            # Run the qThreadStopInfo command.
+            self.reset_test_sequence()
+            self.test_sequence.add_log_lines([
+                "read packet: $qThreadStopInfo{:x}#00".format(thread),
+                {"direction":"send", "regex":r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$", "capture":{1:"stop_result", 2:"key_vals_text"} },
+                ], True)
+            context = self.expect_gdbremote_sequence()
+            self.assertIsNotNone(context)
+
+            # Parse stop reply contents.
+            key_vals_text = context.get("key_vals_text")
+            self.assertIsNotNone(key_vals_text)
+            kv_dict = self.parse_key_val_dict(key_vals_text)
+            self.assertIsNotNone(kv_dict)
+
+            # Verify there is a thread.
+            kv_thread = kv_dict.get("thread")
+            self.assertIsNotNone(kv_thread)
+            self.assertEquals(int(kv_thread, 16), thread)
+
+        return threads
+
+    def qThreadStopInfo_works_for_multiple_threads(self, thread_count):
+        # Gather threads from stop notification when QThreadsInStopReply is enabled.
+        # stop_reply_threads = self.gather_stop_replies_via_qThreadStopInfo(self.ENABLE_THREADS_IN_STOP_REPLY_ENTRIES, thread_count)
+        stop_reply_threads = self.gather_stop_replies_via_qThreadStopInfo(thread_count)
+        self.assertEquals(len(stop_reply_threads), thread_count)
+
+    @debugserver_test
+    @dsym_test
+    def test_qThreadStopInfo_works_for_multiple_threads_debugserver_dsym(self):
+        self.init_debugserver_test()
+        self.buildDsym()
+        self.set_inferior_startup_launch()
+        self.qThreadStopInfo_works_for_multiple_threads(5)
+
+    @llgs_test
+    @dwarf_test
+    def test_qThreadStopInfo_works_for_multiple_threads_llgs_dwarf(self):
+        self.init_llgs_test()
+        self.buildDwarf()
+        self.set_inferior_startup_launch()
+        self.qThreadStopInfo_works_for_multiple_threads(5)
+
+
+if __name__ == '__main__':
+    unittest2.main()





More information about the lldb-commits mailing list