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

Reply via email to