[Lldb-commits] [lldb] b4f2d7c - [lldb] [llgs] Support "t" vCont action
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 27 08:34:22 PDT 2022
Author: Michał Górny
Date: 2022-06-27T17:33:59+02:00
New Revision: b4f2d7cde54c301f591a8e2a16135bb113c5e7ed
URL: https://github.com/llvm/llvm-project/commit/b4f2d7cde54c301f591a8e2a16135bb113c5e7ed
DIFF: https://github.com/llvm/llvm-project/commit/b4f2d7cde54c301f591a8e2a16135bb113c5e7ed.diff
LOG: [lldb] [llgs] Support "t" vCont action
Implement support for the "t" action that is used to stop a thread.
Normally this action is used only in non-stop mode. However, there's
no technical reason why it couldn't be also used in all-stop mode,
e.g. to express "resume all threads except ..." (`t:...;c`).
While at it, add a more complete test for vCont correctly resuming
a subset of program's threads.
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.llvm.org/D126983
Added:
Modified:
lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/test/API/tools/lldb-server/TestGdbRemote_vCont.py
lldb/test/API/tools/lldb-server/vCont-threads/TestGdbRemote_vContThreads.py
lldb/test/API/tools/lldb-server/vCont-threads/main.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 5324a2c0bf51e..0fb4c691118b7 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -947,7 +947,7 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
case eStateSuspended:
case eStateStopped:
- llvm_unreachable("Unexpected state");
+ break;
default:
return Status("NativeProcessLinux::%s (): unexpected state %s specified "
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 10647839eec2e..a6d7500f41792 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -117,7 +117,7 @@ Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {
}
case eStateSuspended:
case eStateStopped:
- llvm_unreachable("Unexpected state");
+ break;
default:
return Status(
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 2c009ef7fcd9a..ae8b8ef8ae156 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1654,7 +1654,7 @@ GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
StringExtractorGDBRemote &packet) {
StreamString response;
- response.Printf("vCont;c;C;s;S");
+ response.Printf("vCont;c;C;s;S;t");
return SendPacketNoLock(response.GetString());
}
@@ -1723,6 +1723,11 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont(
thread_action.state = eStateStepping;
break;
+ case 't':
+ // Stop
+ thread_action.state = eStateSuspended;
+ break;
+
default:
return SendIllFormedResponse(packet, "Unsupported vCont action");
break;
diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemote_vCont.py b/lldb/test/API/tools/lldb-server/TestGdbRemote_vCont.py
index db1e39b9759d7..c17d0b7740dde 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemote_vCont.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemote_vCont.py
@@ -39,6 +39,10 @@ def test_vCont_supports_S(self):
self.build()
self.vCont_supports_mode("S")
+ def test_vCont_supports_t(self):
+ self.build()
+ self.vCont_supports_mode("t")
+
@skipIfWindows # No pty support to test O* & I* notification packets.
@skipIf(triple='^mips')
def test_single_step_only_steps_one_instruction_with_Hc_vCont_s(self):
diff --git a/lldb/test/API/tools/lldb-server/vCont-threads/TestGdbRemote_vContThreads.py b/lldb/test/API/tools/lldb-server/vCont-threads/TestGdbRemote_vContThreads.py
index 30a136f127787..2a3275004e831 100644
--- a/lldb/test/API/tools/lldb-server/vCont-threads/TestGdbRemote_vContThreads.py
+++ b/lldb/test/API/tools/lldb-server/vCont-threads/TestGdbRemote_vContThreads.py
@@ -1,5 +1,6 @@
import json
import re
+import time
import gdbremote_testcase
from lldbsuite.test.decorators import *
@@ -13,8 +14,7 @@ def start_threads(self, num):
# start the process and wait for output
self.test_sequence.add_log_lines([
"read packet: $c#63",
- {"type": "output_match", "regex": self.maybe_strict_output_regex(
- r"@started\r\n")},
+ {"type": "output_match", "regex": r".*@started\r\n.*"},
], True)
# then interrupt it
self.add_interrupt_packets()
@@ -33,9 +33,8 @@ def send_and_check_signal(self, vCont_data, threads):
self.test_sequence.add_log_lines([
"read packet: $vCont;{0}#00".format(vCont_data),
{"type": "output_match",
- "regex": self.maybe_strict_output_regex(
- len(threads) *
- r"received SIGUSR1 on thread id: ([0-9a-f]+)\r\n"),
+ "regex": len(threads) *
+ r".*received SIGUSR1 on thread id: ([0-9a-f]+)\r\n.*",
"capture": dict((i, "tid{0}".format(i)) for i
in range(1, len(threads)+1)),
},
@@ -243,3 +242,71 @@ def test_signal_two_signals(self):
context = self.expect_gdbremote_sequence()
self.assertIsNotNone(context)
+
+ THREAD_MATCH_RE = re.compile(r"thread ([0-9a-f]+) running")
+
+ def continue_and_get_threads_running(self, continue_packet):
+ self.test_sequence.add_log_lines(
+ ["read packet: ${}#00".format(continue_packet),
+ ], True)
+ self.expect_gdbremote_sequence()
+ self.reset_test_sequence()
+ time.sleep(1)
+ self.add_interrupt_packets()
+ exp = self.expect_gdbremote_sequence()
+ found = set()
+ for line in exp["O_content"].decode().splitlines():
+ m = self.THREAD_MATCH_RE.match(line)
+ if m is not None:
+ found.add(int(m.group(1), 16))
+ return found
+
+ @add_test_categories(["llgs"])
+ def test_vCont_run_subset_of_threads(self):
+ self.build()
+ self.set_inferior_startup_launch()
+
+ threads = set(self.start_threads(3))
+ all_subthreads = self.continue_and_get_threads_running("c")
+ all_subthreads_list = list(all_subthreads)
+ self.assertEqual(len(all_subthreads), 3)
+ self.assertEqual(threads & all_subthreads, all_subthreads)
+
+ # resume two threads explicitly, stop the third one implicitly
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;c:{:x};c:{:x}".format(*all_subthreads_list[:2])),
+ set(all_subthreads_list[:2]))
+
+ # resume two threads explicitly, stop others explicitly
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;c:{:x};c:{:x};t".format(*all_subthreads_list[:2])),
+ set(all_subthreads_list[:2]))
+
+ # stop one thread explicitly, resume others
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;t:{:x};c".format(all_subthreads_list[-1])),
+ set(all_subthreads_list[:2]))
+
+ # resume one thread explicitly, stop one explicitly,
+ # resume others
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;c:{:x};t:{:x};c".format(*all_subthreads_list[-2:])),
+ set(all_subthreads_list[:2]))
+
+ # resume one thread explicitly, stop one explicitly,
+ # stop others implicitly
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;t:{:x};c:{:x}".format(*all_subthreads_list[:2])),
+ set(all_subthreads_list[1:2]))
+
+ # resume one thread explicitly, stop one explicitly,
+ # stop others explicitly
+ self.assertEqual(
+ self.continue_and_get_threads_running(
+ "vCont;t:{:x};c:{:x};t".format(*all_subthreads_list[:2])),
+ set(all_subthreads_list[1:2]))
diff --git a/lldb/test/API/tools/lldb-server/vCont-threads/main.cpp b/lldb/test/API/tools/lldb-server/vCont-threads/main.cpp
index f70be42af1a92..301b54f878dfc 100644
--- a/lldb/test/API/tools/lldb-server/vCont-threads/main.cpp
+++ b/lldb/test/API/tools/lldb-server/vCont-threads/main.cpp
@@ -22,7 +22,10 @@ static void sigusr1_handler(int signo) {
static void thread_func() {
pseudo_barrier_wait(barrier);
- std::this_thread::sleep_for(std::chrono::minutes(1));
+ for (int i = 0; i < 300; ++i) {
+ std::printf("thread %" PRIx64 " running\n", get_thread_id());
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ }
}
int main(int argc, char **argv) {
More information about the lldb-commits
mailing list