On Friday 03 July 2026 13:45:14 LIU Hao wrote: > 在 2026-7-1 02:57, Pali Rohár 写道: > > On Tuesday 30 June 2026 14:57:04 LIU Hao wrote: > > > Hi Pali, > > > > > > There's a report about this linker error today: > > > https://github.com/mingw-w64/mingw-w64/issues/177#issuecomment-4840677432 > > > > > > The current setup where libmsvcrt references symbols from libmingw32 > > > doesn't > > > look quite correct; in GCC default specs, CRT libraries are linked in this > > > order `-lmingw32 -lmingwex -lmsvcrt`. Therefore I suggest > > > b9ac6b67372d065a5bcd4f515b7f84118a65446b be reverted before the issue is > > > solved. > > > > Hello, thank you for noticing me about this problem. > > > > I understand this problem, variables/functions/symbols defined in > > mingw-w64-crt/crt/ directory cannot be referenced in files from other > > directories because /crt/ is in libmingw32.a library and that is before > > other libraries in gcc specs file. > > > > The bad thing about this issue is that it happens only sometimes. I did > > not figured out when gcc/ld starts complaining about > > "undefined reference" and when not. I observed that higher probability > > is when the LTO is enabled. > > > > For example on CI in tests are used those i386__beginthreadex.c > > implementations and 32-bit x86 gcc on CI is happy, it always passed. > > Also it passed all my local testing. So such issues can happen and we > > will get info about them only once somebody hit it. > > > > > > In the attachment I'm sending a proposal for fixing this issue. > > Basically "copy" the implementation into both crtexe.c and > > i386__beginthreadex.c files. I do not see any easy way how to "share" > > that one symbol between libmingw32.a and libmsvcrt-os.a (or libmsvcrt.a). > > And because now the __mingw_SEH_error_handler implementation is very > > small (just wrapper around the _XcptFilter), so do not think this > > copy would be an issue. > > > > I have tested it only locally, to provide fix as fast as possible, so > > maybe there could be some CI issues. > > > > Could you please forward these patches to reporter, so could try to > > verify if it works? > > > > Note that patches are on top of my "__mingw_init_ehandler" changes: > > https://sourceforge.net/p/mingw-w64/mailman/message/59348860/ > > but rebasing without them should be relatively easy, there should be > > just context conflict in crtexe.c around "asm volatile" line. > > Would you please hard-wrap those lines before submitting a patch?
I rebased them on without the __mingw_init_ehandler changes.
>From c368d19f5325085d3ba28da59f53b60fe06c28b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]> Date: Tue, 23 Jun 2026 22:34:44 +0200 Subject: [PATCH 1/3] crt: Move duplicated sse_float_exception_handler function into common file i386_sse_float_exception_handler.h --- mingw-w64-crt/misc/i386__beginthread.c | 19 +-------------- mingw-w64-crt/misc/i386__beginthreadex.c | 19 +-------------- .../misc/i386_sse_float_exception_handler.h | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 36 deletions(-) create mode 100644 mingw-w64-crt/misc/i386_sse_float_exception_handler.h diff --git a/mingw-w64-crt/misc/i386__beginthread.c b/mingw-w64-crt/misc/i386__beginthread.c index 6d07df7e7cfa..150b0f3d6ec6 100644 --- a/mingw-w64-crt/misc/i386__beginthread.c +++ b/mingw-w64-crt/misc/i386__beginthread.c @@ -6,29 +6,12 @@ #if defined(__i386__) -/* Function _beginthread() in pre-msvcr100 libraries do not handle STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS SEH exceptions. - * These two SEH exceptions are thrown by Windows system for 32-bit x86 processes when SSE floating point exception occurs. - * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_error_handler() which correctly process them. - * x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */ - #include <stdlib.h> #include <errno.h> #include <process.h> #include <windows.h> -EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(EXCEPTION_RECORD *, PVOID, CONTEXT *, PVOID); - -#if defined(__i386__) -/* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ -__attribute__((force_align_arg_pointer)) -#endif -static EXCEPTION_DISPOSITION __cdecl sse_float_exception_handler(EXCEPTION_RECORD *ExceptionRecord, PVOID EstablisherFrame, CONTEXT *ContextRecord, PVOID DispatcherContext) -{ - if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS || ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS) - return __mingw_SEH_error_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); - else - return ExceptionContinueSearch; -} +#include "i386_sse_float_exception_handler.h" #if defined(__i386__) /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ diff --git a/mingw-w64-crt/misc/i386__beginthreadex.c b/mingw-w64-crt/misc/i386__beginthreadex.c index aede03f34d31..b23f654844fa 100644 --- a/mingw-w64-crt/misc/i386__beginthreadex.c +++ b/mingw-w64-crt/misc/i386__beginthreadex.c @@ -6,29 +6,12 @@ #if defined(__i386__) -/* Function _beginthreadex() in pre-msvcr100 libraries do not handle STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS SEH exceptions. - * These two SEH exceptions are thrown by Windows system for 32-bit x86 processes when SSE floating point exception occurs. - * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_error_handler() which correctly process them. - * x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */ - #include <stdlib.h> #include <errno.h> #include <process.h> #include <windows.h> -EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(EXCEPTION_RECORD *, PVOID, CONTEXT *, PVOID); - -#if defined(__i386__) -/* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ -__attribute__((force_align_arg_pointer)) -#endif -static EXCEPTION_DISPOSITION __cdecl sse_float_exception_handler(EXCEPTION_RECORD *ExceptionRecord, PVOID EstablisherFrame, CONTEXT *ContextRecord, PVOID DispatcherContext) -{ - if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS || ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS) - return __mingw_SEH_error_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); - else - return ExceptionContinueSearch; -} +#include "i386_sse_float_exception_handler.h" #if defined(__i386__) /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ diff --git a/mingw-w64-crt/misc/i386_sse_float_exception_handler.h b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h new file mode 100644 index 000000000000..940c88c6aa12 --- /dev/null +++ b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h @@ -0,0 +1,24 @@ +/** + * 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. + */ + +/* Functions _beginthread() and _beginthreadex() in 32-bit x86 pre-msvcr100 libraries do not handle STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS SEH exceptions. + * These two SEH exceptions are thrown by Windows system for 32-bit x86 processes when SSE floating point exception occurs. + * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_error_handler() which correctly process them. + * x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */ + +EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(EXCEPTION_RECORD *, PVOID, CONTEXT *, PVOID); + +#if defined(__i386__) +/* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ +__attribute__((force_align_arg_pointer)) +#endif +static EXCEPTION_DISPOSITION __cdecl sse_float_exception_handler(EXCEPTION_RECORD *ExceptionRecord, PVOID EstablisherFrame, CONTEXT *ContextRecord, PVOID DispatcherContext) +{ + if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS || ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS) + return __mingw_SEH_error_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + else + return ExceptionContinueSearch; +} -- 2.20.1 >From b53a104aef1d78c4315b01d012d6a0af6d5d634c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]> Date: Tue, 30 Jun 2026 20:34:06 +0200 Subject: [PATCH 2/3] crt: Fix linking issues for __mingw_SEH_error_handler symbol When LTO is enabled, gcc in some configurations cannot reference the __mingw_SEH_error_handler symbol from i386__beginthreadex.c file. This is because -lmingw32 is before -lmsvcrt in gcc specs file, which means that libmsvcrt.a (library which contains i386__beginthreadex.o) cannot reference symbols from libmingw32.a (library which provides the __mingw_SEH_error_handler symbol). Only opposite direction is valid. Fix this problem by including the implementation of __mingw_SEH_error_handler symbol into the i386__beginthreadex.c itself. To prevent this issue to happen again, move the implementation of __mingw_SEH_error_handler from .c file to internal header file and mark it as static. That header file is then included into the i386__beginthreadex.c. And also remove arm64ec symbol mangling in crtexe.c file which is needed only for non-static symbols. Static symbols do not use that mangling. --- mingw-w64-crt/Makefile.am | 4 ++-- mingw-w64-crt/crt/crtexe.c | 12 +++--------- .../crt/{crt_handler.c => seh_signal_dispatcher.h} | 4 +--- .../misc/i386_sse_float_exception_handler.h | 2 +- 4 files changed, 7 insertions(+), 15 deletions(-) rename mingw-w64-crt/crt/{crt_handler.c => seh_signal_dispatcher.h} (96%) diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index b651dce59d51..31ce267e9183 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -115,14 +115,14 @@ src_libtaskschd=libsrc/taskschd.c src_libntoskrnl=libsrc/memcmp.c src_libdloadhelper=libsrc/dloadhelper.c misc/delay-f.c -src_libmingw32=include/internal.h include/sect_attribs.h \ +src_libmingw32=include/internal.h include/sect_attribs.h crt/seh_signal_dispatcher.h \ crt/crtexewin.c crt/dll_argv.c crt/gccmain.c crt/natstart.c crt/pseudo-reloc-list.c crt/wildcard.c \ crt/charmax.c crt/ucrtexewin.c crt/dllargv.c crt/_newmode.c crt/tlssup.c crt/xncommod.c \ crt/cinitexe.c crt/merr.c crt/pesect.c crt/udllargc.c crt/xthdloc.c \ crt/mingw_custom.c crt/mingw_helpers.c \ crt/pseudo-reloc.c crt/udll_argv.c \ crt/usermatherr.c \ - crt/xtxtmode.c crt/crt_handler.c \ + crt/xtxtmode.c \ crt/tlsthrd.c crt/tlsmthread.c crt/tlsmcrt.c \ crt/cxa_atexit.c crt/cxa_thread_atexit.c crt/tls_atexit.c diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c index 86c3842f6162..5976fc5e48db 100644 --- a/mingw-w64-crt/crt/crtexe.c +++ b/mingw-w64-crt/crt/crtexe.c @@ -24,15 +24,10 @@ #else #define ASM_SEH_EXCEPT "@except" #endif -#ifdef __arm64ec__ -#define ASM_SEH_PREFIX "\"#" -#define ASM_SEH_SUFFIX "\"" -#else -#define ASM_SEH_PREFIX "" -#define ASM_SEH_SUFFIX "" -#endif #endif +#include "seh_signal_dispatcher.h" + extern IMAGE_DOS_HEADER __ImageBase; int *__cdecl __p__commode(void); @@ -66,7 +61,6 @@ static int managedapp; static int has_cctor = 0; extern void _pei386_runtime_relocator (void); -EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler (struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *); #if defined(__x86_64__) && !defined(SEH_INLINE_ASM) int __mingw_init_ehandler (void); #endif @@ -164,7 +158,7 @@ __tmainCRTStartup (void) }; __writefsdword (0, (DWORD)&exception_record); /* dynamically register SEH error handler, it is active until manually unregistered */ #elif defined(SEH_INLINE_ASM) - asm volatile (".seh_handler " ASM_SEH_PREFIX "%c0" ASM_SEH_SUFFIX ", " ASM_SEH_EXCEPT :: "i" (__mingw_SEH_error_handler)); /* statically register SEH error handler, it is active only in the current function */ + asm volatile (".seh_handler %c0, " ASM_SEH_EXCEPT :: "i" (__mingw_SEH_error_handler)); /* statically register SEH error handler, it is active only in the current function */ #elif defined(__x86_64__) __mingw_init_ehandler (); /* dynamically register SEH error handler for all functions, it is active until program terminates */ #else diff --git a/mingw-w64-crt/crt/crt_handler.c b/mingw-w64-crt/crt/seh_signal_dispatcher.h similarity index 96% rename from mingw-w64-crt/crt/crt_handler.c rename to mingw-w64-crt/crt/seh_signal_dispatcher.h index 191c2da65751..4b5164321ffa 100644 --- a/mingw-w64-crt/crt/crt_handler.c +++ b/mingw-w64-crt/crt/seh_signal_dispatcher.h @@ -13,8 +13,6 @@ #include <signal.h> #include <stdio.h> -EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *); - #if defined(__x86_64__) && !defined(_MSC_VER) && !defined(__SEH__) #pragma pack(push,1) @@ -81,7 +79,7 @@ __mingw_init_ehandler (void) /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ __attribute__((force_align_arg_pointer)) #endif -EXCEPTION_DISPOSITION __cdecl +static EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord, void *EstablisherFrame __attribute__ ((unused)), struct _CONTEXT* ContextRecord, diff --git a/mingw-w64-crt/misc/i386_sse_float_exception_handler.h b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h index 940c88c6aa12..44aca73f3a64 100644 --- a/mingw-w64-crt/misc/i386_sse_float_exception_handler.h +++ b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h @@ -9,7 +9,7 @@ * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_error_handler() which correctly process them. * x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */ -EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(EXCEPTION_RECORD *, PVOID, CONTEXT *, PVOID); +#include "../crt/seh_signal_dispatcher.h" #if defined(__i386__) /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ -- 2.20.1 >From 3d98e14ae169f6d91ef3fcb085742b43f3ed7f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]> Date: Sat, 13 Jun 2026 11:48:35 +0200 Subject: [PATCH 3/3] crt: Rename __mingw_SEH_error_handler to __mingw_SEH_signal_dispatcher This better describe the purpose and logic of that function. Add also description of the function into the comment. --- mingw-w64-crt/crt/crtexe.c | 6 +++--- mingw-w64-crt/crt/seh_signal_dispatcher.h | 7 ++++++- mingw-w64-crt/misc/i386_sse_float_exception_handler.h | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c index 5976fc5e48db..a74adfb8ff84 100644 --- a/mingw-w64-crt/crt/crtexe.c +++ b/mingw-w64-crt/crt/crtexe.c @@ -149,16 +149,16 @@ __attribute__((force_align_arg_pointer)) __declspec(noinline) int __tmainCRTStartup (void) { - /* Registration of SEH error handler __mingw_SEH_error_handler used for + /* Registration of SEH error handler __mingw_SEH_signal_dispatcher used for * delivering SEH exceptions to registered CRT signal handlers. */ #if defined(__i386__) EXCEPTION_REGISTRATION_RECORD exception_record = { .Next = (EXCEPTION_REGISTRATION_RECORD *)__readfsdword (0), - .Handler = (PEXCEPTION_ROUTINE)(INT_PTR)__mingw_SEH_error_handler, + .Handler = (PEXCEPTION_ROUTINE)(INT_PTR)__mingw_SEH_signal_dispatcher, }; __writefsdword (0, (DWORD)&exception_record); /* dynamically register SEH error handler, it is active until manually unregistered */ #elif defined(SEH_INLINE_ASM) - asm volatile (".seh_handler %c0, " ASM_SEH_EXCEPT :: "i" (__mingw_SEH_error_handler)); /* statically register SEH error handler, it is active only in the current function */ + asm volatile (".seh_handler %c0, " ASM_SEH_EXCEPT :: "i" (__mingw_SEH_signal_dispatcher)); /* statically register SEH error handler, it is active only in the current function */ #elif defined(__x86_64__) __mingw_init_ehandler (); /* dynamically register SEH error handler for all functions, it is active until program terminates */ #else diff --git a/mingw-w64-crt/crt/seh_signal_dispatcher.h b/mingw-w64-crt/crt/seh_signal_dispatcher.h index 4b5164321ffa..57a51f01e3fb 100644 --- a/mingw-w64-crt/crt/seh_signal_dispatcher.h +++ b/mingw-w64-crt/crt/seh_signal_dispatcher.h @@ -75,12 +75,17 @@ __mingw_init_ehandler (void) #endif +/* This is SEH exception handler which handles only SEH exceptions for + * C signals and dispatches them to the registered C signal handler. + * Calling the appropriate C signal handler which was registered by the + * CRT signal() function is done by the CRT _XcptFilter() function. + */ #if defined(__i386__) /* We need to make sure that we align the stack to 16 bytes for the sake of SSE */ __attribute__((force_align_arg_pointer)) #endif static EXCEPTION_DISPOSITION __cdecl -__mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord, +__mingw_SEH_signal_dispatcher (struct _EXCEPTION_RECORD* ExceptionRecord, void *EstablisherFrame __attribute__ ((unused)), struct _CONTEXT* ContextRecord, void *DispatcherContext __attribute__ ((unused))) diff --git a/mingw-w64-crt/misc/i386_sse_float_exception_handler.h b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h index 44aca73f3a64..98ebecb2bc0e 100644 --- a/mingw-w64-crt/misc/i386_sse_float_exception_handler.h +++ b/mingw-w64-crt/misc/i386_sse_float_exception_handler.h @@ -6,7 +6,7 @@ /* Functions _beginthread() and _beginthreadex() in 32-bit x86 pre-msvcr100 libraries do not handle STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS SEH exceptions. * These two SEH exceptions are thrown by Windows system for 32-bit x86 processes when SSE floating point exception occurs. - * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_error_handler() which correctly process them. + * So fix the pre-msvcr100 behavior by catching those two exceptions manually and propagating them to __mingw_SEH_signal_dispatcher() which correctly process them. * x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */ #include "../crt/seh_signal_dispatcher.h" @@ -18,7 +18,7 @@ __attribute__((force_align_arg_pointer)) static EXCEPTION_DISPOSITION __cdecl sse_float_exception_handler(EXCEPTION_RECORD *ExceptionRecord, PVOID EstablisherFrame, CONTEXT *ContextRecord, PVOID DispatcherContext) { if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS || ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS) - return __mingw_SEH_error_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + return __mingw_SEH_signal_dispatcher(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); else return ExceptionContinueSearch; } -- 2.20.1
_______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
