Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names
@ 2026-07-09 17:43 Pedro Alves
  2026-07-10  5:18 ` Eli Zaretskii
  2026-07-10 14:41 ` [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Andrew Burgess
  0 siblings, 2 replies; 8+ messages in thread
From: Pedro Alves @ 2026-07-09 17:43 UTC (permalink / raw)
  To: gdb-patches

Running gdb.base/execl-update-breakpoints.exp on Windows 11 shows this
FAIL:

 (gdb) run
 Starting program: .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe
 Error creating process .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe (error 740): The requested operation requires elevation.
 (gdb) FAIL: gdb.base/execl-update-breakpoints.exp: runto: run to main

Error 740 is ERROR_ELEVATION_REQUIRED.

Turns out that Windows has an "installer detection" heuristic that
refuses to launch executables whose filename contains keywords like
"update", "setup", and "install" without elevation (admin rights),
unless the PE embeds a manifest declaring
requestedExecutionLevel="asInvoker".

I found some older Microsoft documentation claiming that the heuristic
only applies to 32-bit binaries, but what I observe is that:

 - It triggers with 64-bit PEs on current Windows.

And also:

 - Matches the word (e.g. "update") as a substring anywhere in the
   filename (not just as a prefix).

 - Is not drive-dependent.  I thought moving the process to a dev
   drive might suppress the check, but it does not.

I saw this problem first in a downstream ROCgdb testcase, and there I
fixed it by adjusting the name of that particular testcase.

Since this is the second case I'm seeing this already, I thought I'd
fix it in a more general way this time, one that avoids adding the
same explanatory comment to several testcases.

Fix it by making standard_testfile tweak the resulting "binfile"
output variable to avoid the "bad" words, on Windows.  This way, in
theory we only need to handle this once, in a central place.

Change-Id: I93c7d733fb8870b4ec6ff97ca59013211b362061
---
 gdb/testsuite/lib/gdb.exp | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 8eeaf2fc8e6..1201b615ee6 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4130,6 +4130,12 @@ proc is_aarch64_target {} {
     return [expr {![is_aarch32_target]}]
 }
 
+# Return true if the target is Windows-based.
+
+proc is_windows_based_target {} {
+    return [expr {[istarget *-*-cygwin*] || [istarget *-*-mingw*]}]
+}
+
 # Return 1 if displaced stepping is supported on target, otherwise, return 0.
 proc support_displaced_stepping {} {
 
@@ -8414,7 +8420,23 @@ proc standard_testfile {args} {
     global testfile binfile
 
     set testfile $gdb_test_file_name
-    set binfile [standard_output_file ${testfile}]
+
+    if {[is_windows_based_target]} {
+	# Windows' installer detection heuristic refuses to launch
+	# executables whose name contains the following words without
+	# elevation, failing with ERROR_ELEVATION_REQUIRED (740).
+	#
+	# Map of WORD => REPLACEMENT.
+	set word_map {
+	    "update" "up_date"
+	    "setup" "set_up"
+	    "install" "inst_all"
+	}
+	set binfile_basename [string map $word_map $testfile]
+    } else {
+	set binfile_basename $testfile
+    }
+    set binfile [standard_output_file ${binfile_basename}]
 
     if {[llength $args] == 0} {
 	set args .c

base-commit: 4c4e1dd5a02c1a03e7eb408987404ffd1adfd1e4
-- 
2.54.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names
  2026-07-09 17:43 [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Pedro Alves
@ 2026-07-10  5:18 ` Eli Zaretskii
  2026-07-10 18:59   ` [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables Pedro Alves
  2026-07-10 14:41 ` [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Andrew Burgess
  1 sibling, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2026-07-10  5:18 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <pedro@palves.net>
> Date: Thu,  9 Jul 2026 18:43:51 +0100
> 
> Running gdb.base/execl-update-breakpoints.exp on Windows 11 shows this
> FAIL:
> 
>  (gdb) run
>  Starting program: .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe
>  Error creating process .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe (error 740): The requested operation requires elevation.
>  (gdb) FAIL: gdb.base/execl-update-breakpoints.exp: runto: run to main
> 
> Error 740 is ERROR_ELEVATION_REQUIRED.
> 
> Turns out that Windows has an "installer detection" heuristic that
> refuses to launch executables whose filename contains keywords like
> "update", "setup", and "install" without elevation (admin rights),
> unless the PE embeds a manifest declaring
> requestedExecutionLevel="asInvoker".
> 
> I found some older Microsoft documentation claiming that the heuristic
> only applies to 32-bit binaries, but what I observe is that:
> 
>  - It triggers with 64-bit PEs on current Windows.
> 
> And also:
> 
>  - Matches the word (e.g. "update") as a substring anywhere in the
>    filename (not just as a prefix).
> 
>  - Is not drive-dependent.  I thought moving the process to a dev
>    drive might suppress the check, but it does not.

Yes, this happens on 64-bit Windows as well.

> I saw this problem first in a downstream ROCgdb testcase, and there I
> fixed it by adjusting the name of that particular testcase.
> 
> Since this is the second case I'm seeing this already, I thought I'd
> fix it in a more general way this time, one that avoids adding the
> same explanatory comment to several testcases.
> 
> Fix it by making standard_testfile tweak the resulting "binfile"
> output variable to avoid the "bad" words, on Windows.  This way, in
> theory we only need to handle this once, in a central place.

Note that IME, not only programs literally called "install.exe",
"update.exe" etc. are blocked, but also programs whose name begins
with these words.  For example, I had problems with the Texinfo's
install-info.exe.

> +    if {[is_windows_based_target]} {
> +	# Windows' installer detection heuristic refuses to launch
> +	# executables whose name contains the following words without
> +	# elevation, failing with ERROR_ELEVATION_REQUIRED (740).
> +	#
> +	# Map of WORD => REPLACEMENT.
> +	set word_map {
> +	    "update" "up_date"
> +	    "setup" "set_up"
> +	    "install" "inst_all"
> +	}
> +	set binfile_basename [string map $word_map $testfile]
> +    } else {
> +	set binfile_basename $testfile
> +    }
> +    set binfile [standard_output_file ${binfile_basename}]

FTR, another way of overcoming this is by providing a manifest file.
Below is an example of such a manifest I use for patch.exe.  The
manifest must be named PROGRAM.exe.manifest and should be in the same
directory as the executable.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="7.95.0.0"
     processorArchitecture="X86"
     name="patch.exe"
     type="win32"/>
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
	<requestedExecutionLevel
	    level="asInvoker"
	    uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
  <application> 
  <!-- Windows Vista -->
  <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
  <!-- Windows 7 -->
  <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
  <!-- Windows 8 -->
  <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
  <!-- Windows 8.1 -->
  <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
  <!-- Windows 10 -->
  <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
  </application> 
  </compatibility>
</assembly>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names
  2026-07-09 17:43 [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Pedro Alves
  2026-07-10  5:18 ` Eli Zaretskii
@ 2026-07-10 14:41 ` Andrew Burgess
  2026-07-10 19:14   ` Pedro Alves
  1 sibling, 1 reply; 8+ messages in thread
From: Andrew Burgess @ 2026-07-10 14:41 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

Pedro Alves <pedro@palves.net> writes:

> Running gdb.base/execl-update-breakpoints.exp on Windows 11 shows this
> FAIL:
>
>  (gdb) run
>  Starting program: .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe
>  Error creating process .../gdb.base/execl-update-breakpoints/execl-update-breakpoints1.exe (error 740): The requested operation requires elevation.
>  (gdb) FAIL: gdb.base/execl-update-breakpoints.exp: runto: run to main
>
> Error 740 is ERROR_ELEVATION_REQUIRED.
>
> Turns out that Windows has an "installer detection" heuristic that
> refuses to launch executables whose filename contains keywords like
> "update", "setup", and "install" without elevation (admin rights),
> unless the PE embeds a manifest declaring
> requestedExecutionLevel="asInvoker".
>
> I found some older Microsoft documentation claiming that the heuristic
> only applies to 32-bit binaries, but what I observe is that:
>
>  - It triggers with 64-bit PEs on current Windows.
>
> And also:
>
>  - Matches the word (e.g. "update") as a substring anywhere in the
>    filename (not just as a prefix).
>
>  - Is not drive-dependent.  I thought moving the process to a dev
>    drive might suppress the check, but it does not.
>
> I saw this problem first in a downstream ROCgdb testcase, and there I
> fixed it by adjusting the name of that particular testcase.
>
> Since this is the second case I'm seeing this already, I thought I'd
> fix it in a more general way this time, one that avoids adding the
> same explanatory comment to several testcases.
>
> Fix it by making standard_testfile tweak the resulting "binfile"
> output variable to avoid the "bad" words, on Windows.  This way, in
> theory we only need to handle this once, in a central place.
>
> Change-Id: I93c7d733fb8870b4ec6ff97ca59013211b362061
> ---
>  gdb/testsuite/lib/gdb.exp | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 8eeaf2fc8e6..1201b615ee6 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -4130,6 +4130,12 @@ proc is_aarch64_target {} {
>      return [expr {![is_aarch32_target]}]
>  }
>  
> +# Return true if the target is Windows-based.
> +
> +proc is_windows_based_target {} {
> +    return [expr {[istarget *-*-cygwin*] || [istarget *-*-mingw*]}]
> +}
> +
>  # Return 1 if displaced stepping is supported on target, otherwise, return 0.
>  proc support_displaced_stepping {} {
>  
> @@ -8414,7 +8420,23 @@ proc standard_testfile {args} {
>      global testfile binfile
>  
>      set testfile $gdb_test_file_name
> -    set binfile [standard_output_file ${testfile}]
> +
> +    if {[is_windows_based_target]} {
> +	# Windows' installer detection heuristic refuses to launch
> +	# executables whose name contains the following words without
> +	# elevation, failing with ERROR_ELEVATION_REQUIRED (740).
> +	#
> +	# Map of WORD => REPLACEMENT.
> +	set word_map {
> +	    "update" "up_date"
> +	    "setup" "set_up"
> +	    "install" "inst_all"
> +	}
> +	set binfile_basename [string map $word_map $testfile]
> +    } else {
> +	set binfile_basename $testfile
> +    }
> +    set binfile [standard_output_file ${binfile_basename}]

The change looks fine, but I wonder if we should factor this mapping
into a helper function?  There are tests that setup multiple
executables, and a common pattern is to call standard_output_file rather
than building the names from BINFILE.  It might be helpful if we had a
helper proc that we could call if needed in these cases.

Or maybe standard_output_file could use parse_some_args to allow
something like:

  set binfile [standard_output_file -exec ${binfile_basename}]

with '-exec' being a flag to indicate we're creating an executable, in
which ase BINFILE_BASENAME would have the string mapping applied?

Just a thought though, we can always tweak things later if you'd rather
stick with this.

Reviewed-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables
  2026-07-10  5:18 ` Eli Zaretskii
@ 2026-07-10 18:59   ` Pedro Alves
  2026-07-10 19:09     ` Pedro Alves
  2026-07-11  6:07     ` Eli Zaretskii
  0 siblings, 2 replies; 8+ messages in thread
From: Pedro Alves @ 2026-07-10 18:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On 2026-07-10 06:18, Eli Zaretskii wrote:
>> From: Pedro Alves <pedro@palves.net>
>> Turns out that Windows has an "installer detection" heuristic that
>> refuses to launch executables whose filename contains keywords like
>> "update", "setup", and "install" without elevation (admin rights),
>> unless the PE embeds a manifest declaring
>> requestedExecutionLevel="asInvoker".
>>

...

>>  - Matches the word (e.g. "update") as a substring anywhere in the
>>    filename (not just as a prefix).
>>

...

> Note that IME, not only programs literally called "install.exe",
> "update.exe" etc. are blocked, but also programs whose name begins
> with these words.  For example, I had problems with the Texinfo's
> install-info.exe.

Right, I mentioned this above.  It triggers if the string appears anywhere
on the filename as a substring.  E.g., fooupdatebar.exe triggers it.

It's curious that you bring up patch.exe.  In the downstream testcase
I mention, the initial comment that I wrote there mentioned "patch" as "bad"
word too (as some docs somewhere mention it), and then after the initial fix,
I noticed that "patch" is actually OK, and so I dropped it from the comment
in a follow up patch.

Just tried it again, to confirm:

 $ ./hello.exe
 Hello!

 $ mv hello.exe update.exe
 $ ./update.exe
 -bash: /c/msys2/home/alves/update.exe: Permission denied

 $ mv update.exe patch.exe
 $ ./patch.exe
 Hello!

So looks like Microsoft decided that "patch" wasn't a bad word after all
at some point more recently...

> FTR, another way of overcoming this is by providing a manifest file.
> Below is an example of such a manifest I use for patch.exe.  The
> manifest must be named PROGRAM.exe.manifest and should be in the same
> directory as the executable.

Indeed, I mentioned "unless manifest" further above too.  

Putting a sidecar manifest file next to every executable wouldn't work very well,
as some testcases want to rename the executable after compiling it.

It should also be possible to embed a manifest into the binary directly
using windres.  The problem I ran into the last time I tried this was that
windres/llvm-windres wasn't available in the AMD GPU LLVM-based toolchain I need
to support.  llvm-rc can also be used (with a different interface), and it is
available in some distributions, but even that one is not available in the latest
daily builds of TheRock for Windows, which I'll need to support.

... several hours of head banging and poking later ...

OK, I got it working.  Turns out that lld-link has built-in support for
embedding a manifest!  Nice.  So I can cover all the bases after all.

Also, I noticed that executables produced by the GCC 16 that comes with
MSYS2 do not have the issue. (??!)  Digging a bit, it turns out that both MSYS2 and
Cygwin ship a default-manifest.o object file that GCC pulls in via a spec file.
This default-manifest.o file is in a separate optional package, which may be
removed, and GCC keeps working, just won't link in the default manifest.

  https://gcc.gnu.org/legacy-ml/gcc-patches/2014-04/msg01378.html
  https://sourceforge.net/p/mingw-w64/wiki2/default_manifest/

I'm normally using the xPack GCC distribution (https://github.com/xpack-dev-tools/gcc-xpack/),
which does have that .o file, and thus no default manifest.
As for the gdb.rocm/ testcase I saw this first on, that is compiled wit hipcc/llvm/lld-link,
which likewise has no manifest by default.

Find below the new patch adding a manifest to every executable in the testsuite.  WDYT of this one?

Note: this caches the windres .o file using the same logic as for set_unbuffered_mode.o, which in
parallel mode should hit the same EBUSY failure fixed by the file_rename_atomic proc added by:

   https://inbox.sourceware.org/gdb-patches/20260709155657.412594-1-pedro@palves.net/T/#u

Funny I wrote there "Put the rename in
its own procedure, as I expect this will be used in more places.", and then immediately
run into such a spot the day after.  I'll tweak this new code to use that other patch's
proc once that one is in, it's just a one line change.

-- >8 --
From d721c058e8c31a07d1ce188938df8707ef773e04 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Fri, 10 Jul 2026 12:28:34 +0100
Subject: [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test
 executables

Running gdb.base/execl-update-breakpoints.exp on Windows 11 shows this
FAIL:

 (gdb) run
 Starting program: .../execl-update-breakpoints1.exe
 Error creating process .../execl-update-breakpoints1.exe (error 740): The requested operation requires elevation.
 (gdb) FAIL: gdb.base/execl-update-breakpoints.exp: runto: run to main

Error 740 is ERROR_ELEVATION_REQUIRED.

Windows has an "installer detection" heuristic that refuses to launch
executables whose file name contains keywords like "update", "setup"
and "install" without elevation (admin rights), unless the PE embeds
an application manifest declaring requestedExecutionLevel="asInvoker".

Some older Microsoft documentation claims the heuristic only applies
to 32-bit binaries, but what I observe is that:

 - It triggers with 64-bit PEs on current Windows.

And also:

 - It matches the word (e.g. "update") as a substring anywhere in the
   file name, not just as a prefix.

 - It is not drive-dependent.  I thought moving the executable to a
   dev drive might suppress the check, but it does not.

I saw this problem first in a downstream ROCgdb testcase, and there I
worked around it by renaming that particular testcase.  This is the
second case now, so rather than teach individual testcases to avoid
the "bad" words, fix it once, centrally, in a way that is independent
of the executable's file name.

The Microsoft-sanctioned escape hatch is to embed an application
manifest that declares the "asInvoker" execution level.  That's what
this commit does, it makes gdb_compile embed one in every Windows
executable it builds.

How the manifest gets embedded depends on the linker.  There are two
ways:

 - GNU ld can't embed a manifest by itself, so compile it into a
   resource object with windres and link that in.

 - lld-link is able to embed one directly, with the /manifest:embed
   and /manifestinput options.

Since it's not guaranteed that clang always links with lld-link, and
conversely, gcc may also link with lld-link, gdb_compile picks between
the two by probing what the linker accepts, rather than keying off the
compiler or the target.

This whole issue only reproduces with some toolchains, because some
MinGW or Cygwin installations already embed an equivalent manifest of
their own, via a default-manifest.o that the gcc spec links in.  That
object comes from the separate windows-default-manifest package, so
whether it is embedded depends on the installation rather than the gcc
version.

Since we're adding a manifest, might as well declare the supported
Windows versions there too (a compatibility section listing
per-version GUIDs), like default-manifest.o does.  Without those, the
version-reporting APIs (GetVersionEx and friends) cap out at Windows
8.  We should probably add such a manifest to GDB itself too, at some
point.

Change-Id: Ic0afc925136a61c259cb8b6681627dc1775a8445
---
 gdb/testsuite/lib/future.exp       |  10 ++
 gdb/testsuite/lib/gdb.exp          | 150 +++++++++++++++++++++++++++++
 gdb/testsuite/lib/windows.manifest |  53 ++++++++++
 gdb/testsuite/lib/windows.rc       |  23 +++++
 4 files changed, 236 insertions(+)
 create mode 100644 gdb/testsuite/lib/windows.manifest
 create mode 100644 gdb/testsuite/lib/windows.rc

diff --git a/gdb/testsuite/lib/future.exp b/gdb/testsuite/lib/future.exp
index 0f45aa44628..3ab160a05fc 100644
--- a/gdb/testsuite/lib/future.exp
+++ b/gdb/testsuite/lib/future.exp
@@ -177,6 +177,16 @@ proc gdb_find_readelf {} {
     return $readelf
 }
 
+proc gdb_find_windres {} {
+    global WINDRES_FOR_TARGET
+    if {[info exists WINDRES_FOR_TARGET]} {
+	set windres $WINDRES_FOR_TARGET
+    } else {
+	set windres [transform windres]
+    }
+    return $windres
+}
+
 proc gdb_find_eu-unstrip {} {
     global EU_UNSTRIP_FOR_TARGET
     if {[info exists EU_UNSTRIP_FOR_TARGET]} {
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index a40c87c6727..9b86d53be08 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4217,6 +4217,12 @@ proc is_aarch64_target {} {
     return [expr {![is_aarch32_target]}]
 }
 
+# Return true if the target is Windows-based.
+
+proc is_windows_based_target {} {
+    return [expr {[istarget *-*-cygwin*] || [istarget *-*-mingw*]}]
+}
+
 # Return 1 if displaced stepping is supported on target, otherwise, return 0.
 proc support_displaced_stepping {} {
 
@@ -6402,6 +6408,97 @@ proc quote_for_host { args } {
     return $str
 }
 
+# Set while linker_supports_manifest_embed is running its test link,
+# so that the inner gdb_compile that link goes through skips the
+# manifest-embedding logic and doesn't recurse back into the probe.
+set gdb_probing_manifest_embed 0
+
+# Return the ldflags (as a list of "ldflags=..." options) that make
+# lld-link embed our application manifest into the executable.
+
+proc gdb_windows_manifest_embed_lld_link_ldflags {} {
+    global srcdir
+
+    set ldflags {}
+
+    # Turn on embedding (off by default).
+    lappend ldflags ldflags=-Wl,/manifest:embed
+
+    # Stop lld-link from also generating its own UAC block.  With
+    # this, lld-link embeds our input as-is, while without it lld-link
+    # runs its manifest merger, which before LLVM 21 reprefixes
+    # trustInfo into the asm.v1 namespace and produces a manifest the
+    # Windows loader rejects.  See
+    # <https://github.com/llvm/llvm-project/issues/120394>.
+    lappend ldflags ldflags=-Wl,/manifestuac:no
+
+    # Embed our manifest file.  Pass it in Windows-native form.
+    # MSYS2's argument conversion treats a "/foo:/bar" argument as a
+    # colon-separated list of POSIX paths and mistakenly rewrites it
+    # to a semicolon-separated list of Windows paths.  E.g.:
+    #
+    #  "/manifestinput:/c/gdb/.../windows.manifest"
+    #    =>
+    #  "C:\msys64\manifestinput;C:\gdb\...\windows.manifest"
+    #
+    # I.e., the flag name itself gets converted as if it were a path,
+    # and the ":" becomes ";".
+    #
+    # What triggers the conversion is the value after the colon looking
+    # like an absolute POSIX path (a leading "/").  "/manifest:embed"
+    # above is left alone because "embed" doesn't.  Passing the value
+    # as a native "C:/..." path likewise avoids it.
+    set manifest [host_file_normalize ${srcdir}/lib/windows.manifest]
+    lappend ldflags ldflags=-Wl,/manifestinput:${manifest}
+
+    return $ldflags
+}
+
+# Compile lib/windows.rc into an object embedding our application
+# manifest and return the object path, so that gdb_compile can link it
+# into every Windows test executable.  The result is cached.  Returns
+# the empty string on failure.  This is used when linking with GNU ld,
+# which cannot embed a manifest by itself.
+
+proc gdb_windows_manifest_obj {} {
+    global srcdir objdir
+    global gdb_saved_windows_manifest_obj
+
+    if {[info exists gdb_saved_windows_manifest_obj]} {
+	return $gdb_saved_windows_manifest_obj
+    }
+
+    set rc_src ${srcdir}/lib/windows.rc
+    set obj_basename windows-manifest.o
+    set obj [standard_temp_file $obj_basename]
+
+    set windres [gdb_find_windres]
+    set cmd [list $windres -I [file dirname $rc_src] \
+		 -i $rc_src -o $obj -O coff]
+    verbose -log "Executing $cmd"
+    if {[catch {exec {*}$cmd} output]} {
+	verbose -log "gdb_windows_manifest_obj: windres failed: $output"
+	return ""
+    }
+
+    if {[is_remote host]} {
+	set saved $obj_basename
+    } else {
+	set saved ${objdir}/$obj_basename
+    }
+    # Link a copy of the output object, because the original may be
+    # automatically deleted.
+    if {[info exists ::GDB_PARALLEL]} {
+	# Make sure to write the .o file atomically.  (Note
+	# GDB_PARALLEL mode does not support remote host testing.)
+	file rename -force -- $obj $saved
+    } else {
+	remote_download host $obj $saved
+    }
+    set gdb_saved_windows_manifest_obj $saved
+    return $saved
+}
+
 # Compile source files specified by SOURCE into a binary of type TYPE at path
 # DEST.  gdb_compile is implemented using DejaGnu's target_compile, so the type
 # parameter and most options are passed directly to it.
@@ -6942,6 +7039,40 @@ proc gdb_compile {source dest type options} {
 	}
     }
 
+    # On Windows, embed an "asInvoker" application manifest, so that
+    # Windows doesn't refuse to launch executables (with
+    # ERROR_ELEVATION_REQUIRED/740) whose file name happens to contain
+    # an installer-detection keyword such as "update", "setup" or
+    # "install".
+    #
+    # There are two ways to get the manifest in, depending on the
+    # linker:
+    #
+    #  - GNU ld can't embed a manifest by itself, so compile the
+    #    manifest into a resource object with windres and link that
+    #    in.
+    #
+    #  - lld-link can embed a manifest by itself, no resource compiler
+    #    needed.  Note that the LLVM toolchain has llvm-windres and
+    #    llvm-rc, but not all LLVM-based toolchain distributions ship
+    #    them.
+    #
+    # Probe whether the linker supports embedding a manifest rather
+    # than trying to guess which linker is in use from the compiler or
+    # target.
+    if { $type == "executable"
+	 && [is_windows_based_target]
+	 && !$::gdb_probing_manifest_embed } {
+	if { [linker_supports_manifest_embed] } {
+	    lappend options {*}[gdb_windows_manifest_embed_lld_link_ldflags]
+	} else {
+	    set manifest_obj [gdb_windows_manifest_obj]
+	    if { $manifest_obj != "" } {
+		lappend options "ldflags=$manifest_obj"
+	    }
+	}
+    }
+
     # Automatically handle includes in testsuite/lib/.
     auto_lappend_include_files options $source
 
@@ -11203,6 +11334,25 @@ gdb_caching_proc linker_supports_image_base_flag {} {
     return [gdb_simple_compile $me $src executable $flags]
 }
 
+# Return 1 if the linker is lld-link which can embed our application
+# manifest by itself, otherwise 0.  Probes the exact flag combination
+# gdb_compile uses.
+gdb_caching_proc linker_supports_manifest_embed {} {
+    set me "linker_supports_manifest_embed"
+    set flags [gdb_windows_manifest_embed_lld_link_ldflags]
+    set src { int main() { return 0; } }
+
+    # Guard against infinite recursion: the test link below itself
+    # goes through gdb_compile, which consults this proc to decide
+    # whether to embed the manifest.  The guard makes that inner
+    # gdb_compile skip the manifest logic.
+    set ::gdb_probing_manifest_embed 1
+    set result [gdb_simple_compile $me $src executable $flags]
+    set ::gdb_probing_manifest_embed 0
+
+    return $result
+}
+
 
 # Return 1 if compiler supports scalar_storage_order attribute, otherwise
 # return 0.
diff --git a/gdb/testsuite/lib/windows.manifest b/gdb/testsuite/lib/windows.manifest
new file mode 100644
index 00000000000..f0e371588f2
--- /dev/null
+++ b/gdb/testsuite/lib/windows.manifest
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2026 Free Software Foundation, Inc.
+
+     This file is part of GDB.
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; either version 3 of the License, or
+     (at your option) any later version.
+
+     This program is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<!-- Windows' installer-detection heuristic refuses to launch an
+     executable whose file name contains words such as "update",
+     "setup" or "install" unless the PE embeds an application manifest
+     that declares the "asInvoker" execution level.  gdb_compile embeds
+     this manifest in every test executable: with GNU ld via the
+     windows.rc resource script, with lld-link via
+     /manifest:embed /manifestinput.  See gdb_compile in lib/gdb.exp.
+
+     The compatibility section declares the supported Windows versions.
+     Without it, the version-reporting APIs (GetVersionEx and friends)
+     cap out at Windows 8.  -->
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+      <!-- Windows 10 and Windows 11 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+    </application>
+  </compatibility>
+</assembly>
diff --git a/gdb/testsuite/lib/windows.rc b/gdb/testsuite/lib/windows.rc
new file mode 100644
index 00000000000..2c1b2ca81d4
--- /dev/null
+++ b/gdb/testsuite/lib/windows.rc
@@ -0,0 +1,23 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Embed the application manifest.
+
+   1  => CREATEPROCESS_MANIFEST_RESOURCE_ID
+   24 => RT_MANIFEST
+*/
+1 24 "windows.manifest"

base-commit: 490469846dcef89fe53668bdbba73591c64bed61
-- 
2.54.0



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables
  2026-07-10 18:59   ` [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables Pedro Alves
@ 2026-07-10 19:09     ` Pedro Alves
  2026-07-11  6:07     ` Eli Zaretskii
  1 sibling, 0 replies; 8+ messages in thread
From: Pedro Alves @ 2026-07-10 19:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Argh, silly typo:

On 2026-07-10 19:59, Pedro Alves wrote:

> I'm normally using the xPack GCC distribution (https://github.com/xpack-dev-tools/gcc-xpack/),
> which does have that .o file, and thus no default manifest.

I meant "does NOT have that .o file".


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names
  2026-07-10 14:41 ` [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Andrew Burgess
@ 2026-07-10 19:14   ` Pedro Alves
  0 siblings, 0 replies; 8+ messages in thread
From: Pedro Alves @ 2026-07-10 19:14 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches

Hi Andrew,

On 2026-07-10 15:41, Andrew Burgess wrote:

> The change looks fine, but I wonder if we should factor this mapping
> into a helper function?  There are tests that setup multiple
> executables, and a common pattern is to call standard_output_file rather
> than building the names from BINFILE.  It might be helpful if we had a
> helper proc that we could call if needed in these cases.
> 
> Or maybe standard_output_file could use parse_some_args to allow
> something like:
> 
>   set binfile [standard_output_file -exec ${binfile_basename}]
> 
> with '-exec' being a flag to indicate we're creating an executable, in
> which ase BINFILE_BASENAME would have the string mapping applied?
> 
> Just a thought though, we can always tweak things later if you'd rather
> stick with this.
> 

Yeah, this approach has some fragility to it.  I just now sent an alternative
approach, based on embedding a manifest into the test executables:

 https://inbox.sourceware.org/gdb-patches/17aacd11-cc42-43eb-8328-bdcedcc0dfb5@palves.net/

That should be more robust, and let us not have to worry about this ever again (fingers crossed).

> Reviewed-By: Andrew Burgess <aburgess@redhat.com>

Thank you.

Pedro Alves


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables
  2026-07-10 18:59   ` [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables Pedro Alves
  2026-07-10 19:09     ` Pedro Alves
@ 2026-07-11  6:07     ` Eli Zaretskii
  2026-07-22 14:16       ` Pedro Alves
  1 sibling, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2026-07-11  6:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> Date: Fri, 10 Jul 2026 19:59:17 +0100
> Cc: gdb-patches@sourceware.org
> From: Pedro Alves <pedro@palves.net>
> 
> It's curious that you bring up patch.exe.  In the downstream testcase
> I mention, the initial comment that I wrote there mentioned "patch" as "bad"
> word too (as some docs somewhere mention it), and then after the initial fix,
> I noticed that "patch" is actually OK, and so I dropped it from the comment
> in a follow up patch.

It used to be a problem in some older builds of Windows 11 (and nasty
one not even a manifest could work around it), but ceased to be a
problem a few system updates ago.  I have no idea what is the
situation on Windows 10, though.

>  $ mv update.exe patch.exe
>  $ ./patch.exe
>  Hello!
> 
> So looks like Microsoft decided that "patch" wasn't a bad word after all
> at some point more recently...

Yes.  But do we want to rely on the test suite being run only on the
latest builds of Windows?

> Also, I noticed that executables produced by the GCC 16 that comes with
> MSYS2 do not have the issue. (??!)  Digging a bit, it turns out that both MSYS2 and
> Cygwin ship a default-manifest.o object file that GCC pulls in via a spec file.
> This default-manifest.o file is in a separate optional package, which may be
> removed, and GCC keeps working, just won't link in the default manifest.
> 
>   https://gcc.gnu.org/legacy-ml/gcc-patches/2014-04/msg01378.html
>   https://sourceforge.net/p/mingw-w64/wiki2/default_manifest/

Thanks, that's good to know.

> Find below the new patch adding a manifest to every executable in the testsuite.  WDYT of this one?

LGTM.

> +    # Embed our manifest file.  Pass it in Windows-native form.
> +    # MSYS2's argument conversion treats a "/foo:/bar" argument as a
> +    # colon-separated list of POSIX paths and mistakenly rewrites it
> +    # to a semicolon-separated list of Windows paths.  E.g.:
> +    #
> +    #  "/manifestinput:/c/gdb/.../windows.manifest"
> +    #    =>
> +    #  "C:\msys64\manifestinput;C:\gdb\...\windows.manifest"
> +    #
> +    # I.e., the flag name itself gets converted as if it were a path,
> +    # and the ":" becomes ";".
> +    #
> +    # What triggers the conversion is the value after the colon looking
> +    # like an absolute POSIX path (a leading "/").  "/manifest:embed"
> +    # above is left alone because "embed" doesn't.  Passing the value
> +    # as a native "C:/..." path likewise avoids it.
> +    set manifest [host_file_normalize ${srcdir}/lib/windows.manifest]
> +    lappend ldflags ldflags=-Wl,/manifestinput:${manifest}

IME, you can work around this incorrect conversion by setting
MSYS_NO_PATHCONV=1.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables
  2026-07-11  6:07     ` Eli Zaretskii
@ 2026-07-22 14:16       ` Pedro Alves
  0 siblings, 0 replies; 8+ messages in thread
From: Pedro Alves @ 2026-07-22 14:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Hi!

On 2026-07-11 07:07, Eli Zaretskii wrote:
>> Date: Fri, 10 Jul 2026 19:59:17 +0100
>> Cc: gdb-patches@sourceware.org
>> From: Pedro Alves <pedro@palves.net>
>>
>> It's curious that you bring up patch.exe.  In the downstream testcase
>> I mention, the initial comment that I wrote there mentioned "patch" as "bad"
>> word too (as some docs somewhere mention it), and then after the initial fix,
>> I noticed that "patch" is actually OK, and so I dropped it from the comment
>> in a follow up patch.
> 
> It used to be a problem in some older builds of Windows 11 (and nasty
> one not even a manifest could work around it), but ceased to be a
> problem a few system updates ago.  I have no idea what is the
> situation on Windows 10, though.
> 
>>  $ mv update.exe patch.exe
>>  $ ./patch.exe
>>  Hello!
>>
>> So looks like Microsoft decided that "patch" wasn't a bad word after all
>> at some point more recently...
> 
> Yes.  

> But do we want to rely on the test suite being run only on the
> latest builds of Windows?

Right.  I meant more like, I thought that the docs I had found were wrong, and that
"patch" had never been forbidden.  But from your explanations, I now understand
that is instead that Microsoft started allowing "patch" more recently.

> 
>> Also, I noticed that executables produced by the GCC 16 that comes with
>> MSYS2 do not have the issue. (??!)  Digging a bit, it turns out that both MSYS2 and
>> Cygwin ship a default-manifest.o object file that GCC pulls in via a spec file.
>> This default-manifest.o file is in a separate optional package, which may be
>> removed, and GCC keeps working, just won't link in the default manifest.
>>
>>   https://gcc.gnu.org/legacy-ml/gcc-patches/2014-04/msg01378.html
>>   https://sourceforge.net/p/mingw-w64/wiki2/default_manifest/
> 
> Thanks, that's good to know.
> 
>> Find below the new patch adding a manifest to every executable in the testsuite.  WDYT of this one?
> 
> LGTM.

Thanks, I merged it.

> 
>> +    # Embed our manifest file.  Pass it in Windows-native form.
>> +    # MSYS2's argument conversion treats a "/foo:/bar" argument as a
>> +    # colon-separated list of POSIX paths and mistakenly rewrites it
>> +    # to a semicolon-separated list of Windows paths.  E.g.:
>> +    #
>> +    #  "/manifestinput:/c/gdb/.../windows.manifest"
>> +    #    =>
>> +    #  "C:\msys64\manifestinput;C:\gdb\...\windows.manifest"
>> +    #
>> +    # I.e., the flag name itself gets converted as if it were a path,
>> +    # and the ":" becomes ";".
>> +    #
>> +    # What triggers the conversion is the value after the colon looking
>> +    # like an absolute POSIX path (a leading "/").  "/manifest:embed"
>> +    # above is left alone because "embed" doesn't.  Passing the value
>> +    # as a native "C:/..." path likewise avoids it.
>> +    set manifest [host_file_normalize ${srcdir}/lib/windows.manifest]
>> +    lappend ldflags ldflags=-Wl,/manifestinput:${manifest}
> 
> IME, you can work around this incorrect conversion by setting
> MSYS_NO_PATHCONV=1.

That doesn't help here -- we do want the unix -> windows conversion to happen
for all filename arguments, like in "gcc /c/foo.c -o /c/foo.o".
Setting MSYS_NO_PATHCONV=1 would break all those.

msys2 also allows disabling conversion for one specific argument by using double slash,
like //option instead of /option, but here in this case the slash does not appear at
the front of the argument, it's after -Wl, so it doesn't work, as it is the compiler
that calls the linker, and the compiler is always native windows, doesn't invoke the linker
via msys2/bash.

An in any case, if it worked, then we'd be stopping the conversion
for /manifestinput _and_ the manifest path (the ${manifest} var) at the same time, as
it's all part of the same option split by ":", so we'd have to do the manual
conversion anyhow.  Just like the patch is already doing.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-07-22 14:16 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-09 17:43 [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Pedro Alves
2026-07-10  5:18 ` Eli Zaretskii
2026-07-10 18:59   ` [PATCH] gdb/Windows testsuite: Embed asInvoker manifest in test executables Pedro Alves
2026-07-10 19:09     ` Pedro Alves
2026-07-11  6:07     ` Eli Zaretskii
2026-07-22 14:16       ` Pedro Alves
2026-07-10 14:41 ` [PATCH] gdb/Windows testsuite: Avoid "bad" words in exe names Andrew Burgess
2026-07-10 19:14   ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox