On Friday 12 June 2026 09:52:56 Pali Rohár wrote:
> On Friday 12 June 2026 10:22:15 Martin Storsjö wrote:
> > On Fri, 12 Jun 2026, LIU Hao wrote:
> > 
> > > 在 2026-6-12 01:57, Evgeny Karpov 写道:
> > > > On 11 Jun 2026, Pali R. wrote:
> > > > > Could you enable the ifdef branch which calls __mingw_init_ehandler?
> > > > > It would be needed to enable it also in crt_handler.c file.
> > > > 
> > > > It should be possible, however it should be sufficient to add this 
> > > > change
> > > > as a temporary workaround.
> > > > 
> > > > + #elif defined(__aarch64__) && !defined(__clang__)
> > > > +    /* __SEH__ is not implemented yet for aarch64-w64-mingw32 GCC
> > > > target. */
> > > I understand that SEH is not currently implemented in GNU toolchains for
> > > aarch64-w64-mingw32.
> > > 
> > > Since the proposed change is only 'a temporary workaround', I suggest
> > > you put it in your workflows. If this change was committed to mingw-w64,
> > > then once you have a fully operational toolchain in the future, it would
> > > be mingw-w64 that would seem broken.
> > 
> > FWIW, I think it could be entirely reasonable to have cases with "#if
> > defined(__SEH__)" around such cases, where applicable, to allow building
> > without SEH on such architectures.
> > 
> > Even with llvm-mingw, the aarch64 target didn't use SEH, but DWARF unwind
> > info, for the first couple years, until LLVM (and libunwind) supported SEH
> > on aarch64. And for 32 bit ARM, it took yet another couple years before that
> > could be switched to SEH (as late as in 2022).
> > 
> > It's easy to tweak a from-scratch build of llvm-mingw to use these different
> > unwind info formats, by adding e.g. a "-fdwarf-exceptions" in
> > "wrappers/aarch64-w64-windows-gnu.cfg" - just like you can configure a build
> > of GCC to use either SJLJ, DWARF or SEH. (SEH is obviously the default on
> > x86_64 these days, but I do remember seeing e.g. Qt being built with a SJLJ
> > x86_64 toolchain for quite long after SEH being generally usable - same with
> > e.g. distro shipped compilers.)
> > 
> > For upstream mingw-w64, we probably can't commit to continuously testing and
> > maintaining that all these build configurations work (that'd be a pretty bad
> > extra combinatorial explosion), but I think it'd be fair to accept patches
> > to fix it, if someone wants to contribute it.
> 
> I will look at it. Just give me some time to understand how that
> __mingw_init_ehandler needs to differ between architectures.

I was looking at the current amd64 implementation of the __mingw_init_ehandler
and after doing lot of experiments I figured out that it is not working
correctly. Everything which I wrote below is for this amd64. I have not
looked at arm64 yet.

For testing purposes it is not required to recompile gcc. gcc has flag
-fno-asynchronous-unwind-tables which turn of generating of .pdata and
.xdata sections used by the SEH and RtlUnwind. When it is specified then
the __SEH__ macro is not defined anymore, so it can be easily recompiled
the mingw-w64 sources without the .pdata/.xdata support.

What is __mingw_init_ehandler doing is that it registers exception
handler for every single instruction in the PE image and this exception
handler is called when SEH is thrown.

This is quite wrong as SEH exceptions needs to be propagated to the
caller (for example some parent function from other DLL library which
called us) wants to catch that SEH exception and not to make it fatal.

There is missing unregistration when the module (DLL library) is being
unloaded. Probably this could have an side effect if some other module
is loaded at runtime later at the same location then crash could occur.

Also for correct propagation is needed to have unwind code table. If the
stack frame is set by every function it should be relatively easily to
generate backtrace. But if -fomit-frame-pointer is used then it mostly
would not work. I saw that gcc lot of times let %rbp as-is from parent
so propagating should work (just the intermediate function without frame
pointer would be hidden). Moreover gcc has parameter -ffixed-rbp which
should ensure that rbp is either used as frame pointer or preserved (and
not used for some temporary variable).

For DLL modules, the registration of exception handler should not be
called at all. Exceptions and converting them to C signals is done
exclusively by the handler in main entrypoint of main exe module.

So based on this I'm proposing the following changes:
- completely remove __mingw_init_ehandler and replace by new code
- register unwind code for standard prologue (push %rbp; mov %rsp %rbp)
  for all executable code in the module (for both exe and dll builds)
- unregister unwind code when unloading module (needed for dll builds)
- register exception handler "__mingw_SEH_error_handler" just for the
  __tmainCRTStartup function in exe builds (nothing for dll builds)
- inside __tmainCRTStartup force compiler to generate frame pointer
  (so any code which throws exception can via unwind code go back to
  entry point)
- adjust callbacks which are being passed to CRT DLL functions to also
  have own frame pointer

All runtime registration and unregistration has to be done via
RtlAddFunctionTable and RtlDeleteFunctionTable

I have done these changes and they fixed t_sigfpe.c test. Changes are in
the attachment. I have not done exhausting testing, so there may be some
other new issues.

Similar thing could be done for arm32 and arm64 and this could address
the main issue that mingw-w64 does not work with gcc without SEH.

I would like to point out that either -fno-omit-frame-pointer flag or
-ffixed-rbp flag should be used for compiling applications when gcc does
not have enabled SEH support. Otherwise correct propagation does not
have to work.

Please let me know what do you think about it. If I should continue on
this direction and create final version of this change. Or this is wrong
direction and something different should be done.

> > One probably can't expect all the corner cases around unwind etc to work
> > with the same quality of implementation as with SEH now, but I would want
> > such a toolchain to "generally work" at least.
> > 
> > // Martin
diff --git a/mingw-w64-crt/crt/crt_handler.c b/mingw-w64-crt/crt/crt_handler.c
index 191c2da65751..c484e8e57a8c 100644
--- a/mingw-w64-crt/crt/crt_handler.c
+++ b/mingw-w64-crt/crt/crt_handler.c
@@ -6,77 +6,10 @@
 
 #include <windows.h>
 #include <excpt.h>
-#include <string.h>
 #include <stdlib.h>
-#include <malloc.h>
-#include <memory.h>
-#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)
-typedef struct _UNWIND_INFO {
-  BYTE Version:3;
-  BYTE Flags:5;
-  BYTE PrologSize;
-  BYTE CountOfUnwindCodes;
-  BYTE FrameRegisterAndOffset;
-  ULONG AddressOfExceptionHandler;
-} UNWIND_INFO,*PUNWIND_INFO;
-#pragma pack(pop)
-
-PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
-PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
-PBYTE _GetPEImageBase (void);
-
-#define MAX_PDATA_ENTRIES 32
-static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES];
-static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES];
-
-int __mingw_init_ehandler (void);
-int
-__mingw_init_ehandler (void)
-{
-  static int was_here = 0;
-  size_t e = 0;
-  PIMAGE_SECTION_HEADER pSec;
-  PBYTE _ImageBase = _GetPEImageBase ();
-  
-  if (was_here || !_ImageBase)
-    return was_here;
-  was_here = 1;
-  if (_FindPESectionByName (".pdata") != NULL)
-    return 1;
-
-  e = 0;
-  /* Fill tables and entries.  */
-  while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL)
-    {
-      emu_xdata[e].Version = 1;
-      emu_xdata[e].Flags = UNW_FLAG_EHANDLER;
-      emu_xdata[e].AddressOfExceptionHandler =
-	(DWORD)(size_t) ((LPBYTE)__mingw_SEH_error_handler - _ImageBase);
-      emu_pdata[e].BeginAddress = pSec->VirtualAddress;
-      emu_pdata[e].EndAddress = pSec->VirtualAddress + pSec->Misc.VirtualSize;
-      emu_pdata[e].UnwindData =
-	(DWORD)(size_t)((LPBYTE)&emu_xdata[e] - _ImageBase);
-      ++e;
-    }
-#ifdef _DEBUG_CRT
-  if (!e || e > MAX_PDATA_ENTRIES)
-    abort ();
-#endif
-  /* RtlAddFunctionTable.  */
-  if (e != 0)
-    RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase);
-  return 1;
-}
-
-#endif
-
 #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))
diff --git a/mingw-w64-crt/crt/crtdll.c b/mingw-w64-crt/crt/crtdll.c
index 18e831ef9525..a8817bfe6489 100644
--- a/mingw-w64-crt/crt/crtdll.c
+++ b/mingw-w64-crt/crt/crtdll.c
@@ -17,9 +17,14 @@
 #include <sect_attribs.h>
 #include <locale.h>
 
-#if defined(__x86_64__) && !defined(__SEH__)
-extern int __mingw_init_ehandler (void);
+#if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7)
+#define SEH_INLINE_ASM
 #endif
+
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+#include "runtime_seh.h"
+#endif
+
 extern void __main ();
 extern void _pei386_runtime_relocator (void);
 extern _PIFV __xi_a[];
@@ -72,9 +77,6 @@ WINBOOL WINAPI _CRT_INIT (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 	  __native_startup_state = __initializing;
 	  
 	  _pei386_runtime_relocator ();
-#if defined(__x86_64__) && !defined(__SEH__)
-	  __mingw_init_ehandler ();
-#endif
 	  ret = _initialize_onexit_table (&atexit_table);
 	  if (ret != 0)
 	    goto i__leave;
@@ -146,6 +148,14 @@ DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 {
   WINBOOL retcode = TRUE;
 
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+  if (dwReason == DLL_PROCESS_ATTACH)
+    {
+      if (!register_runtime_image_unwind_info ()) /* dynamically register propagation of SEH exceptions for the whole image */
+        return FALSE;
+    }
+#endif
+
   if (dwReason == DLL_PROCESS_ATTACH)
     __mingw_app_type = 0;
 
@@ -174,6 +184,14 @@ DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
     }
 i__leave:
   __native_dllmain_reason = UINT_MAX;
+
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+  if (dwReason == DLL_PROCESS_DETACH || (dwReason == DLL_PROCESS_ATTACH && !retcode))
+    {
+      unregister_runtime_image_unwind_info ();
+    }
+#endif
+
   return retcode ;
 }
 
diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c
index 86c3842f6162..c17c5b66cfad 100644
--- a/mingw-w64-crt/crt/crtexe.c
+++ b/mingw-w64-crt/crt/crtexe.c
@@ -33,6 +33,10 @@
 #endif
 #endif
 
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+#include "runtime_seh.h"
+#endif
+
 extern IMAGE_DOS_HEADER __ImageBase;
 
 int *__cdecl __p__commode(void);
@@ -67,9 +71,6 @@ 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
 static int duplicate_ppstrings (int ac, _TCHAR ***av);
 
 extern int _MINGW_INSTALL_DEBUG_MATHERR;
@@ -146,12 +147,19 @@ int mainCRTStartup (void)
   return __tmainCRTStartup ();
 }
 
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+static int __tmainCRTStartup_real(void);
+static const char __tmainCRTStartup_end;
+#endif
 static
 #if defined(__i386__) || defined(_X86_)
 /* We need to make sure that we align the stack to 16 bytes for the sake of SSE
    opts in main or in functions called from main.  */
 __attribute__((force_align_arg_pointer))
 #endif
+#if defined(__x86_64__) && !defined(SEH_INLINE_ASM)
+__attribute__((section(".text.__tmainCRTStartup$A")))
+#endif
 __declspec(noinline) int
 __tmainCRTStartup (void)
 {
@@ -166,7 +174,19 @@ __tmainCRTStartup (void)
 #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 */
 #elif defined(__x86_64__)
-    __mingw_init_ehandler (); /* dynamically register SEH error handler for all functions, it is active until program terminates */
+    asm volatile ("" :: "r" (__builtin_frame_address (0))); /* force usage of the standard prolog with frame pointer */
+    if (!register_runtime_function_exception_handler ((uintptr_t)&__tmainCRTStartup, (uintptr_t)&__tmainCRTStartup_end, __mingw_SEH_error_handler)) /* dynamically register SEH error handler, it is active only in the specified function */
+      _amsg_exit (22); /* _RT_NONCONT_TXT */
+    if (!register_runtime_image_unwind_info ()) /* dynamically register propagation of SEH exceptions for the whole image */
+      _amsg_exit (22); /* _RT_NONCONT_TXT */
+    int ret = __tmainCRTStartup_real (); /* call the real __tmainCRTStartup with a new frame */
+    asm volatile ("nop"); /* required by SEH unwind for __tmainCRTStartup_real */
+    return ret;
+}
+__attribute__((section(".text.__tmainCRTStartup$Z"))) static const char __tmainCRTStartup_end = 0;
+static __declspec(noinline) int __tmainCRTStartup_real (void)
+{
+    asm volatile ("" :: "r" (__builtin_frame_address (0))); /* force usage of the standard prolog with frame pointer */
 #else
 #error unsupported platform
 #endif
diff --git a/mingw-w64-crt/crt/runtime_seh.h b/mingw-w64-crt/crt/runtime_seh.h
new file mode 100644
index 000000000000..21af9cb971b3
--- /dev/null
+++ b/mingw-w64-crt/crt/runtime_seh.h
@@ -0,0 +1,204 @@
+/**
+ * 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>
+
+#if defined(__x86_64__)
+
+/* https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#unwind-data-definitions-in-c */
+
+typedef enum {
+  UWOP_PUSH_NONVOL = 0, /* info == register number */
+  UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */
+  UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */
+  UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
+  UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */
+  UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
+  UWOP_SAVE_XMM,
+  UWOP_SAVE_XMM_FAR,
+  UWOP_SAVE_XMM128,     /* info == XMM reg number, offset in next slot */
+  UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
+  UWOP_PUSH_MACHFRAME,  /* info == 0: no error-code, 1: error-code */
+} UNWIND_CODE_OPS;
+
+typedef enum {
+  UWREG_RAX = 0,
+  UWREG_RCX,
+  UWREG_RDX,
+  UWREG_RBX,
+  UWREG_RSP,
+  UWREG_RBP,
+  UWREG_RSI,
+  UWREG_RDI,
+  UWREG_R8,
+  UWREG_R9,
+  UWREG_R10,
+  UWREG_R11,
+  UWREG_R12,
+  UWREG_R13,
+  UWREG_R14,
+  UWREG_R15,
+  UWREG_XMM0,
+  UWREG_XMM1,
+  UWREG_XMM2,
+  UWREG_XMM3,
+  UWREG_XMM4,
+  UWREG_XMM5,
+  UWREG_XXM6,
+  UWREG_XMM7,
+  UWREG_XMM8,
+  UWREG_XMM9,
+  UWREG_XMM10,
+  UWREG_XMM11,
+  UWREG_XMM12,
+  UWREG_XMM13,
+  UWREG_XXM14,
+  UWREG_XMM15,
+} UNWIND_REGS;
+
+typedef struct {
+  BYTE CodeOffset;
+  BYTE UnwindOp:4;
+  BYTE OpInfo:4;
+} UNWIND_CODE;
+
+#define UNWIND_INFO(unwind_codes_count, exception_data_count) struct __attribute__((aligned(4))) { \
+  BYTE Version:3; \
+  BYTE Flags:5; \
+  BYTE SizeOfProlog; \
+  BYTE CountOfCodes; /* must match unwind_codes_count */ \
+  BYTE FrameRegister:4; \
+  BYTE FrameOffset:4; \
+  UNWIND_CODE UnwindCode[unwind_codes_count]; \
+  /* if unwind_codes_count is odd number then there is an automatic padding */ \
+  union __attribute__((aligned(4))) { \
+    ULONG ExceptionHandler; /* when Flags do not contain UNW_FLAG_CHAININFO */ \
+    ULONG FunctionEntry; /* when Flags contains UNW_FLAG_CHAININFO */ \
+  }; \
+  ULONG ExceptionData[exception_data_count]; \
+}
+
+/* Define unwind code for standard prolog which uses frame pointers via rbp.
+ * This makes the RtlUnwind() function to work and allows to traverse stack.
+ *
+ * As the one unwind code is defined for the whole image, it means that it
+ * does not represent one function and so there is no real function prolog.
+ * Therefore SizeOfProlog is 0 and all CodeOffset are also zeros.
+ *
+ * Functions which do not create its own frame pointer on stack (for example
+ * when compiling with -fomit-frame-pointer) are hidden during unwinding.
+ * Startup code for mingw-w64 manually ensures that frame pointers via rbp
+ * are properly maintained. Rest is up to the application. If application
+ * is compiled with -fomit-frame-pointer then it is expected that rbp value
+ * is not damaged or used for some intermediate operations. This can be
+ * achieved by additional application compile flag -ffixed-rbp.
+ */
+#define UNWIND_CODE_TABLE_COUNT 2
+#define UNWIND_CODE_TABLE { \
+    { .CodeOffset = 0, .UnwindOp = UWOP_SET_FPREG,   .OpInfo = 0         }, \
+    { .CodeOffset = 0, .UnwindOp = UWOP_PUSH_NONVOL, .OpInfo = UWREG_RBP }, \
+}
+
+#else
+
+#error unsupported platform
+
+#endif
+
+
+
+#if defined(__x86_64__)
+static const UNWIND_INFO(UNWIND_CODE_TABLE_COUNT, 0) all_functions_unwind_xdata = {
+  .Version = 1,
+  .CountOfCodes = UNWIND_CODE_TABLE_COUNT,
+  .FrameRegister = UWREG_RBP,
+  .UnwindCode = UNWIND_CODE_TABLE,
+};
+#else
+#error unsupported platform
+#endif
+
+static RUNTIME_FUNCTION all_functions_pdata = {
+  .BeginAddress = 0,
+#if defined(__x86_64__)
+  .EndAddress = -1, /* filled at runtime */
+#endif
+  .UnwindData = -1, /* filled at runtime */
+};
+
+/* Registration of unwind info for the whole image must be done _after_
+ * registering unwind info for separate functions or registering SEH handlers.
+ * It is because this registration covers whole image and covers also ranges of
+ * other functions. RtlUnwind() searches for unwind info first in executable
+ * image and then in runtime tables in order in which they were registered.
+ */
+static inline __attribute__((always_inline)) int register_runtime_image_unwind_info(void)
+{
+  /* All addresses in UNWIND_INFO and RUNTIME_FUNCTION are relative the image base. */
+  extern IMAGE_DOS_HEADER __ImageBase;
+#if defined(__x86_64__)
+  all_functions_pdata.EndAddress = ((IMAGE_NT_HEADERS*)((BYTE*)&__ImageBase + __ImageBase.e_lfanew))->OptionalHeader.SizeOfImage;
+#endif
+  all_functions_pdata.UnwindData = (uintptr_t)&all_functions_unwind_xdata - (uintptr_t)&__ImageBase;
+  return RtlAddFunctionTable(&all_functions_pdata, 1, (uintptr_t)&__ImageBase);
+}
+
+/* It is required to unregister unwind info when unloading the image.
+ * This is mostly for cases when DLL library is being unloaded.
+ */
+static inline __attribute__((always_inline)) void unregister_runtime_image_unwind_info(void)
+{
+  RtlDeleteFunctionTable(&all_functions_pdata);
+}
+
+
+
+#if defined(__x86_64__)
+static UNWIND_INFO(UNWIND_CODE_TABLE_COUNT, 0) function_unwind_xdata = {
+  .Version = 1,
+  .Flags = UNW_FLAG_EHANDLER,
+  .CountOfCodes = UNWIND_CODE_TABLE_COUNT,
+  .FrameRegister = UWREG_RBP,
+  .UnwindCode = UNWIND_CODE_TABLE,
+  .ExceptionHandler = -1, /* filled at runtime */
+};
+#else
+#error unsupported platform
+#endif
+
+static RUNTIME_FUNCTION function_pdata = {
+  .BeginAddress = -1, /* filled at runtime */
+#if defined(__x86_64__)
+  .EndAddress = -1, /* filled at runtime */
+#endif
+  .UnwindData = -1, /* filled at runtime */
+};
+
+/* Function for which is being registered SEH exception handler needs to use
+ * standard prolog and also direct child functions need to use standard prolog.
+ * Registration of SEH handler for particular function needs to be done before
+ * calling register_runtime_unwind_info(). Otherwise it would have no effect.
+ * Also please note that without the followup register_runtime_unwind_info()
+ * call, the SEH exception would not be propagated to SEH handler because
+ * RtlUnwind() would not be able to unwind stack and find this SEH handler.
+ */
+static inline __attribute__((always_inline)) int register_runtime_function_exception_handler(uintptr_t function_begin, uintptr_t function_end, PEXCEPTION_ROUTINE exception_handler)
+{
+  /* All addresses in UNWIND_INFO and RUNTIME_FUNCTION are relative the image base. */
+  extern IMAGE_DOS_HEADER __ImageBase;
+  function_unwind_xdata.ExceptionHandler = (uintptr_t)exception_handler - (uintptr_t)&__ImageBase;
+  function_pdata.BeginAddress = function_begin - (uintptr_t)&__ImageBase;
+#if defined(__x86_64__)
+  function_pdata.EndAddress = function_end - (uintptr_t)&__ImageBase;
+#endif
+  function_pdata.UnwindData = (uintptr_t)&function_unwind_xdata - (uintptr_t)&__ImageBase;
+  return RtlAddFunctionTable(&function_pdata, 1, (uintptr_t)&__ImageBase);
+}
+
+static inline __attribute__((always_inline)) void unregister_runtime_function_exception_handler(void)
+{
+  RtlDeleteFunctionTable(&function_pdata);
+}
diff --git a/mingw-w64-crt/testcases/t_sigfpe.c b/mingw-w64-crt/testcases/t_sigfpe.c
index 0c30621052c1..bc9ab024568c 100644
--- a/mingw-w64-crt/testcases/t_sigfpe.c
+++ b/mingw-w64-crt/testcases/t_sigfpe.c
@@ -1162,8 +1162,15 @@ __attribute__((force_align_arg_pointer))
 #endif
 static unsigned __stdcall test_from_beginthreadex(void *arg)
 {
+#if !defined(__i386__) && !defined(__SEH__)
+  asm volatile ("" :: "r" (__builtin_frame_address(0))); /* force usage of the standard prolog with frame pointer */
+#endif
   (void)arg;
-  return test();
+  int ret = test();
+#if !defined(__i386__) && !defined(__SEH__)
+  asm volatile (""); /* prevent tail optimization */
+#endif
+  return ret;
 }
 
 #if defined(__i386__)
@@ -1180,6 +1187,9 @@ static void __cdecl test_from_beginthread(void *arg)
    * The thread handle is used by _beginthread()'s caller which will close it.
    * So the only safe option is to exit this tread via WinAPI ExitThread() function.
    */
+#if !defined(__i386__) && !defined(__SEH__)
+  asm volatile ("" :: "r" (__builtin_frame_address(0))); /* force usage of the standard prolog with frame pointer */
+#endif
   (void)arg;
   ExitThread(test());
 }
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to