ld: testsuite: Fix a few backslash-related issues on MinGW.

Message ID 20260717101723.1022175-1-jdx@o2.pl
State New
Headers
Series ld: testsuite: Fix a few backslash-related issues on MinGW. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed

Commit Message

Jan Dubiec July 17, 2026, 10:14 a.m. UTC
  Several relatively new test cases fail on MinGW:
[...]
Running /d/Works/binutils/ld/testsuite/ld-archive/archive.exp ...
FAIL: Script fake archive link
FAIL: Script fake whole archive link
FAIL: Script fake group archive link accept
[...]

This is because on Windows ld uses "\" instead of "/" to create full file
names as shown in the log below:

[...]
/d/Works/xcomp/build-binutils-h8300-mingw/ld/../gas/as-new   -I/d/Works/binutils/ld/testsuite/ld-archive   -o tmpdir/abc.o  /d/Works/binutils/ld/testsuite/ld-archive/abc.s
Executing on host: sh -c {/d/Works/xcomp/build-binutils-h8300-mingw/ld/../gas/as-new   -I/d/Works/binutils/ld/testsuite/ld-archive   -o tmpdir/abc.o  /d/Works/binutils/ld/testsuite/ld-archive/abc.s 2>&1}  /dev/null ld.tmp (timeout = 300)
spawn [open ...]
/d/Works/xcomp/build-binutils-h8300-mingw/ld/ld-new    -o tmpdir/absc  -L/d/Works/binutils/ld/testsuite/ld-archive -e ff tmpdir/abc.o /d/Works/binutils/ld/testsuite/ld-archive/ab.t --verbose --print-map
Executing on host: sh -c {/d/Works/xcomp/build-binutils-h8300-mingw/ld/ld-new    -o tmpdir/absc  -L/d/Works/binutils/ld/testsuite/ld-archive -e ff tmpdir/abc.o /d/Works/binutils/ld/testsuite/ld-archive/ab.t --verbose --print-map 2>&1}  /dev/null ld.tmp (timeout = 300)
spawn [open ...]
GNU ld (GNU Toolchain for Renesas H8 Family [Built by jdx] (rev. 150e616528b)) 2.47.50.20260713
  Supported emulations:
   h8300helf
   h8300self
   h8300hnelf
   h8300snelf
   h8300sxelf
   h8300sxnelf
   h8300elf
using internal linker script:

[... IRRELEVANT LINKER SCRIPT REMOVED ..]

==================================================
D:\Works\xcomp\build-binutils-h8300-mingw\ld\ld-new.exe: mode h8300helf
attempt to open tmpdir/abc.o succeeded
tmpdir/abc.o
attempt to open D:/Works/binutils/ld/testsuite/ld-archive/ab.t succeeded
D:/Works/binutils/ld/testsuite/ld-archive/ab.t
opened script file D:/Works/binutils/ld/testsuite/ld-archive/ab.t
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/a.o failed
attempt to open tmpdir/a.o succeeded
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/b.o failed
attempt to open tmpdir/b.o succeeded
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/x.o failed
attempt to open tmpdir/x.o succeeded
<no file> (D:\Works\xcomp\build-binutils-h8300-mingw\ld\ld-new.exe generated)
Archive member included to satisfy reference by file (symbol)

tmpdir/a.o                    tmpdir/abc.o (aa)
tmpdir/a.o
tmpdir/b.o                    tmpdir/abc.o (bb)
tmpdir/b.o

There are no discarded input sections

[... IRRELEVANT MAP FILE REMOVED ..]

regexp_diff match failure
regexp "^attempt to open .*/ld/testsuite/ld-archive/tmpdir/a\.o failed$"
line   "attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/a.o failed"
regexp_diff match failure
regexp "^attempt to open .*/ld/testsuite/ld-archive/tmpdir/b\.o failed$"
line   "attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/b.o failed"
regexp_diff match failure
regexp "^attempt to open .*/ld/testsuite/ld-archive/tmpdir/x\.o failed$"
line   "attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/x.o failed"
FAIL: Script fake archive link
[...]

Signed-off-by: Jan Dubiec <jdx@o2.pl>
---
 ld/testsuite/ld-archive/absc.vd   | 6 +++---
 ld/testsuite/ld-archive/abscfg.vd | 6 +++---
 ld/testsuite/ld-archive/abwsc.vd  | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)
  

Comments

