[Lldb-commits] [lldb] [lldb][Windows] Remember server's primary stop thread on gdb-remote stops (PR #203525)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 12 06:27:40 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Charles Zablit (charles-zablit)
<details>
<summary>Changes</summary>
The client kept the previously-selected thread across stops, ignoring the primary tid from the server in `T<sig>thread:<tid>`.
On Windows, lldb-server halts the inferior by injecting a thread called `DbgUiRemoteBreakin` whose only job is to execute an int 3. After an interrupt, the process has `N+1` threads and the new one is what caused the stop. The server reports that thread as primary, but the client ignored it and stayed on whichever thread was selected before. In `TestExpressionInSyscall` that thread is main, paused just past `NtDelayExecution`'s syscall with a garbage value in the RSI register. Evaluating an expression there crashes the JIT trampoline.
This patch makes `ProcessGDBRemote::RefreshStateAfterStop` record the primary tid from the most recent T-packet's `thread:<tid>` and select it after applying per thread stop infos.
Fixes `TestBreakpointSetRestart` and `TestExpressionInSyscall` with LLDB_USE_LLDB_SERVER=1.
---
Full diff: https://github.com/llvm/llvm-project/pull/203525.diff
2 Files Affected:
- (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (+8)
- (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (+3)
``````````diff
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 2fc6dbb546f79..754666665ae07 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -2621,6 +2621,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
SetAddressableBitMasks(addressable_bits);
+ m_last_stop_primary_tid = tid;
+
ThreadSP thread_sp = SetThreadStopInfo(
tid, expedited_register_map, signo, thread_name, reason, description,
exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid,
@@ -2669,7 +2671,13 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
if (m_initial_tid != LLDB_INVALID_THREAD_ID) {
m_thread_list.SetSelectedThreadByID(m_initial_tid);
m_initial_tid = LLDB_INVALID_THREAD_ID;
+ } else if (m_last_stop_primary_tid != LLDB_INVALID_THREAD_ID) {
+ if (ThreadSP primary_thread_sp =
+ m_thread_list.FindThreadByProtocolID(m_last_stop_primary_tid,
+ /*can_update=*/false))
+ m_thread_list.SetSelectedThreadByID(primary_thread_sp->GetID());
}
+ m_last_stop_primary_tid = LLDB_INVALID_THREAD_ID;
// Let all threads recover from stopping and do any clean up based on the
// previous thread state (if any).
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0a3386082c388..7a030cd966a18 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -322,6 +322,9 @@ class ProcessGDBRemote : public Process,
lldb::CommandObjectSP m_command_sp;
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ lldb::tid_t m_last_stop_primary_tid =
+ LLDB_INVALID_THREAD_ID; // Thread ID extracted from the most recent
+ // T-packet's "thread:<tid>" key.
bool m_use_g_packet_for_reading;
bool m_allow_flash_writes;
``````````
</details>
https://github.com/llvm/llvm-project/pull/203525
More information about the lldb-commits
mailing list