public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: Eli Zaretskii <eliz@gnu.org>
Cc: gdb-patches@sourceware.org
Subject: [PATCH 31/34 v1.2] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is available
Date: Wed, 8 May 2024 22:33:30 +0100	[thread overview]
Message-ID: <d7b3f201-ee73-496d-b369-35b987bc7451@palves.net> (raw)
In-Reply-To: <86edaca2wi.fsf@gnu.org>

On 2024-05-08 13:45, Eli Zaretskii wrote:

>> However, I found out that we can find the Windows major/minor/build in
>> the KUSER_SHARED_DATA structure, which defines the layout of a data
>> area that the kernel places at a pre-set address for sharing with
>> user-mode software:
>>
>>   https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kuser_shared_data/index.htm
>>
>> The Windows major/minor/build version retrieved using that method
>> bypasses the manifest stuff, it actually gets you the real OS version
>> numbers.  That is what this patch is using.
> 
> ...do we really need to do this via a version-check?  Can't we instead
> just call ContinueDebugEvent and if it fails, consider DBG_REPLY_LATER
> unsupported?  (If calling ContinueDebugEvent with that flag on older
> versions of Windows causes an exception, we could use try/catch.)  If
> this works, it is a more reliable way to test, IMO and IME.  I think
> we should prefer that to poking kernel data structures.

We need to know whether DBG_REPLY_LATER will work before starting the inferior.
And we can only call ContinueDebugEvent after starting some inferior, and
after the kernel returns an event for it via WaitForDebugEvent.

Hannes on IRC suggested using RtlGetVersion, which is exported by ntdll.dll.
I tried it, and it works nicely.  Looking around the web, I see suggestions to
use that on stockoverflow, blogs, etc.  I don't know why I didn't run into
that one before.  Maybe because the MSFT page describing it says it is
"kernel-mode":

 https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion

In truth, you can call it in user mode just fine.

Here is a version of the patch using that function.  Much simpler!

From 4331947c4728071b2d53011bf7d70bd0ab7c4e93 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Wed, 8 May 2024 21:14:26 +0100
Subject: [PATCH] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is
 available

Per
<https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-continuedebugevent>,
DBG_REPLY_LATER is "Supported in Windows 10, version 1507 or above, ..."

We need to know whether DBG_REPLY_LATER is available before starting
any inferior.

On Linux, we check which ptrace options are supported by the running
kernel by forking gdb and then the parent gdb debugging the child gdb
with PTRACE_ME, and then trying to set the ptrace options.

Doing something like that on Windows would be more complicated,
because we can't just fork, we have to start some executable, and the
only executable we know we can start, probably, is gdb itself.  And
that's a large program, so takes time to be started.  And then we'd
have to implement a WaitForDebugEvent loop to start up the process,
and then finally try ContinueDebugEvent(DBG_REPLY_LATER).

It's a lot simpler to just check the Windows version.  Unlike on
Linux, we don't have to worry about kernel feature backports.  This
patch does that.

Change-Id: Ia27b981aeecaeef430ec90cebc5b3abdce00449d
---
 gdb/nat/windows-nat.c | 56 +++++++++++++++++++++++++++++++++++++++++++
 gdb/nat/windows-nat.h |  8 +++++++
 2 files changed, 64 insertions(+)

diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 4fd717e6521..a7383276ec2 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -40,6 +40,7 @@ namespace windows_nat
    ContinueDebugEvent.  */
 static DEBUG_EVENT last_wait_event;
 
+RtlGetVersion_ftype *RtlGetVersion;
 AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
 DebugActiveProcessStop_ftype *DebugActiveProcessStop;
 DebugBreakProcess_ftype *DebugBreakProcess;
@@ -939,6 +940,57 @@ disable_randomization_available ()
 	  && DeleteProcThreadAttributeList != nullptr);
 }
 