Jan Beulich July 17, 2026, 10:59 a.m. UTC | #1
On 17.07.2026 12:14, Jan Dubiec wrote:
> Several relatively new test cases fail on MinGW:
> [...]
> Running /d/Works/binutils/ld/testsuite/ld-archive/archive.exp ...
> FAIL: Script fake archive link
> FAIL: Script fake whole archive link
> FAIL: Script fake group archive link accept
> [...]
> 
> This is because on Windows ld uses "\" instead of "/" to create full file
> names as shown in the log below:

Yet: Does it need to? If slashes work, can't ld simply use slashes?

Jan
  
Maciej W. Rozycki July 17, 2026, 11:35 a.m. UTC | #2
On Fri, 17 Jul 2026, Jan Beulich wrote:

> > Several relatively new test cases fail on MinGW:
> > [...]
> > Running /d/Works/binutils/ld/testsuite/ld-archive/archive.exp ...
> > FAIL: Script fake archive link
> > FAIL: Script fake whole archive link
> > FAIL: Script fake group archive link accept
> > [...]
> > 
> > This is because on Windows ld uses "\" instead of "/" to create full file
> > names as shown in the log below:
> 
> Yet: Does it need to? If slashes work, can't ld simply use slashes?

 Seconded: what's the root cause, i.e. where does the backslash exactly 
come from?

  Maciej
  
Jan Dubiec July 17, 2026, 12:16 p.m. UTC | #3
On 17.07.2026 13:35, Maciej W. Rozycki wrote:
[...]

>   Seconded: what's the root cause, i.e. where does the backslash exactly
> come from?
 From the linker. It is invoked as follows:
/d/Works/xcomp/build-binutils-h8300-mingw/ld/ld-new    -o tmpdir/absc 
-L/d/Works/binutils/ld/testsuite/ld-archive -e ff tmpdir/abc.o 
/d/Works/binutils/ld/testsuite/ld-archive/ab.t --verbose --print-map

For each library listed in ld/testsuite/ld-archive/ab.t, the linker 
takes the library name, prepends the library search path specified with 
the -L option, inserting a "\" between them, and then attempts to open 
the resulting file. If that fails, it falls back to using the relative 
file name instead. It's all in the log:

[...]
D:\Works\xcomp\build-binutils-h8300-mingw\ld\ld-new.exe: mode h8300helf
attempt to open tmpdir/abc.o succeeded
tmpdir/abc.o
attempt to open D:/Works/binutils/ld/testsuite/ld-archive/ab.t succeeded
D:/Works/binutils/ld/testsuite/ld-archive/ab.t
opened script file D:/Works/binutils/ld/testsuite/ld-archive/ab.t
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/a.o failed
attempt to open tmpdir/a.o succeeded
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/b.o failed
attempt to open tmpdir/b.o succeeded
attempt to open D:/Works/binutils/ld/testsuite/ld-archive\tmpdir/x.o failed
attempt to open tmpdir/x.o succeeded
[...]

/J.D.
  
Jan Dubiec July 17, 2026, 12:33 p.m. UTC | #4
On 17.07.2026 12:59, Jan Beulich wrote:
[...]> Yet: Does it need to? If slashes work, can't ld simply use slashes?
Don't ask me — I wasn't involved in porting the GNU tools to 
Windows/MinGW. :-)

In any case, the tools built with MinGW are native Windows executables. 
They use the WinAPI directly, without a compatibility layer such as 
Cygwin. As a result, they can be invoked either from a Unix-like shell 
or from the rather crappy native Windows shell, cmd.exe, which doesn't 
always handle forward slashes gracefully. So I would say that it is 
quite common that these tools mix backward and forward slashes.

/J.D.
  
Jan Beulich July 17, 2026, 12:51 p.m. UTC | #5
On 17.07.2026 14:33, Jan Dubiec wrote:
> On 17.07.2026 12:59, Jan Beulich wrote:
> [...]> Yet: Does it need to? If slashes work, can't ld simply use slashes?
> Don't ask me — I wasn't involved in porting the GNU tools to 
> Windows/MinGW. :-)
> 
> In any case, the tools built with MinGW are native Windows executables. 
> They use the WinAPI directly, without a compatibility layer such as 
> Cygwin. As a result, they can be invoked either from a Unix-like shell 
> or from the rather crappy native Windows shell, cmd.exe, which doesn't 
> always handle forward slashes gracefully. So I would say that it is 
> quite common that these tools mix backward and forward slashes.

