[1/3] Windows gdb: Show CONTEXT_EXCEPTION_REQUEST info in "info threads"
Commit Message
This patch makes the Windows native target expose
CONTEXT_EXCEPTION_REQUEST information in "info threads" extra info,
like so:
(gdb) info threads
Id Target Id Frame
1 Thread 15648.0x4338 "sleeper" main () at sleeper.c:5
2 Thread 15648.0x3d58 (in syscall) 0x00007ffde37057b4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:/WINDOWS/SYSTEM32/ntdll.dll
3 Thread 15648.0x27e0 "sig" (in syscall) 0x00007ffde3701bc4 in ntdll!ZwReadFile () from C:/WINDOWS/SYSTEM32/ntdll.dll
4 Thread 15648.0x26f0 (in syscall) 0x00007ffde37057b4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:/WINDOWS/SYSTEM32/ntdll.dll
* 5 Thread 15648.0xff8 (in exception) 0x00007ffde00aa464 in KERNELBASE!CtrlRoutine () from C:/WINDOWS/System32/KERNELBASE.dll
(gdb)
Above, we can see that thread 1 is running user space code, threads 2
to 4 are in some system call, and thread 5 raised an exception (a
Ctrl-C).
This is useful information to see, as system calls are not
interruptible on Windows. E.g. an infcall on a thread that is blocked
in a system call will appear to hang, until the system call returns on
its own.
Change-Id: I04221f123eef81d59b5cc1c9fbb298f7a33fa001
commit-id:d93544e4
---
gdb/nat/windows-nat.h | 3 ++-
gdb/windows-nat.c | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
Comments
> From: Pedro Alves <pedro@palves.net>
> Date: Mon, 4 May 2026 18:33:40 +0100
>
> This patch makes the Windows native target expose
> CONTEXT_EXCEPTION_REQUEST information in "info threads" extra info,
> like so:
>
> (gdb) info threads
> Id Target Id Frame
> 1 Thread 15648.0x4338 "sleeper" main () at sleeper.c:5
> 2 Thread 15648.0x3d58 (in syscall) 0x00007ffde37057b4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:/WINDOWS/SYSTEM32/ntdll.dll
> 3 Thread 15648.0x27e0 "sig" (in syscall) 0x00007ffde3701bc4 in ntdll!ZwReadFile () from C:/WINDOWS/SYSTEM32/ntdll.dll
> 4 Thread 15648.0x26f0 (in syscall) 0x00007ffde37057b4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:/WINDOWS/SYSTEM32/ntdll.dll
> * 5 Thread 15648.0xff8 (in exception) 0x00007ffde00aa464 in KERNELBASE!CtrlRoutine () from C:/WINDOWS/System32/KERNELBASE.dll
> (gdb)
>
> Above, we can see that thread 1 is running user space code, threads 2
> to 4 are in some system call, and thread 5 raised an exception (a
> Ctrl-C).
>
> This is useful information to see, as system calls are not
> interruptible on Windows. E.g. an infcall on a thread that is blocked
> in a system call will appear to hang, until the system call returns on
> its own.
>
> Change-Id: I04221f123eef81d59b5cc1c9fbb298f7a33fa001
> commit-id:d93544e4
> ---
> gdb/nat/windows-nat.h | 3 ++-
> gdb/windows-nat.c | 22 ++++++++++++++++++++++
> 2 files changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
> index 52378765438..d66d5ec0ed3 100644
> --- a/gdb/nat/windows-nat.h
> +++ b/gdb/nat/windows-nat.h
> @@ -527,7 +527,8 @@ struct WindowsContext<CONTEXT *>
> | CONTEXT_SEGMENTS
> #endif
> | CONTEXT_DEBUG_REGISTERS
> - | CONTEXT_EXTENDED_REGISTERS);
> + | CONTEXT_EXTENDED_REGISTERS
> + | CONTEXT_EXCEPTION_REQUEST);
> };
>
> #ifdef __x86_64__
> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
> index a9647e90bb8..d01fbc8e4ba 100644
> --- a/gdb/windows-nat.c
> +++ b/gdb/windows-nat.c
> @@ -3363,6 +3363,28 @@ windows_nat_target::extra_thread_info (thread_info *info)
> || th->last_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
> return "exiting process";
>
> + /* Specifying CONTEXT_EXCEPTION_REQUEST in ContextFlags as input
> + (which we do), asks Windows to report back why the thread entered
> + kernel mode. If GetThreadContext returns a context with
> + CONTEXT_EXCEPTION_REPORTING set, it means that it understood the
> + request. */
> + windows_process->fill_thread_context (th);
> + DWORD context_flags = *windows_process->context_flags_ptr (th);
> + if ((context_flags & CONTEXT_EXCEPTION_REPORTING) != 0)
> + {
> + /* The thread was running user space code which raised an
> + exception, which we intercepted. */
> + if ((context_flags & CONTEXT_EXCEPTION_ACTIVE) != 0)
> + return "in exception";
> +
> + /* The thread was running a system call. */
> + if ((context_flags & CONTEXT_SERVICE_ACTIVE) != 0)
> + return "in syscall";
> +
> + /* Otherwise, the thread was simply suspended while running
> + user space code. */
> + }
> +
> return nullptr;
> }
The CONTEXT_* constants you are adding aren't defined in mingw.org's
MinGW headers. I'm guessing they were introduced for Vista or
something. So I think we will need to have their explicit definitions
in nat/windows-nat.h, guarded with #ifndef.
Also, this page:
https://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html
seems to say (near the end) that XP doesn't support
CONTEXT_EXCEPTION_REQUEST, so maybe this feature should be guarded by
a later Windows version, say 7 or 8.1?
@@ -527,7 +527,8 @@ struct WindowsContext<CONTEXT *>
| CONTEXT_SEGMENTS
#endif
| CONTEXT_DEBUG_REGISTERS
- | CONTEXT_EXTENDED_REGISTERS);
+ | CONTEXT_EXTENDED_REGISTERS
+ | CONTEXT_EXCEPTION_REQUEST);
};
#ifdef __x86_64__
@@ -3363,6 +3363,28 @@ windows_nat_target::extra_thread_info (thread_info *info)
|| th->last_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
return "exiting process";
+ /* Specifying CONTEXT_EXCEPTION_REQUEST in ContextFlags as input
+ (which we do), asks Windows to report back why the thread entered
+ kernel mode. If GetThreadContext returns a context with
+ CONTEXT_EXCEPTION_REPORTING set, it means that it understood the
+ request. */
+ windows_process->fill_thread_context (th);
+ DWORD context_flags = *windows_process->context_flags_ptr (th);
+ if ((context_flags & CONTEXT_EXCEPTION_REPORTING) != 0)
+ {
+ /* The thread was running user space code which raised an
+ exception, which we intercepted. */
+ if ((context_flags & CONTEXT_EXCEPTION_ACTIVE) != 0)
+ return "in exception";
+
+ /* The thread was running a system call. */
+ if ((context_flags & CONTEXT_SERVICE_ACTIVE) != 0)
+ return "in syscall";
+
+ /* Otherwise, the thread was simply suspended while running
+ user space code. */
+ }
+
return nullptr;
}