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

Reply via email to