But you're making testsuite adjustments. There's no cmd.exe shell involved
there, I don't think. Clearly with the many slashes in the paths that you
quoted, one more slash won't break things?

Jan
  
Maciej W. Rozycki July 17, 2026, 2:05 p.m. UTC | #6
On Fri, 17 Jul 2026, Jan Dubiec wrote:

> >   Seconded: what's the root cause, i.e. where does the backslash exactly
> > come from?
> From the linker. It is invoked as follows:
> /d/Works/xcomp/build-binutils-h8300-mingw/ld/ld-new    -o tmpdir/absc
> -L/d/Works/binutils/ld/testsuite/ld-archive -e ff tmpdir/abc.o
> /d/Works/binutils/ld/testsuite/ld-archive/ab.t --verbose --print-map
> 
> For each library listed in ld/testsuite/ld-archive/ab.t, the linker takes the
> library name, prepends the library search path specified with the -L option,
> inserting a "\" between them, and then attempts to open the resulting file. If
> that fails, it falls back to using the relative file name instead. It's all in
> the log:

 This doesn't answer my question; we know from your report that it happens 
"somewhere in the linker" already.  Please point me at the source code 
line this happens at.  I have no MinGW host system available to track it 
down myself.

  Maciej
  
Jan Dubiec July 17, 2026, 2:23 p.m. UTC | #7
On 17.07.2026 14:51, Jan Beulich wrote:
[...]

> But you're making testsuite adjustments. There's no cmd.exe shell involved

Yes, because this is not an ld issue — ld behaves as expected. The 
problem lies in these three test cases, which do not account for the 
fact that different hosts may use different directory separators.

> there, I don't think. Clearly with the many slashes in the paths that you
> quoted, one more slash won't break things?
Sure, but why bother when the linker already does the job? Besides, 
changing that one innocent \ to / doesn't seem like a trivial task to 
me. IMO, it would require fairly extensive testing.

/J.D.
  
Jan Dubiec July 17, 2026, 3:43 p.m. UTC | #8
On 17.07.2026 16:05, Maciej W. Rozycki wrote:
[...]

>   This doesn't answer my question; we know from your report that it happens
> "somewhere in the linker" already.  Please point me at the source code
> line this happens at.  I have no MinGW host system available to track it
> down myself.
I don't know the exact line number, but look at ld/ldfile.c. Near the 
top it has the following definition:

[...]
#ifdef VMS
static char *slash = "";
#else
#if defined (_WIN32) && !defined (__CYGWIN32__)
static char *slash = "\\";
#else
static char *slash = "/";
#endif
#endif
[...]

and then four times calls concat() (concat.c from libiberty), e.g. like 
this:

[...]
if (entry->flags.maybe_archive && !entry->flags.full_name_provided)
     string = concat (search->name, slash, lib, entry->filename,
                      arch, suffix, (const char *) NULL);
else
     string = concat (search->name, slash, entry->filename,
                      (const char *) 0);

if (ldfile_try_open_bfd (string, entry))
[...]

But does it really matter? The definition of slash appears to be 30+ 
years old, and the binutils tools have been working successfully on 
Windows for many years. The issue clearly lies with the test cases.

/J.D.
  
Maciej W. Rozycki July 18, 2026, 5:53 p.m. UTC | #9
On Fri, 17 Jul 2026, Jan Dubiec wrote:

> >   This doesn't answer my question; we know from your report that it happens
> > "somewhere in the linker" already.  Please point me at the source code
> > line this happens at.  I have no MinGW host system available to track it
> > down myself.
> I don't know the exact line number, but look at ld/ldfile.c. Near the top it
> has the following definition:
> 
> [...]
> #ifdef VMS
> static char *slash = "";
> #else
> #if defined (_WIN32) && !defined (__CYGWIN32__)
> static char *slash = "\\";
> #else
> static char *slash = "/";
> #endif
> #endif
> [...]

 Thanks for looking into it.  A reference to this arrangement would IMO 
serve as the correct justification in the commit description and while I 
could not approve such a change I would back out my objection.  However...

> But does it really matter? The definition of slash appears to be 30+ years
> old, and the binutils tools have been working successfully on Windows for many
> years. The issue clearly lies with the test cases.

 It does matter to me, I find the inconsistency resulting in a mixture of 
forward and backward slashes a mess.

 And I'm not alone, as GDB has literally just cleaned up that mess; cf.
