On Friday 14 January 2022 01:36:10 Pali Rohár wrote: > On Thursday 13 January 2022 23:22:10 Martin Storsjö wrote: > > On Wed, 12 Jan 2022, Pali Rohár wrote: > > > > > Original MSVC 6.0 msvcrt.dll library does not provide _vscprintf() > > > function. MinGW-w64 __ms_snprintf() and __ms_vsnprintf() implementations > > > call _vscprintf() function. So include fallback _vscprintf() > > > implementation > > > into MinGW-w64 crt code to allow applications to use snprintf() with > > > original MSVC 6.0 msvcrt.dll library. > > > --- > > > mingw-w64-crt/Makefile.am | 1 + > > > mingw-w64-crt/lib-common/msvcrt.def.in | 4 ++ > > > mingw-w64-crt/misc/_vscprintf.c | 72 ++++++++++++++++++++++++++ > > > 3 files changed, 77 insertions(+) > > > create mode 100644 mingw-w64-crt/misc/_vscprintf.c > > > > > > diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am > > > index e6b644ec1d44..1be9250c1e53 100644 > > > --- a/mingw-w64-crt/Makefile.am > > > +++ b/mingw-w64-crt/Makefile.am > > > @@ -282,6 +282,7 @@ src_msvcrt32=\ > > > misc/_create_locale.c \ > > > misc/_free_locale.c \ > > > misc/_get_current_locale.c \ > > > + misc/_vscprintf.c \ > > > misc/lc_locale_func.c \ > > > misc/wassert.c > > > > > > diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in > > > b/mingw-w64-crt/lib-common/msvcrt.def.in > > > index 0ea9d388fbe4..17bc7e9a076e 100644 > > > --- a/mingw-w64-crt/lib-common/msvcrt.def.in > > > +++ b/mingw-w64-crt/lib-common/msvcrt.def.in > > > @@ -1111,7 +1111,11 @@ _vprintf_l > > > _vprintf_p > > > _vprintf_p_l > > > _vprintf_s_l > > > +#ifdef DEF_I386 > > > +; _vscprintf Replaced by emu > > > +#else > > > _vscprintf > > > +#endif > > > > We've got neater macros that avoid needing to spend many lines on this; you > > can make it F_NON_I386(_vscprintf) instead of spelling out the ifdef. See > > def-include/func.def.in for the full set of macros you can use for > > conditional availability. > > Ok! > > > > +int (__cdecl *__MINGW_IMP_SYMBOL(_vscprintf))(const char * __restrict__, > > > va_list) = init_vscprintf; > > > > This provides __imp___vscprintf only, but not __vscprintf, while > > lib32_libmingwex_a-vsnprintf.o has an undefined reference to __vscprintf. > > > > Linking still works, but this forces the linker to do an autoimport of the > > symbol, which is quite suboptimal. So it would be best if this object file > > would provide the prefix-less regular function too, which just calls what > > the __imp_ prefixed symbol points at. > > > > // Martin > > Do you mean adding following line into source unit? > > int __cdecl _vscprintf(const char * __restrict__ format, va_list arglist) { > return __MINGW_IMP_SYMBOL(_vscprintf)(format, arglist); } > > Or is there any macro for this purpose?
In attachment are updated patches which adds these redirects and usage of F_NON_I386() macro. With these redirects it is possible to compile target mingw applications also with those gcc linker flags -Wl,--disable-auto-import -Wl,--disable-runtime-pseudo-reloc. Previously gcc really throw linker error about undefined symbols _vscrpintf. Anyway, is not this redirect required to add also for _wassert() function which is in mingw-w64-crt/misc/wassert.c file? Because it use same construction like _vscprintf in my patch. And similarly other source files which calls __mingw_get_msvcrt_handle() function?
>From d57e8340e43d71b834cc2ab7b03a11f26bfb8b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Thu, 23 Dec 2021 15:15:55 +0100 Subject: [PATCH 1/2] crt: Add fallback _vscprintf() implementation Original MSVC 6.0 msvcrt.dll library does not provide _vscprintf() function. MinGW-w64 __ms_snprintf() and __ms_vsnprintf() implementations call _vscprintf() function. So include fallback _vscprintf() implementation into MinGW-w64 crt code to allow applications to use snprintf() with original MSVC 6.0 msvcrt.dll library. --- mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/lib-common/msvcrt.def.in | 2 +- mingw-w64-crt/misc/_vscprintf.c | 77 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 mingw-w64-crt/misc/_vscprintf.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index e6b644ec1d44..1be9250c1e53 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -282,6 +282,7 @@ src_msvcrt32=\ misc/_create_locale.c \ misc/_free_locale.c \ misc/_get_current_locale.c \ + misc/_vscprintf.c \ misc/lc_locale_func.c \ misc/wassert.c diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in b/mingw-w64-crt/lib-common/msvcrt.def.in index 0ea9d388fbe4..ec1f2cdf337e 100644 --- a/mingw-w64-crt/lib-common/msvcrt.def.in +++ b/mingw-w64-crt/lib-common/msvcrt.def.in @@ -1111,7 +1111,7 @@ _vprintf_l _vprintf_p _vprintf_p_l _vprintf_s_l -_vscprintf +F_NON_I386(_vscprintf) ; i386 _vscprintf replaced by emu _vscprintf_l _vscprintf_p_l _vscwprintf diff --git a/mingw-w64-crt/misc/_vscprintf.c b/mingw-w64-crt/misc/_vscprintf.c new file mode 100644 index 000000000000..6bbbb274a5ff --- /dev/null +++ b/mingw-w64-crt/misc/_vscprintf.c @@ -0,0 +1,77 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <windows.h> +#include <msvcrt.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +/* emulation of _vscprintf() via _vsnprintf() */ +static int __cdecl emu_vscprintf(const char * __restrict__ format, va_list arglist) +{ + char *buffer, *new_buffer; + size_t size; + int ret; + + /* if format is a null pointer, _vscprintf() returns -1 and sets errno to EINVAL */ + if (!format) { + _set_errno(EINVAL); + return -1; + } + + /* size for _vsnprintf() must be non-zero and buffer must have place for terminating null character */ + size = strlen(format) * 2 + 1; + buffer = malloc(size); + + if (!buffer) { + _set_errno(ENOMEM); + return -1; + } + + /* if the number of characters to write is greater than size, _vsnprintf() returns -1 */ + while (size < SIZE_MAX/2 && (ret = _vsnprintf(buffer, size, format, arglist)) < 0) { + /* in this case try with larger buffer */ + size *= 2; + new_buffer = realloc(buffer, size); + if (!new_buffer) + break; + buffer = new_buffer; + } + + free(buffer); + + if (ret < 0) { + _set_errno(ENOMEM); + return -1; + } + + return ret; +} + +static int __cdecl init_vscprintf(const char * __restrict__ format, va_list arglist); + +int (__cdecl *__MINGW_IMP_SYMBOL(_vscprintf))(const char * __restrict__, va_list) = init_vscprintf; + +static int __cdecl init_vscprintf(const char * __restrict__ format, va_list arglist) +{ + HMODULE msvcrt = __mingw_get_msvcrt_handle(); + int (__cdecl *func)(const char * __restrict__, va_list) = NULL; + + if (msvcrt) + func = (int (__cdecl *)(const char * __restrict__, va_list))GetProcAddress(msvcrt, "_vscprintf"); + + if (!func) + func = emu_vscprintf; + + return (__MINGW_IMP_SYMBOL(_vscprintf) = func)(format, arglist); +} + +int __cdecl _vscprintf(const char * __restrict__ format, va_list arglist) +{ + return __MINGW_IMP_SYMBOL(_vscprintf)(format, arglist); +} -- 2.20.1
>From 84ab9531bc184bd5e76349fd6ed62579084637d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Tue, 11 Jan 2022 13:56:21 +0100 Subject: [PATCH 2/2] crt: Add fallback _scprintf() implementation Original MSVC 6.0 msvcrt.dll library does not provide _scprintf() function. Add fallback _scprintf() implementation like for _vscprintf(). --- mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/lib-common/msvcrt.def.in | 2 +- mingw-w64-crt/misc/_scprintf.c | 57 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 mingw-w64-crt/misc/_scprintf.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 1be9250c1e53..8ced6bd97b00 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -282,6 +282,7 @@ src_msvcrt32=\ misc/_create_locale.c \ misc/_free_locale.c \ misc/_get_current_locale.c \ + misc/_scprintf.c \ misc/_vscprintf.c \ misc/lc_locale_func.c \ misc/wassert.c diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in b/mingw-w64-crt/lib-common/msvcrt.def.in index ec1f2cdf337e..942c4c4ebefe 100644 --- a/mingw-w64-crt/lib-common/msvcrt.def.in +++ b/mingw-w64-crt/lib-common/msvcrt.def.in @@ -930,7 +930,7 @@ _scalb F_X64(_scalbf) _scanf_l _scanf_s_l -_scprintf +F_NON_I386(_scprintf) ; i386 _scprintf replaced by emu _scprintf_l _scprintf_p_l _scwprintf diff --git a/mingw-w64-crt/misc/_scprintf.c b/mingw-w64-crt/misc/_scprintf.c new file mode 100644 index 000000000000..eb3044a8c5df --- /dev/null +++ b/mingw-w64-crt/misc/_scprintf.c @@ -0,0 +1,57 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <windows.h> +#include <msvcrt.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +/* mingw-w64 always provides _vscprintf() implementation, so use it */ +static int __cdecl emu_scprintf(const char * __restrict__ format, ...) +{ + va_list arglist; + int ret; + + va_start(arglist, format); + ret = _vscprintf(format, arglist); + va_end(arglist); + return ret; +} + +static int __cdecl init_scprintf(const char * __restrict__ format, ...); + +int (__cdecl *__MINGW_IMP_SYMBOL(_scprintf))(const char * __restrict__, ...) = init_scprintf; + +__attribute__((used)) +static void resolve_scprintf(void) +{ + HMODULE msvcrt = __mingw_get_msvcrt_handle(); + int (__cdecl *func)(const char * __restrict__, ...) = NULL; + + if (msvcrt) + func = (int (__cdecl *)(const char * __restrict__, ...))GetProcAddress(msvcrt, "_scprintf"); + + if (!func) + func = emu_scprintf; + + __MINGW_IMP_SYMBOL(_scprintf) = func; +} + +/* gcc does not provide an easy way to call another variadic function with reusing current arguments + * this source file is used only on i386, so do this function redirect via inline i386 assembly */ +#define ASM_SYM(sym) __MINGW64_STRINGIFY(__MINGW_USYMBOL(sym)) +asm ( +".def\t" ASM_SYM(init_scprintf) ";\t.scl\t3;\t.type\t32;\t.endef\n" +ASM_SYM(init_scprintf) ":\n\t" + "pushal\n\t" + "call\t" ASM_SYM(resolve_scprintf) "\n\t" + "popal\n\t" + /* fallthrough */ +".globl\t" ASM_SYM(_scprintf) "\n\t" +".def\t" ASM_SYM(_scprintf) ";\t.scl\t2;\t.type\t32;\t.endef\n" +ASM_SYM(_scprintf) ":\n\t" + "jmp\t*" ASM_SYM(__MINGW_IMP_SYMBOL(_scprintf)) +); -- 2.20.1
_______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public