2010-08-28 Kai Tietz <kai.tietz@onevision.com>
* crt/crtexe.c: Prepare x64 SEH support.
* crt/crt_handler.c: Correct some stuff and moved
default handler from crtexe.c here.
git-svn-id: svn+ssh://svn.code.sf.net/p/mingw-w64/code/trunk@3444 4407c894-4637-0410-b4f5-ada5f102cad1
diff --git a/mingw-w64-crt/ChangeLog b/mingw-w64-crt/ChangeLog
index 5a6eb97..536e2a1 100644
--- a/mingw-w64-crt/ChangeLog
+++ b/mingw-w64-crt/ChangeLog
@@ -1,3 +1,9 @@
+2010-08-28 Kai Tietz <kai.tietz@onevision.com>
+
+ * crt/crtexe.c: Prepare x64 SEH support.
+ * crt/crt_handler.c: Correct some stuff and moved
+ default handler from crtexe.c here.
+
2010-08-13 Jonathan Yong <jon_y@sourceforge.net>
* lib32/secur32.def: Update from Win7.
diff --git a/mingw-w64-crt/crt/cinitexe.c b/mingw-w64-crt/crt/cinitexe.c
index b69eebe..58e52ab 100644
--- a/mingw-w64-crt/crt/cinitexe.c
+++ b/mingw-w64-crt/crt/cinitexe.c
@@ -1,7 +1,8 @@
#include <stdio.h>
-#include <internal.h>
#include <sect_attribs.h>
+typedef void (__cdecl *_PVFV)(void);
+
_CRTALLOC(".CRT$XIA") _PVFV __xi_a[] = { NULL };
_CRTALLOC(".CRT$XIZ") _PVFV __xi_z[] = { NULL };
_CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = { NULL };
diff --git a/mingw-w64-crt/crt/crt_handler.c b/mingw-w64-crt/crt/crt_handler.c
index 8e47df0..7f75eac 100644
--- a/mingw-w64-crt/crt/crt_handler.c
+++ b/mingw-w64-crt/crt/crt_handler.c
@@ -93,7 +93,7 @@
struct _CONTEXT* ContextRecord __attribute__ ((unused)),
void *DispatcherContext __attribute__ ((unused)))
{
- EXCEPTION_DISPOSITION action = EXCEPTION_CONTINUE_SEARCH;
+ EXCEPTION_DISPOSITION action = ExceptionContinueSearch; /* EXCEPTION_CONTINUE_SEARCH; */
void (*old_handler) (int);
int reset_fpu = 0;
@@ -107,6 +107,101 @@
/* this is undefined if the signal was raised by anything other
than raise (). */
signal (SIGSEGV, SIG_IGN);
+ action = 0; //EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else if (old_handler != SIG_DFL)
+ {
+ /* This means 'old' is a user defined function. Call it */
+ (*old_handler) (SIGSEGV);
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else
+ action = 4; /* EXCEPTION_EXECUTE_HANDLER; */
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ case EXCEPTION_PRIV_INSTRUCTION:
+ /* test if the user has set SIGILL */
+ old_handler = signal (SIGILL, SIG_DFL);
+ if (old_handler == SIG_IGN)
+ {
+ /* this is undefined if the signal was raised by anything other
+ than raise (). */
+ signal (SIGILL, SIG_IGN);
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else if (old_handler != SIG_DFL)
+ {
+ /* This means 'old' is a user defined function. Call it */
+ (*old_handler) (SIGILL);
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else
+ action = 4; /* EXCEPTION_EXECUTE_HANDLER;*/
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_UNDERFLOW:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ reset_fpu = 1;
+ /* fall through. */
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ /* test if the user has set SIGFPE */
+ old_handler = signal (SIGFPE, SIG_DFL);
+ if (old_handler == SIG_IGN)
+ {
+ signal (SIGFPE, SIG_IGN);
+ if (reset_fpu)
+ _fpreset ();
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else if (old_handler != SIG_DFL)
+ {
+ /* This means 'old' is a user defined function. Call it */
+ (*old_handler) (SIGFPE);
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ }
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ case EXCEPTION_FLT_STACK_CHECK:
+ case EXCEPTION_INT_OVERFLOW:
+ case EXCEPTION_INVALID_HANDLE:
+ /*case EXCEPTION_POSSIBLE_DEADLOCK: */
+ action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+ break;
+ default:
+ break;
+ }
+ return action;
+}
+
+#endif
+
+LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
+
+long CALLBACK
+_gnu_exception_handler (EXCEPTION_POINTERS *exception_data);
+
+long CALLBACK
+_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
+{
+ void (*old_handler) (int);
+ long action = EXCEPTION_CONTINUE_SEARCH;
+ int reset_fpu = 0;
+
+ switch (exception_data->ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ /* test if the user has set SIGSEGV */
+ old_handler = signal (SIGSEGV, SIG_DFL);
+ if (old_handler == SIG_IGN)
+ {
+ /* this is undefined if the signal was raised by anything other
+ than raise (). */
+ signal (SIGSEGV, SIG_IGN);
action = EXCEPTION_CONTINUE_EXECUTION;
}
else if (old_handler != SIG_DFL)
@@ -115,9 +210,8 @@
(*old_handler) (SIGSEGV);
action = EXCEPTION_CONTINUE_EXECUTION;
}
- else
- action = EXCEPTION_EXECUTE_HANDLER;
break;
+
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_PRIV_INSTRUCTION:
/* test if the user has set SIGILL */
@@ -135,9 +229,8 @@
(*old_handler) (SIGILL);
action = EXCEPTION_CONTINUE_EXECUTION;
}
- else
- action = EXCEPTION_EXECUTE_HANDLER;
break;
+
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DENORMAL_OPERAND:
@@ -164,6 +257,7 @@
action = EXCEPTION_CONTINUE_EXECUTION;
}
break;
+#ifdef _WIN64
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_STACK_CHECK:
@@ -172,10 +266,12 @@
/*case EXCEPTION_POSSIBLE_DEADLOCK: */
action = EXCEPTION_CONTINUE_EXECUTION;
break;
+#endif
default:
break;
}
+
+ if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
+ action = (*__mingw_oldexcpt_handler)(exception_data);
return action;
}
-
-#endif
diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c
index 802990c..34e71ab 100644
--- a/mingw-w64-crt/crt/crtexe.c
+++ b/mingw-w64-crt/crt/crtexe.c
@@ -85,10 +85,10 @@
static int managedapp;
static int has_cctor = 0;
static _startupinfo startinfo;
-static LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
+extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
extern void _pei386_runtime_relocator (void);
-static long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
+long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
#ifdef WPRFLAG
static void duplicate_ppstrings (int ac, wchar_t ***av);
#else
@@ -150,9 +150,20 @@
int WinMainCRTStartup (void)
{
+ int ret = 255;
+#ifdef __SEH__
+ asm ("\t.l_startw:\n"
+ "\t.seh_handler __C_specific_handler, @except\n"
+ "\t.seh_scope .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
+ );
+#endif
mingw_app_type = 1;
__security_init_cookie ();
- return __tmainCRTStartup ();
+ ret = __tmainCRTStartup ();
+#ifdef __SEH__
+ asm ("\t.l_endw: nop\n");
+#endif
+ return ret;
}
int mainCRTStartup (void);
@@ -163,9 +174,20 @@
int mainCRTStartup (void)
{
+ int ret = 255;
+#ifdef __SEH__
+ asm ("\t.l_start:\n"
+ "\t.seh_handler __C_specific_handler, @except\n"
+ "\t.seh_scope .l_start, .l_end, _gnu_exception_handler, .l_end\n"
+ );
+#endif
mingw_app_type = 0;
__security_init_cookie ();
- return __tmainCRTStartup ();
+ ret = __tmainCRTStartup ();
+#ifdef __SEH__
+ asm ("\t.l_end: nop\n");
+#endif
+ return ret;
}
static
@@ -317,97 +339,6 @@
return 0;
}
-static long CALLBACK
-_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
-{
- void (*old_handler) (int);
- long action = EXCEPTION_CONTINUE_SEARCH;
- int reset_fpu = 0;
-
- switch (exception_data->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_ACCESS_VIOLATION:
- /* test if the user has set SIGSEGV */
- old_handler = signal (SIGSEGV, SIG_DFL);
- if (old_handler == SIG_IGN)
- {
- /* this is undefined if the signal was raised by anything other
- than raise (). */
- signal (SIGSEGV, SIG_IGN);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGSEGV);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- break;
-
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- case EXCEPTION_PRIV_INSTRUCTION:
- /* test if the user has set SIGILL */
- old_handler = signal (SIGILL, SIG_DFL);
- if (old_handler == SIG_IGN)
- {
- /* this is undefined if the signal was raised by anything other
- than raise (). */
- signal (SIGILL, SIG_IGN);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGILL);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- break;
-
- case EXCEPTION_FLT_INVALID_OPERATION:
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- case EXCEPTION_FLT_OVERFLOW:
- case EXCEPTION_FLT_UNDERFLOW:
- case EXCEPTION_FLT_INEXACT_RESULT:
- reset_fpu = 1;
- /* fall through. */
-
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- /* test if the user has set SIGFPE */
- old_handler = signal (SIGFPE, SIG_DFL);
- if (old_handler == SIG_IGN)
- {
- signal (SIGFPE, SIG_IGN);
- if (reset_fpu)
- _fpreset ();
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGFPE);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- break;
-#ifdef _WIN64
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- case EXCEPTION_FLT_STACK_CHECK:
- case EXCEPTION_INT_OVERFLOW:
- case EXCEPTION_INVALID_HANDLE:
- /*case EXCEPTION_POSSIBLE_DEADLOCK: */
- action = EXCEPTION_CONTINUE_EXECUTION;
- break;
-#endif
- default:
- break;
- }
-
- if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
- action = (*__mingw_oldexcpt_handler)(exception_data);
- return action;
-}
-
#ifdef WPRFLAG
static size_t wbytelen(const wchar_t *p)
{