+/* Helper for dbg_reply_later_available.  Does the actual work, while
+   dbg_reply_later_available handles caching.  */
+
+static bool
+dbg_reply_later_available_1 ()
+{
+  /* Windows has a number of functions you can use to check the OS
+     version, like GetVersion/GetVersionEx, or the Version Helper
+     functions like IsWindows10OrGreater, VerifyVersionInfo, etc.
+     However, as explained by:
+
+       https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa
+
+     ... and other pages, "Applications not manifested for Windows 8.1
+     or Windows 10 will return the Windows 8 OS version value (6.2)."
+
+     RtlGetVersion is simpler because it bypasses the manifest
+     machinery.  */
+
+  /* We require Windows XP, and RtlGetVersion exists since Windows
+     2000.  */
+  gdb_assert (RtlGetVersion != nullptr);
+
+  OSVERSIONINFOW version_info;
+  version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOW);
+  /* This is documented to always succeed.  */
+  gdb_assert (RtlGetVersion (&version_info) == 0);
+
+  debug_printf ("gdb: Windows version: major=%d, minor=%d, build=%d\n",
+		version_info.dwMajorVersion,
+		version_info.dwMinorVersion,
+		version_info.dwBuildNumber);
+
+  /* DBG_REPLY_LATER is supported since Windows 10, Version 1507,
+     which is reported as build number 10240.  */
+  return (version_info.dwMajorVersion > 10
+	  || (version_info.dwMajorVersion == 10
+	      && version_info.dwBuildNumber >= 10240));
+}
+
+/* See windows-nat.h.  */
+
+bool
+dbg_reply_later_available ()
+{
+  static int available = -1;
+  if (available == -1)
+    available = dbg_reply_later_available_1 ();
+  return available;
+}
+
 /* See windows-nat.h.  */
 
 bool
