1 /** 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. 5 */ 6 7 #include <excpt.h> 8 #include <string.h> 9 #include <stdlib.h> 10 #include <malloc.h> 11 #include <memory.h> 12 #include <signal.h> 13 #include <stdio.h> 14 #define _NTSYSTEM_ 15 #include <windef.h> 16 #include <winbase.h> 17 18 #if defined (_WIN64) && defined (__ia64__) 19 #error FIXME: Unsupported __ImageBase implementation. 20 #else 21 #ifndef _MSC_VER 22 #define __ImageBase __MINGW_LSYMBOL(_image_base__) 23 #endif 24 /* This symbol is defined by the linker. */ 25 extern IMAGE_DOS_HEADER __ImageBase; 26 #endif 27 28 #pragma pack(push,1) 29 typedef struct _UNWIND_INFO { 30 BYTE VersionAndFlags; 31 BYTE PrologSize; 32 BYTE CountOfUnwindCodes; 33 BYTE FrameRegisterAndOffset; 34 ULONG AddressOfExceptionHandler; 35 } UNWIND_INFO,*PUNWIND_INFO; 36 #pragma pack(pop) 37 38 PIMAGE_SECTION_HEADER _FindPESectionByName (const char *); 39 PIMAGE_SECTION_HEADER _FindPESectionExec (size_t); 40 PBYTE _GetPEImageBase (void); 41 42 int __mingw_init_ehandler (void); 43 extern void __cdecl _fpreset (void); 44 45 #if defined(_WIN64) && !defined(_MSC_VER) 46 EXCEPTION_DISPOSITION __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *); 47 48 #define MAX_PDATA_ENTRIES 32 49 static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES]; 50 static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES]; 51 52 int 53 __mingw_init_ehandler (void) 54 { 55 static int was_here = 0; 56 size_t e = 0; 57 PIMAGE_SECTION_HEADER pSec; 58 PBYTE _ImageBase = _GetPEImageBase (); 59 60 if (was_here || !_ImageBase) 61 return was_here; 62 was_here = 1; 63 if (_FindPESectionByName (".pdata") != NULL) 64 return 1; 65 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); 69 70 e = 0; 71 /* Fill tables and entries. */ 72 while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL) 73 { 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); 81 ++e; 82 } 83 #ifdef _DEBUG_CRT 84 if (!e || e > MAX_PDATA_ENTRIES) 85 abort (); 86 #endif 87 /* RtlAddFunctionTable. */ 88 if (e != 0) 89 RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase); 90 return 1; 91 } 92 93 extern void __cdecl _fpreset (void); 94 95 EXCEPTION_DISPOSITION 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))) 100 { 101 EXCEPTION_DISPOSITION action = ExceptionContinueSearch; /* EXCEPTION_CONTINUE_SEARCH; */ 102 void (*old_handler) (int); 103 int reset_fpu = 0; 104 105 switch (ExceptionRecord->ExceptionCode) 106 { 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) 111 { 112 /* this is undefined if the signal was raised by anything other 113 than raise (). */ 114 signal (SIGSEGV, SIG_IGN); 115 action = 0; //EXCEPTION_CONTINUE_EXECUTION; 116 } 117 else if (old_handler != SIG_DFL) 118 { 119 /* This means 'old' is a user defined function. Call it */ 120 (*old_handler) (SIGSEGV); 121 action = 0; // EXCEPTION_CONTINUE_EXECUTION; 122 } 123 else 124 action = 4; /* EXCEPTION_EXECUTE_HANDLER; */ 125 break; 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) 131 { 132 /* this is undefined if the signal was raised by anything other 133 than raise (). */ 134 signal (SIGILL, SIG_IGN); 135 action = 0; // EXCEPTION_CONTINUE_EXECUTION; 136 } 137 else if (old_handler != SIG_DFL) 138 { 139 /* This means 'old' is a user defined function. Call it */ 140 (*old_handler) (SIGILL); 141 action = 0; // EXCEPTION_CONTINUE_EXECUTION; 142 } 143 else 144 action = 4; /* EXCEPTION_EXECUTE_HANDLER;*/ 145 break; 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: 152 reset_fpu = 1; 153 /* fall through. */ 154 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) 159 { 160 signal (SIGFPE, SIG_IGN); 161 if (reset_fpu) 162 _fpreset (); 163 action = 0; // EXCEPTION_CONTINUE_EXECUTION; 164 } 165 else if (old_handler != SIG_DFL) 166 { 167 /* This means 'old' is a user defined function. Call it */ 168 (*old_handler) (SIGFPE); 169 action = 0; // EXCEPTION_CONTINUE_EXECUTION; 170 } 171 break; 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; 179 break; 180 default: 181 break; 182 } 183 return action; 184 } 185 186 #endif 187 188 LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL; 189 190 long CALLBACK 191 _gnu_exception_handler (EXCEPTION_POINTERS *exception_data); 192 193 #define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C' | (1U << 29)) 194 195 long CALLBACK 196 _gnu_exception_handler (EXCEPTION_POINTERS *exception_data) 197 { 198 void (*old_handler) (int); 199 long action = EXCEPTION_CONTINUE_SEARCH; 200 int reset_fpu = 0; 201 202 #ifdef __SEH__ 203 if ((exception_data->ExceptionRecord->ExceptionCode & 0x20ffffff) == GCC_MAGIC) 204 { 205 if ((exception_data->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == 0) 206 return EXCEPTION_CONTINUE_EXECUTION; 207 } 208 #endif 209 210 switch (exception_data->ExceptionRecord->ExceptionCode) 211 { 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) 216 { 217 /* this is undefined if the signal was raised by anything other 218 than raise (). */ 219 signal (SIGSEGV, SIG_IGN); 220 action = EXCEPTION_CONTINUE_EXECUTION; 221 } 222 else if (old_handler != SIG_DFL) 223 { 224 /* This means 'old' is a user defined function. Call it */ 225 (*old_handler) (SIGSEGV); 226 action = EXCEPTION_CONTINUE_EXECUTION; 227 } 228 break; 229 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) 235 { 236 /* this is undefined if the signal was raised by anything other 237 than raise (). */ 238 signal (SIGILL, SIG_IGN); 239 action = EXCEPTION_CONTINUE_EXECUTION; 240 } 241 else if (old_handler != SIG_DFL) 242 { 243 /* This means 'old' is a user defined function. Call it */ 244 (*old_handler) (SIGILL); 245 action = EXCEPTION_CONTINUE_EXECUTION; 246 } 247 break; 248 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: 255 reset_fpu = 1; 256 /* fall through. */ 257 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) 262 { 263 signal (SIGFPE, SIG_IGN); 264 if (reset_fpu) 265 _fpreset (); 266 action = EXCEPTION_CONTINUE_EXECUTION; 267 } 268 else if (old_handler != SIG_DFL) 269 { 270 /* This means 'old' is a user defined function. Call it */ 271 (*old_handler) (SIGFPE); 272 action = EXCEPTION_CONTINUE_EXECUTION; 273 } 274 break; 275 #ifdef _WIN64 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; 283 break; 284 #endif 285 default: 286 break; 287 } 288 289 if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler) 290 action = (*__mingw_oldexcpt_handler)(exception_data); 291 return action; 292 } 293