[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