@@ -950,6 +1002,10 @@ initialize_loadable ()
 #define GPA(m, func)					\
   func = (func ## _ftype *) GetProcAddress (m, #func)
 
+  hm = LoadLibrary (TEXT ("ntdll.dll"));
+  if (hm)
+    GPA (hm, RtlGetVersion);
+
   hm = LoadLibrary (TEXT ("kernel32.dll"));
   if (hm)
     {
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 2efb54e1ce7..cee710e07d4 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -295,6 +295,7 @@ extern BOOL create_process (const wchar_t *image, wchar_t *command_line,
 			    PROCESS_INFORMATION *process_info);
 #endif /* __CYGWIN__ */
 
+#define RtlGetVersion			dyn_RtlGetVersion
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
 #define DebugBreakProcess		dyn_DebugBreakProcess
@@ -322,6 +323,9 @@ extern BOOL create_process (const wchar_t *image, wchar_t *command_line,
 #define UpdateProcThreadAttribute dyn_UpdateProcThreadAttribute
 #define DeleteProcThreadAttributeList dyn_DeleteProcThreadAttributeList
 
+typedef NTSTATUS NTAPI (RtlGetVersion_ftype) (PRTL_OSVERSIONINFOW);
+extern RtlGetVersion_ftype *RtlGetVersion;
+
 typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
 						   PTOKEN_PRIVILEGES,
 						   DWORD, PTOKEN_PRIVILEGES,
@@ -415,6 +419,10 @@ extern DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList;
 
 extern bool disable_randomization_available ();
 
+/* Return true if it's possible to use DBG_REPLY_LATER with
+   ContinueDebugEvent on this host.  */
+extern bool dbg_reply_later_available ();
+
 /* Load any functions which may not be available in ancient versions
    of Windows.  */
 

-- 
2.43.2


  reply	other threads:[~2024-05-08 21:33 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-07 23:41 [PATCH 00/34] Windows non-stop mode Pedro Alves
2024-05-07 23:42 ` [PATCH 01/34] Windows gdb: Dead code in windows_nat_target::do_initial_windows_stuff Pedro Alves
2024-05-08 14:39   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 02/34] Windows gdb: Eliminate global current_process.dr[8] global Pedro Alves
2024-05-08 15:02   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 03/34] Windows gdb+gdbserver: New find_thread, replaces thread_rec(DONT_INVALIDATE_CONTEXT) Pedro Alves
2024-05-08 15:03   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 04/34] Windows gdb: handle_output_debug_string return type Pedro Alves
2024-05-08 14:43   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 05/34] Windows gdb: Eliminate reload_context Pedro Alves
2024-05-08 14:45   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 06/34] Windows gdb+gdbserver: Eliminate thread_rec(INVALIDATE_CONTEXT) calls Pedro Alves
2024-05-08 15:08   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 07/34] Windows gdb+gdbserver: Eliminate DONT_SUSPEND Pedro Alves
2024-05-08 15:12   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 08/34] Windows gdb+gdbserver: Eliminate windows_process_info::thread_rec Pedro Alves
2024-05-08 15:12   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 09/34] Windows gdb: Simplify windows_nat_target::wait Pedro Alves
2024-05-07 23:42 ` [PATCH 10/34] Windows gdb+gdbserver: Move suspending thread to when returning event Pedro Alves
2024-05-07 23:42 ` [PATCH 11/34] Windows gdb: Introduce continue_last_debug_event_main_thread Pedro Alves
2024-05-08 14:53   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 12/34] Windows gdb: Introduce windows_continue_flags Pedro Alves
2024-05-08 15:16   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 13/34] Windows gdb: Factor code out of windows_nat_target::windows_continue Pedro Alves
2024-05-08 15:18   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 14/34] Windows gdb: Pending stop and current_event Pedro Alves
2024-05-08 15:18   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 15/34] Windows gdb+gdbserver: Elim desired_stop_thread_id / rework pending_stops Pedro Alves
2024-05-07 23:42 ` [PATCH 16/34] Windows gdb+gdbserver: Introduce get_last_debug_event_ptid Pedro Alves
2024-05-07 23:42 ` [PATCH 17/34] Windows gdb: Can't pass signal to thread other than last stopped thread Pedro Alves
2024-05-07 23:42 ` [PATCH 18/34] Windows gdbserver: Fix scheduler-locking Pedro Alves
2024-05-07 23:42 ` [PATCH 19/34] Windows gdb: Enable "set scheduler-locking on" Pedro Alves
2024-05-08 15:25   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 20/34] Windows gdbserver: Eliminate soft-interrupt mechanism Pedro Alves
2024-05-08 15:26   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 21/34] Windows gdb+gdbserver: Make current_event per-thread state Pedro Alves
2024-05-07 23:42 ` [PATCH 22/34] Windows gdb+gdbserver: Make last_sig " Pedro Alves
2024-05-07 23:42 ` [PATCH 23/34] Windows gdb+gdbserver: Make siginfo_er " Pedro Alves
2024-05-07 23:42 ` [PATCH 24/34] Add backpointer from windows_thread_info to windows_process_info Pedro Alves
2024-05-08 15:28   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 25/34] Windows gdb+gdbserver: Share $_siginfo reading code Pedro Alves
2024-05-08 15:29   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 26/34] Windows gdb+gdbserver: Eliminate struct pending_stop Pedro Alves
2024-05-07 23:42 ` [PATCH 27/34] Windows gdb: Change serial_event management Pedro Alves
2024-05-07 23:42 ` [PATCH 28/34] Windows gdb: cygwin_set_dr => windows_set_dr, etc Pedro Alves
2024-05-08 14:46   ` Tom Tromey
2024-05-07 23:42 ` [PATCH 29/34] windows_per_inferior::continue_one_thread, unify WoW64/non-WoW64 paths Pedro Alves
2024-05-07 23:42 ` [PATCH 30/34] windows-nat.c: Avoid writing debug registers if watchpoint hit pending Pedro Alves
2024-05-07 23:42 ` [PATCH 31/34] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is available Pedro Alves
2024-05-08 12:45   ` Eli Zaretskii
2024-05-08 21:33     ` Pedro Alves [this message]
2024-05-09 10:07       ` [PATCH 31/34 v1.2] " Hannes Domani
     [not found]         ` <86zfsz5kly.fsf@gnu.org>
2024-05-09 11:11           ` Pedro Alves
2024-05-09 11:47             ` [PATCH 31/34 v1.3] " Pedro Alves
2024-05-09 12:28               ` Eli Zaretskii
2024-05-09 14:17               ` Tom Tromey
     [not found]             ` <86r0eb5g2n.fsf@gnu.org>
2024-05-09 13:27               ` [PATCH 31/34 v1.2] " Pedro Alves
2024-05-07 23:42 ` [PATCH 32/34] Windows gdb: Add non-stop support Pedro Alves
2024-05-07 23:42 ` [PATCH 33/34] Windows gdb: Watchpoints while running (internal vs external stops) Pedro Alves
2024-05-07 23:42 ` [PATCH 34/34] Mention Windows non-stop support in NEWS Pedro Alves
2024-05-08 15:40 ` [PATCH 00/34] Windows non-stop mode Tom Tromey
2024-05-15 17:35   ` Tom Tromey
2024-05-15 20:39     ` Pedro Alves
2024-05-16 15:53       ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d7b3f201-ee73-496d-b369-35b987bc7451@palves.net \
    --to=pedro@palves.net \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).