<https://inbox.sourceware.org/gdb-patches/20260629212430.340516-1-pedro@palves.net/> 
and especially the discussion downthread for the rationale.  Perhaps we 
should too?

 FWIW the possibility of a cleanup analogous to that was the motivation 
for my objection even though I wasn't aware of the GDB effort at the time, 
as I continue being a little behind with mailing list traffic after a 
recent disruption.  Also interesting timing indeed.

 I think a reasonable course of action would be accepting your change in 
the interim for the upcoming release with the commit description amended 
as requested, and then cleaning up the mess with slashes targetting 2.48.

  Maciej
  
Jan Dubiec July 18, 2026, 11:50 p.m. UTC | #10
On 18.07.2026 19:53, Maciej W. Rozycki wrote:
[...]

>   I think a reasonable course of action would be accepting your change in
> the interim for the upcoming release with the commit description amended
> as requested, and then cleaning up the mess with slashes targetting 2.48.
> 
>    Maciej

It's not a big deal — we can wait until 2.48. It also looks like the 
current patch won't be necessary. Given that "slash" is a static 
variable (or rather a constant) and is only used when constructing full 
file names, I simply changed:

-static char *slash = "\\";
+static char *slash = "/";

The results look promising: so far, there have been no regressions. I'll 
post the new patch later.

That said, we should also review the other binutils tools from this 
perspective. Fortunately, a quick search through the sources didn't 
reveal any potentially problematic code (IMO). I also don't recall any 
other tool exhibiting a similar "/" vs. "\\" issue, although I could be 
wrong.

/J.D.
  

Patch

diff --git a/ld/testsuite/ld-archive/absc.vd b/ld/testsuite/ld-archive/absc.vd
index c48f8f3652c..ac543fc9215 100644
--- a/ld/testsuite/ld-archive/absc.vd
+++ b/ld/testsuite/ld-archive/absc.vd
@@ -9,11 +9,11 @@  tmpdir/abc\.o
 attempt to open .*/ld/testsuite/ld-archive/ab\.t succeeded
 .*/ld/testsuite/ld-archive/ab\.t
 opened script file .*/ld/testsuite/ld-archive/ab\.t
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/a\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/a\.o failed
 attempt to open tmpdir/a\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/b\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/b\.o failed
 attempt to open tmpdir/b\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/x\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/x\.o failed
 attempt to open tmpdir/x\.o succeeded
 <no file> \(.* generated\)
 Archive member included to satisfy reference by file \(symbol\)
diff --git a/ld/testsuite/ld-archive/abscfg.vd b/ld/testsuite/ld-archive/abscfg.vd
index 8751f390216..9ee345b7375 100644
--- a/ld/testsuite/ld-archive/abscfg.vd
+++ b/ld/testsuite/ld-archive/abscfg.vd
@@ -7,11 +7,11 @@  using ..ternal linker script:.*
 attempt to open .*/ld/testsuite/ld-archive/ab\.t succeeded
 .*/ld/testsuite/ld-archive/ab\.t
 opened script file .*/ld/testsuite/ld-archive/ab\.t
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/a\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/a\.o failed
 attempt to open tmpdir/a\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/b\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/b\.o failed
 attempt to open tmpdir/b\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/x\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/x\.o failed
 attempt to open tmpdir/x\.o succeeded
 <no file> \(.* generated\)
 attempt to open tmpdir/abc\.o succeeded
diff --git a/ld/testsuite/ld-archive/abwsc.vd b/ld/testsuite/ld-archive/abwsc.vd
index 8c36e694cfa..5e8585b7cca 100644
--- a/ld/testsuite/ld-archive/abwsc.vd
+++ b/ld/testsuite/ld-archive/abwsc.vd
@@ -9,11 +9,11 @@  tmpdir/abc\.o
 attempt to open .*/ld/testsuite/ld-archive/ab\.t succeeded
 .*/ld/testsuite/ld-archive/ab\.t
 opened script file .*/ld/testsuite/ld-archive/ab\.t
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/a\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/a\.o failed
 attempt to open tmpdir/a\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/b\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/b\.o failed
 attempt to open tmpdir/b\.o succeeded
-attempt to open .*/ld/testsuite/ld-archive/tmpdir/x\.o failed
+attempt to open .*/ld/testsuite/ld-archive[/\\]tmpdir/x\.o failed
 attempt to open tmpdir/x\.o succeeded
 <no file> \(.* generated\)
 Archive member included to satisfy reference by file \(symbol\)