2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
18 #if defined (_WIN64) && defined (__ia64__)
19 #error FIXME: Unsupported __ImageBase implementation.
22 #define __ImageBase __MINGW_LSYMBOL(_image_base__)
24 /* This symbol is defined by the linker. */
25 extern IMAGE_DOS_HEADER __ImageBase
;
29 typedef struct _UNWIND_INFO
{
32 BYTE CountOfUnwindCodes
;
33 BYTE FrameRegisterAndOffset
;
34 ULONG AddressOfExceptionHandler
;
35 } UNWIND_INFO
,*PUNWIND_INFO
;
38 PIMAGE_SECTION_HEADER
_FindPESectionByName (const char *);
39 PIMAGE_SECTION_HEADER
_FindPESectionExec (size_t);
40 PBYTE
_GetPEImageBase (void);
42 int __mingw_init_ehandler (void);
43 extern void _fpreset (void);
45 #if defined(_WIN64) && !defined(_MSC_VER)
46 EXCEPTION_DISPOSITION
__mingw_SEH_error_handler(struct _EXCEPTION_RECORD
*, void *, struct _CONTEXT
*, void *);
48 #define MAX_PDATA_ENTRIES 32
49 static RUNTIME_FUNCTION emu_pdata
[MAX_PDATA_ENTRIES
];
50 static UNWIND_INFO emu_xdata
[MAX_PDATA_ENTRIES
];
53 __mingw_init_ehandler (void)
55 static int was_here
= 0;
57 PIMAGE_SECTION_HEADER pSec
;
58 PBYTE _ImageBase
= _GetPEImageBase ();
60 if (was_here
|| !_ImageBase
)
63 if (_FindPESectionByName (".pdata") != NULL
)
66 /* Allocate # of e tables and entries. */
67 memset (emu_pdata
, 0, sizeof (RUNTIME_FUNCTION
) * MAX_PDATA_ENTRIES
);
68 memset (emu_xdata
, 0, sizeof (UNWIND_INFO
) * MAX_PDATA_ENTRIES
);
71 /* Fill tables and entries. */
72 while (e
< MAX_PDATA_ENTRIES
&& (pSec
= _FindPESectionExec (e
)) != NULL
)
74 emu_xdata
[e
].VersionAndFlags
= 9; /* UNW_FLAG_EHANDLER | UNW_VERSION */
75 emu_xdata
[e
].AddressOfExceptionHandler
=
76 (DWORD
)(size_t) ((LPBYTE
)__mingw_SEH_error_handler
- _ImageBase
);
77 emu_pdata
[e
].BeginAddress
= pSec
->VirtualAddress
;
78 emu_pdata
[e
].EndAddress
= pSec
->VirtualAddress
+ pSec
->Misc
.VirtualSize
;
79 emu_pdata
[e
].UnwindData
=
80 (DWORD
)(size_t)((LPBYTE
)&emu_xdata
[e
] - _ImageBase
);
84 if (!e
|| e
> MAX_PDATA_ENTRIES
)
87 /* RtlAddFunctionTable. */
89 RtlAddFunctionTable (emu_pdata
, e
, (DWORD64
)_ImageBase
);
93 extern void _fpreset (void);
96 __mingw_SEH_error_handler (struct _EXCEPTION_RECORD
* ExceptionRecord
,
97 void *EstablisherFrame
__attribute__ ((unused
)),
98 struct _CONTEXT
* ContextRecord
__attribute__ ((unused
)),
99 void *DispatcherContext
__attribute__ ((unused
)))
101 EXCEPTION_DISPOSITION action
= ExceptionContinueSearch
; /* EXCEPTION_CONTINUE_SEARCH; */
102 void (*old_handler
) (int);
105 switch (ExceptionRecord
->ExceptionCode
)
107 case EXCEPTION_ACCESS_VIOLATION
:
108 /* test if the user has set SIGSEGV */
109 old_handler
= signal (SIGSEGV
, SIG_DFL
);
110 if (old_handler
== SIG_IGN
)
112 /* this is undefined if the signal was raised by anything other
114 signal (SIGSEGV
, SIG_IGN
);
115 action
= 0; //EXCEPTION_CONTINUE_EXECUTION;
117 else if (old_handler
!= SIG_DFL
)
119 /* This means 'old' is a user defined function. Call it */
120 (*old_handler
) (SIGSEGV
);
121 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
124 action
= 4; /* EXCEPTION_EXECUTE_HANDLER; */
126 case EXCEPTION_ILLEGAL_INSTRUCTION
:
127 case EXCEPTION_PRIV_INSTRUCTION
:
128 /* test if the user has set SIGILL */
129 old_handler
= signal (SIGILL
, SIG_DFL
);
130 if (old_handler
== SIG_IGN
)
132 /* this is undefined if the signal was raised by anything other
134 signal (SIGILL
, SIG_IGN
);
135 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
137 else if (old_handler
!= SIG_DFL
)
139 /* This means 'old' is a user defined function. Call it */
140 (*old_handler
) (SIGILL
);
141 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
144 action
= 4; /* EXCEPTION_EXECUTE_HANDLER;*/
146 case EXCEPTION_FLT_INVALID_OPERATION
:
147 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
148 case EXCEPTION_FLT_DENORMAL_OPERAND
:
149 case EXCEPTION_FLT_OVERFLOW
:
150 case EXCEPTION_FLT_UNDERFLOW
:
151 case EXCEPTION_FLT_INEXACT_RESULT
:
155 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
156 /* test if the user has set SIGFPE */
157 old_handler
= signal (SIGFPE
, SIG_DFL
);
158 if (old_handler
== SIG_IGN
)
160 signal (SIGFPE
, SIG_IGN
);
163 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
165 else if (old_handler
!= SIG_DFL
)
167 /* This means 'old' is a user defined function. Call it */
168 (*old_handler
) (SIGFPE
);
169 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
172 case EXCEPTION_DATATYPE_MISALIGNMENT
:
173 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
174 case EXCEPTION_FLT_STACK_CHECK
:
175 case EXCEPTION_INT_OVERFLOW
:
176 case EXCEPTION_INVALID_HANDLE
:
177 /*case EXCEPTION_POSSIBLE_DEADLOCK: */
178 action
= 0; // EXCEPTION_CONTINUE_EXECUTION;
188 LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler
= NULL
;
191 _gnu_exception_handler (EXCEPTION_POINTERS
*exception_data
);
193 #define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C' | (1U << 29))
196 _gnu_exception_handler (EXCEPTION_POINTERS
*exception_data
)
198 void (*old_handler
) (int);
199 long action
= EXCEPTION_CONTINUE_SEARCH
;
203 if ((exception_data
->ExceptionRecord
->ExceptionCode
& 0x20ffffff) == GCC_MAGIC
)
205 if ((exception_data
->ExceptionRecord
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
) == 0)
206 return EXCEPTION_CONTINUE_EXECUTION
;
210 switch (exception_data
->ExceptionRecord
->ExceptionCode
)
212 case EXCEPTION_ACCESS_VIOLATION
:
213 /* test if the user has set SIGSEGV */
214 old_handler
= signal (SIGSEGV
, SIG_DFL
);
215 if (old_handler
== SIG_IGN
)
217 /* this is undefined if the signal was raised by anything other
219 signal (SIGSEGV
, SIG_IGN
);
220 action
= EXCEPTION_CONTINUE_EXECUTION
;
222 else if (old_handler
!= SIG_DFL
)
224 /* This means 'old' is a user defined function. Call it */
225 (*old_handler
) (SIGSEGV
);
226 action
= EXCEPTION_CONTINUE_EXECUTION
;
230 case EXCEPTION_ILLEGAL_INSTRUCTION
:
231 case EXCEPTION_PRIV_INSTRUCTION
:
232 /* test if the user has set SIGILL */
233 old_handler
= signal (SIGILL
, SIG_DFL
);
234 if (old_handler
== SIG_IGN
)
236 /* this is undefined if the signal was raised by anything other
238 signal (SIGILL
, SIG_IGN
);
239 action
= EXCEPTION_CONTINUE_EXECUTION
;
241 else if (old_handler
!= SIG_DFL
)
243 /* This means 'old' is a user defined function. Call it */
244 (*old_handler
) (SIGILL
);
245 action
= EXCEPTION_CONTINUE_EXECUTION
;
249 case EXCEPTION_FLT_INVALID_OPERATION
:
250 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
251 case EXCEPTION_FLT_DENORMAL_OPERAND
:
252 case EXCEPTION_FLT_OVERFLOW
:
253 case EXCEPTION_FLT_UNDERFLOW
:
254 case EXCEPTION_FLT_INEXACT_RESULT
:
258 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
259 /* test if the user has set SIGFPE */
260 old_handler
= signal (SIGFPE
, SIG_DFL
);
261 if (old_handler
== SIG_IGN
)
263 signal (SIGFPE
, SIG_IGN
);
266 action
= EXCEPTION_CONTINUE_EXECUTION
;
268 else if (old_handler
!= SIG_DFL
)
270 /* This means 'old' is a user defined function. Call it */
271 (*old_handler
) (SIGFPE
);
272 action
= EXCEPTION_CONTINUE_EXECUTION
;
276 case EXCEPTION_DATATYPE_MISALIGNMENT
:
277 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
278 case EXCEPTION_FLT_STACK_CHECK
:
279 case EXCEPTION_INT_OVERFLOW
:
280 case EXCEPTION_INVALID_HANDLE
:
281 /*case EXCEPTION_POSSIBLE_DEADLOCK: */
282 action
= EXCEPTION_CONTINUE_EXECUTION
;
289 if (action
== EXCEPTION_CONTINUE_SEARCH
&& __mingw_oldexcpt_handler
)
290 action
= (*__mingw_oldexcpt_handler
)(exception_data
);