aboutsummaryrefslogtreecommitdiff
path: root/gdb/nat/windows-nat.h
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2024-05-07 16:04:50 +0100
committerPedro Alves <pedro@palves.net>2024-05-10 11:25:59 +0100
commit3f6f23ee4e943f92ed7e52c875076bdaeb70f93b (patch)
treedb94e7d3bbd217d3dc577cdf7a61a46f1bee9b62 /gdb/nat/windows-nat.h
parent734404845dfd245e26ea900bba84555e8baf09ae (diff)
downloadgdb-3f6f23ee4e943f92ed7e52c875076bdaeb70f93b.zip
gdb-3f6f23ee4e943f92ed7e52c875076bdaeb70f93b.tar.gz
gdb-3f6f23ee4e943f92ed7e52c875076bdaeb70f93b.tar.bz2
Windows gdb+gdbserver: Elim desired_stop_thread_id / rework pending_stops
windows_process.desired_stop_thread_id doesn't work for non-stop, as in that case every thread will have its own independent WaitForDebugEvent event. Instead, detect whether we have been reported a stop that was not supposed to be reported by simply checking whether the thread that is reporting the event is suspended. This is now easilly possible since each thread's suspend state is kept in sync with whether infrun wants the thread executing or not. windows_process.desired_stop_thread_id was also used as thread to pass to windows_continue. However, we don't really need that either. windows_continue is used to update the thread's registers, unsuspend them, and then finally call ContinueDebugEvent. In most cases, we only need the ContinueDebugEvent step, so we can convert the windows_continue calls to continue_last_debug_event_main_thread calls. The exception is when we see a thread creation event -- in that case, we need to update the debug registers of the new thread. We can use continue_one_thread for that. Since the pending stop is now stored in windows_thread_info, get_windows_debug_event needs to avoid reaching the bottom code if there's no thread associated with the event anymore (i.e., EXIT_THREAD_DEBUG_EVENT / EXIT_PROCESS_DEBUG_EVENT). I considered whether it would be possible to keep the pending_stop handling code shared in gdb/nat/windows-nat.c, in this patch and throughout the series, but I conclused that it isn't worth it, until gdbserver is taught about async and non-stop as well. The pending_stop struct will eventually be eliminated later down the series. Change-Id: Ib7c8e8d16edc0900b7c411976c5d70cf93931c1c
Diffstat (limited to 'gdb/nat/windows-nat.h')
-rw-r--r--gdb/nat/windows-nat.h71
1 files changed, 27 insertions, 44 deletions
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index fdbab0f..c268a12 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -32,6 +32,21 @@
namespace windows_nat
{
+/* Info about a potential pending stop. Each thread holds one of
+ these. See "windows_thread_info::pending_stop" for more
+ information. */
+struct pending_stop
+{
+ /* The target waitstatus we computed. TARGET_WAITKIND_IGNORE if the
+ thread does not have a pending stop. */
+ target_waitstatus status;
+
+ /* The event. A few fields of this can be referenced after a stop,
+ and it seemed simplest to store the entire event. */
+ DEBUG_EVENT event;
+};
+
+
/* Thread information structure used to track extra information about
each thread. */
struct windows_thread_info
@@ -71,6 +86,18 @@ struct windows_thread_info
was not. */
int suspended = 0;
+/* Info about a potential pending stop.
+
+ Sometimes, Windows will report a stop on a thread that has been
+ ostensibly suspended. We believe what happens here is that two
+ threads hit a breakpoint simultaneously, and the Windows kernel
+ queues the stop events. However, this can result in the strange
+ effect of trying to single step thread A -- leaving all other
+ threads suspended -- and then seeing a stop in thread B. To handle
+ this scenario, we queue all such "pending" stops here, and then
+ process them once the step has completed. See PR gdb/22992. */
+ struct pending_stop pending_stop {};
+
/* The context of the thread, including any manipulations. */
union
{
@@ -97,22 +124,6 @@ struct windows_thread_info
gdb::unique_xmalloc_ptr<char> name;
};
-
-/* A single pending stop. See "pending_stops" for more
- information. */
-struct pending_stop
-{
- /* The thread id. */
- DWORD thread_id;
-
- /* The target waitstatus we computed. */
- target_waitstatus status;
-
- /* The event. A few fields of this can be referenced after a stop,
- and it seemed simplest to store the entire event. */
- DEBUG_EVENT event;
-};
-
enum handle_exception_result
{
HANDLE_EXCEPTION_UNHANDLED = 0,
@@ -136,22 +147,6 @@ struct windows_process_info
stop. */
DEBUG_EVENT current_event {};
- /* The ID of the thread for which we anticipate a stop event.
- Normally this is -1, meaning we'll accept an event in any
- thread. */
- DWORD desired_stop_thread_id = -1;
-
- /* A vector of pending stops. Sometimes, Windows will report a stop
- on a thread that has been ostensibly suspended. We believe what
- happens here is that two threads hit a breakpoint simultaneously,
- and the Windows kernel queues the stop events. However, this can
- result in the strange effect of trying to single step thread A --
- leaving all other threads suspended -- and then seeing a stop in
- thread B. To handle this scenario, we queue all such "pending"
- stops here, and then process them once the step has completed. See
- PR gdb/22992. */
- std::vector<pending_stop> pending_stops;
-
/* Contents of $_siginfo */
EXCEPTION_RECORD siginfo_er {};
@@ -217,18 +212,6 @@ struct windows_process_info
void add_all_dlls ();
- /* Return true if there is a pending stop matching
- desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
- enabled. */
-
- bool matching_pending_stop (bool debug_events);
-
- /* See if a pending stop matches DESIRED_STOP_THREAD_ID. If so,
- remove it from the list of pending stops, set 'current_event', and
- return it. Otherwise, return an empty optional. */
-
- std::optional<pending_stop> fetch_pending_stop (bool debug_events);
-
const char *pid_to_exec_file (int);
private: