### -*- coding: utf-8 -*-
###
### bug #40227: Various fixes for MSVC build of 4.0
### -----------------------------------------------
###
### Synopsis:
###
### 1) Debugging make built with mingw.org 32-bits toolchain
### 2) Debugging make built with MinGW-w64 32-bits toolchain (unpatched)
### 3) Debugging make built with MinGW-w64 32-bits toolchain (patched)
###
### The 1) part is done to force the error to happen in a
### straightforward way, easy to reproduce with mingw.org. Then 2)
### shows that the behavior of a MinGW-w64 build is by default the
### same as for 1). Finally, 3) shows that the patches fixed this
### issue for MinGW-w64 builds.
#############################################################################
### 1) Debugging make built with mingw.org 32-bits toolchain
### Built using the command-line `./build_w32.bat --debug gcc`, with a
### patch enabling the use of _vsnprintf (i.e. the non-ANSI compatible
### version from the MSVCRT), in order to show what we get when
### _vsnprintf returns -1 when the buffer is not large enough.
$ which gcc
/C//Dev/MinGW-gcc440/mingw/bin/gcc
$ git diff
diff --git a/output.c b/output.c
index 5e3b073..ccfe192 100644
--- a/output.c
+++ b/output.c
@@ -14,6 +14,10 @@ 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 . */
+#ifdef WINDOWS32
+# define vsnprintf _vsnprintf
+#endif
+
#include "makeint.h"
#include "job.h"
$ gdb gnumake.exe
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32"...
(gdb) b output.c:635
Breakpoint 1 at 0x413050: file output.c, line 635.
(gdb) run -f non-existent-Makefile
Starting program: c:\Workspace\src\git\make/gnumake.exe -f non-existent-Makefile
[New thread 53896.0xb604]
Error: dll starting at 0x76dd0000 not found.
Error: dll starting at 0x75e20000 not found.
Error: dll starting at 0x76dd0000 not found.
Error: dll starting at 0x76ef0000 not found.
Breakpoint 1, vfmtconcat (fmt=0x430476 "%s: ", args=0x28f424 "≤\017║") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x4304bc "%s%s: %s", args=0x28f458 " \004C") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) b 636
Breakpoint 2 at 0x41307e: file output.c, line 636.
(gdb) step
Breakpoint 2, vfmtconcat (fmt=0x4304bc "%s%s: %s", args=0x28f458 " \004C") at output.c:638
638 if (tot >= unused)
(gdb) print tot
$1 = -1
(gdb) next
649 fmtbuf.len += tot;
(gdb)
651 return fmtbuf.buffer;
(gdb) print fmtbuf.buffer
$2 = 0xd504a0 "gnumake.exe: non-existent-½½½½½½½½ε■ε■ε■"
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x430484 "\n", args=0x28f424 "X⌠(") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) bt
#0 vfmtconcat (fmt=0x430484 "\n", args=0x28f424 "X⌠(") at output.c:635
#1 0x00413132 in fmtconcat (fmt=0x430484 "\n") at output.c:661
#2 0x0041326d in error (flocp=0x0, fmt=0x4304bc "%s%s: %s") at output.c:717
#3 0x00413383 in perror_with_name (str=0x4304ff "", name=0xd49ff2 "non-existent-Makefile")
at output.c:755
#4 0x004134f9 in read_all_makefiles (makefiles=0xbae480) at read.c:224
#5 0x0040c94f in main (argc=3, argv=0xba1158, envp=0xba47b0) at main.c:1905
(gdb) step
Breakpoint 2, vfmtconcat (fmt=0x430484 "\n", args=0x28f424 "X⌠(") at output.c:638
638 if (tot >= unused)
(gdb) next
649 fmtbuf.len += tot;
(gdb) next
651 return fmtbuf.buffer;
(gdb) print fmtbuf.buffer
$3 = 0xd504a0 "gnumake.exe:\n"
(gdb) cont
Continuing.
gnumake.exe:
Breakpoint 1, vfmtconcat (fmt=0x43049c "%s: *** ", args=0x28f334 "≤\017║") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x43049c "%s: *** ", args=0x28f334 "≤\017║") at output.c:638
638 if (tot >= unused)
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x430e58 "%sNo rule to make target '%s'%s",
args=0x28f368 "¿\016C") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x430e58 "%sNo rule to make target '%s'%s",
args=0x28f368 "¿\016C") at output.c:638
638 if (tot >= unused)
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x4304b2 ". Stop.\n", args=0x28f334 "h≤(") at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x4304b2 ". Stop.\n", args=0x28f334 "h≤(") at output.c:638
638 if (tot >= unused)
(gdb) cont
Continuing.
gnumake.exe: ***. Stop.
Program exited with code 02.
(gdb) quit
#############################################################################
### 2) Debugging make built with MinGW-w64 32-bits toolchain (unpatched)
### Built using the command-line `./build_w32.bat --debug gcc`, with
### *no patches applied*. We see the same behavior as in 1).
$ which gcc
/C/Dev/mingw-builds/x32-4.8.1-posix-sjlj-rev5/mingw32/bin/gcc
$ gdb gnumake
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-w64-mingw32".
For bug reporting instructions, please see:
...
Reading symbols from c:\Workspace\src\git\make\gnumake.exe...done.
(gdb) b output.c:631
Breakpoint 1 at 0x413a5b: file output.c, line 631.
(gdb) b output.c:634
Breakpoint 2 at 0x413a89: file output.c, line 634.
(gdb) run -f non-existent-Makefile
Starting program: c:\Workspace\src\git\make\gnumake.exe -f non-existent-Makefile
[New Thread 25576.0x6ab4]
Breakpoint 1, vfmtconcat (fmt=0x4323d6 "%s: ", args=0x28f3a4 "j\023û")
at output.c:631
631 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) step
vsnprintf (__stream=0x0, __n=0, __format=0x4323d6 "%s: ",
__local_argv=0x28f3a4 "j\023û")
at c:/dev/mingw-builds/x32-4.8.1-posix-sjlj-rev5/mingw32/i686-w64-mingw32/include/stdio.h:552
552 return __ms_vsnprintf (__stream, __n, __format, __local_argv);
### Note: this shows that in MinGW-w64 _vsnprintf will by default call
### __ms_vsnprintf (which in turn simply calls MSVCRT's _vsnprintf)
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x4323d6 "%s: ", args=0x28f3a4 "j\023û")
at output.c:634
634 if (tot >= unused)
(gdb) print tot
$1 = 9
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x43241c "%s%s: %s", args=0x28f3d8 "_$C")
at output.c:631
631 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x43241c "%s%s: %s", args=0x28f3d8 "_$C")
at output.c:634
634 if (tot >= unused)
(gdb) print tot
$2 = -1
(gdb) print fmtbuf
$3 = {buffer = 0x2870958 "gnumake: non-exist««««««««î_î_î_", size = 18, len = 9}
(gdb) next
645 fmtbuf.len += tot;
(gdb)
647 return fmtbuf.buffer;
(gdb) print fmtbuf
$4 = {buffer = 0x2870958 "gnumake: non-exist««««««««î_î_î_", size = 18, len = 8}
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x4323e4 "\n", args=0x28f3a4 "Oó(")
at output.c:631
631 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x4323e4 "\n", args=0x28f3a4 "Oó(")
at output.c:634
634 if (tot >= unused)
(gdb) next
645 fmtbuf.len += tot;
(gdb) print tot
$5 = 1
(gdb) next
647 return fmtbuf.buffer;
(gdb) print fmtbuf.buffer
$6 = 0x2870958 "gnumake:\n"
(gdb) cont
Continuing.
gnumake:
Breakpoint 1, vfmtconcat (fmt=0x4323fc "%s: *** ", args=0x28f2b4 "j\023û")
at output.c:631
631 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x4323fc "%s: *** ", args=0x28f2b4 "j\023û")
at output.c:634
634 if (tot >= unused)
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x432db8 "%sNo rule to make target '%s'%s",
args=0x28f2e8 "\b.C") at output.c:631
631 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) del
Delete all breakpoints? (y or n) y
(gdb) cont
Continuing.
gnumake: ***. Sto½½½½½½½½ε■ε■ε■[Inferior 1 (process 25576) exited with code 02]
(gdb) quit
#############################################################################
### 3) Debugging make built with MinGW-w64 32-bits toolchain (patched)
### Built using the command-line `./build_w32.bat --debug gcc`, with
### the __USE_MINGW_ANSI_STDIO=1 patch applied. We see that the
### problem is gone, as an ANSI compatible version of vsnprintf gets
### now called.
$ which gcc
/C/Dev/mingw-builds/x32-4.8.1-posix-sjlj-rev5/mingw32/bin/gcc
$ git diff
diff --git a/output.c b/output.c
index 5e3b073..9ee42b9 100644
--- a/output.c
+++ b/output.c
@@ -14,6 +14,10 @@ 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 . */
+#ifdef WINDOWS32
+# define __USE_MINGW_ANSI_STDIO 1
+#endif
+
#include "makeint.h"
#include "job.h"
$ gdb gnumake
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-w64-mingw32".
For bug reporting instructions, please see:
...
Reading symbols from c:\Workspace\src\git\make\gnumake.exe...done.
(gdb) run -f non-existent-Makefiel
Starting program: c:\Workspace\src\git\make\gnumake.exe -f non-existent-Makefiel
[New Thread 71232.0x11f30]
gnumake: non-existent-Makefiel: No such file or directory
gnumake: *** No rule to make target 'non-existent-Makefiel'. Stop.
[Inferior 1 (process 71232) exited with code 02]
(gdb) b output.c:635
Breakpoint 1 at 0x413a8b: file output.c, line 635.
(gdb) b output.c:638
Breakpoint 2 at 0x413ab9: file output.c, line 638.
(gdb) run -f non-existent-Makefile
Starting program: c:\Workspace\src\git\make\gnumake.exe -f non-existent-Makefile
[New Thread 71324.0x11de4]
Breakpoint 1, vfmtconcat (fmt=0x4373d6 "%s: ", args=0x28f3a4 "j\023\065")
at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) step
vsnprintf (__stream=0x0, __n=0, __format=0x4373d6 "%s: ",
__local_argv=0x28f3a4 "j\023\065")
at c:/dev/mingw-builds/x32-4.8.1-posix-sjlj-rev5/mingw32/i686-w64-mingw32/include/stdio.h:352
352 return __mingw_vsnprintf( __stream, __n, __format, __local_argv );
### Note: this shows that in MinGW-w64, with __USE_MINGW_ANSI_STDIO=1
### _vsnprintf calls __mingw_vsnprintf (which has an ANSI compatible
### behavior, as we'll see below).
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x4373d6 "%s: ", args=0x28f3a4 "j\023\065")
at output.c:638
638 if (tot >= unused)
(gdb) cont
Continuing.
Breakpoint 1, vfmtconcat (fmt=0x43741c "%s%s: %s", args=0x28f3d8 "_tC")
at output.c:635
635 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, args);
(gdb) step
vsnprintf (__stream=0x2960961 "", __n=9, __format=0x43741c "%s%s: %s",
__local_argv=0x28f3d8 "_tC")
at c:/dev/mingw-builds/x32-4.8.1-posix-sjlj-rev5/mingw32/i686-w64-mingw32/include/stdio.h:352
352 return __mingw_vsnprintf( __stream, __n, __format, __local_argv );
(gdb) cont
Continuing.
Breakpoint 2, vfmtconcat (fmt=0x43741c "%s%s: %s", args=0x28f3d8 "_tC")
at output.c:638
638 if (tot >= unused)
(gdb) print tot
$1 = 48
(gdb) next
640 fmtbuf.size += tot * 2;
(gdb)
641 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
(gdb)
643 unused = fmtbuf.size - fmtbuf.len;
(gdb)
644 tot = vsnprintf (&fmtbuf.buffer[fmtbuf.len], unused, fmt, vcopy);
(gdb)
649 fmtbuf.len += tot;
(gdb) print tot
$2 = 48
(gdb) next
651 return fmtbuf.buffer;
(gdb) print fmtbuf
$3 = {buffer = 0x2960958 "gnumake: non-existent-Makefile: No such file or directory",
size = 114, len = 57}
(gdb) del
Delete all breakpoints? (y or n) y
(gdb) cont
Continuing.
gnumake: non-existent-Makefile: No such file or directory
gnumake: *** No rule to make target 'non-existent-Makefile'. Stop.
[Inferior 1 (process 71324) exited with code 02]
(gdb) quit