From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) by sourceware.org (Postfix) with ESMTPS id 4B55B3858C50 for ; Wed, 8 May 2024 21:33:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4B55B3858C50 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4B55B3858C50 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715204036; cv=none; b=LSt+sx21M4xWMx1LUyS66I+n3POOl2g3A8sn/6sWWDlOhUYweETTNCOEooFwm/q6AyrLO3Jps+keHgdX08g7fX/U+R/JjXkq+LubC0Kqlj9WwBIPX8AXl1Py3gOr0AwnMtlV3Xb3RKS2hfz1JpRob3ICJWaYygB/r4veYXveg4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715204036; c=relaxed/simple; bh=RKXOMoQE3h4IgHs+yWyiplFgaIQ9N+cOpzU2fAHjVvU=; h=Message-ID:Date:MIME-Version:Subject:To:From; b=NPhN5+HaSV6XBnURoRV+5/zH7K/ZY0fug4wEr57hpMxZj0P4KFmkCcbOEile5nfHnbLih4mgy74zKpuSHdlFtrFRPijyAcxZpVMzXSNG6y8lw3ocHhMMmsO112hdK66DH2n8weDwA+dCkU88mf9z89yic0icgu514GxdM2ePOuE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-34e040ed031so192443f8f.0 for ; Wed, 08 May 2024 14:33:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715204033; x=1715808833; h=content-transfer-encoding:in-reply-to:content-language:from :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=UFZk4YnrY0drC+iFExiivPlhRZ5PWp+rpkfqb+4bDzM=; b=MWBKuH0CNuUg2DAXs33oBYv7ir+4XeRZlA3IJdniM0ulbTna1TvHa7FRA5wAF6T7g9 xif8sG/IxDkXSxysMGgSHcg+9WiI1r5KDPB37vT0PvpfMEcu+zFYjruhI9RplKzkJ09E juZzdrsm4hyAU2uwe5z9fzXxXYSNHpIWYLDY3N4qBNK3NdJTGTyh92v+AVqoG9axItJC 2IbytjGOp36hthj84O+A78djSsHIfPmARF65coT6UWwy0nTx1Vqqmx5aNcJHm0DMsb14 G6XxYsnUFSHqIKUNs3Y0dW7mvl4dhLQ8x8dnkGH8MmFqJNuS5Kq8EB9dhNs3jTSbs8fp z00A== X-Gm-Message-State: AOJu0YzOjIiac1w8QU+jp/PBun1JxGSi6L9XDKOWTVWlUUrgwJJMohjW LRjdc0jvr1mqwjyOsSI+zRrtxVKVH30XzkOO3M+FOMJuBIRFlnsw82bPZFzn X-Google-Smtp-Source: AGHT+IF5FOWPQYTpsBO6URpPnNuxEhcyzOyFaGAKSRzrd71EjwXz5pTIfj/lS7FuyrTUvbBiv/n2NQ== X-Received: by 2002:a05:600c:46ce:b0:41c:97e:2100 with SMTP id 5b1f17b1804b1-41f71ad1ea8mr32342915e9.3.1715204012300; Wed, 08 May 2024 14:33:32 -0700 (PDT) Received: from ?IPV6:2001:8a0:f908:4900:a37a:b2e1:e7ad:4c0f? ([2001:8a0:f908:4900:a37a:b2e1:e7ad:4c0f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-41fccce93aesm1150735e9.26.2024.05.08.14.33.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 08 May 2024 14:33:31 -0700 (PDT) Message-ID: Date: Wed, 8 May 2024 22:33:30 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH 31/34 v1.2] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is available To: Eli Zaretskii Cc: gdb-patches@sourceware.org References: <20240507234233.371123-1-pedro@palves.net> <20240507234233.371123-32-pedro@palves.net> <86edaca2wi.fsf@gnu.org> From: Pedro Alves Content-Language: en-US In-Reply-To: <86edaca2wi.fsf@gnu.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,GIT_PATCH_0,HEADER_FROM_DIFFERENT_DOMAINS,KAM_DMARC_STATUS,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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 Date: Wed, 8 May 2024 21:14:26 +0100 Subject: [PATCH] Windows gdb+gdbserver: Check whether DBG_REPLY_LATER is available Per , 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