### -*- 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