master
  1/**
  2 * This file has no copyright assigned and is placed in the Public Domain.
  3 * This file is part of the mingw-w64 runtime package.
  4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5 */
  6
  7#include <windows.h>
  8#include <excpt.h>
  9#include <string.h>
 10#include <stdlib.h>
 11#include <malloc.h>
 12#include <memory.h>
 13#include <signal.h>
 14#include <stdio.h>
 15
 16#pragma pack(push,1)
 17typedef struct _UNWIND_INFO {
 18  BYTE VersionAndFlags;
 19  BYTE PrologSize;
 20  BYTE CountOfUnwindCodes;
 21  BYTE FrameRegisterAndOffset;
 22  ULONG AddressOfExceptionHandler;
 23} UNWIND_INFO,*PUNWIND_INFO;
 24#pragma pack(pop)
 25
 26PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
 27PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
 28PBYTE _GetPEImageBase (void);
 29
 30int __mingw_init_ehandler (void);
 31extern void _fpreset (void);
 32
 33#if defined(__x86_64__) && !defined(_MSC_VER) && !defined(__SEH__)
 34EXCEPTION_DISPOSITION __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
 35
 36#define MAX_PDATA_ENTRIES 32
 37static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES];
 38static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES];
 39
 40int
 41__mingw_init_ehandler (void)
 42{
 43  static int was_here = 0;
 44  size_t e = 0;
 45  PIMAGE_SECTION_HEADER pSec;
 46  PBYTE _ImageBase = _GetPEImageBase ();
 47  
 48  if (was_here || !_ImageBase)
 49    return was_here;
 50  was_here = 1;
 51  if (_FindPESectionByName (".pdata") != NULL)
 52    return 1;
 53
 54  e = 0;
 55  /* Fill tables and entries.  */
 56  while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL)
 57    {
 58      emu_xdata[e].VersionAndFlags = 9; /* UNW_FLAG_EHANDLER | UNW_VERSION */
 59      emu_xdata[e].AddressOfExceptionHandler =
 60	(DWORD)(size_t) ((LPBYTE)__mingw_SEH_error_handler - _ImageBase);
 61      emu_pdata[e].BeginAddress = pSec->VirtualAddress;
 62      emu_pdata[e].EndAddress = pSec->VirtualAddress + pSec->Misc.VirtualSize;
 63      emu_pdata[e].UnwindData =
 64	(DWORD)(size_t)((LPBYTE)&emu_xdata[e] - _ImageBase);
 65      ++e;
 66    }
 67#ifdef _DEBUG_CRT
 68  if (!e || e > MAX_PDATA_ENTRIES)
 69    abort ();
 70#endif
 71  /* RtlAddFunctionTable.  */
 72  if (e != 0)
 73    RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase);
 74  return 1;
 75}
 76
 77extern void _fpreset (void);
 78
 79EXCEPTION_DISPOSITION
 80__mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
 81			   void *EstablisherFrame  __attribute__ ((unused)),
 82			   struct _CONTEXT* ContextRecord __attribute__ ((unused)),
 83			   void *DispatcherContext __attribute__ ((unused)))
 84{
 85  EXCEPTION_DISPOSITION action = ExceptionContinueSearch; /* EXCEPTION_CONTINUE_SEARCH; */
 86  void (*old_handler) (int);
 87  int reset_fpu = 0;
 88
 89  switch (ExceptionRecord->ExceptionCode)
 90    {
 91    case EXCEPTION_ACCESS_VIOLATION:
 92      /* test if the user has set SIGSEGV */
 93      old_handler = signal (SIGSEGV, SIG_DFL);
 94      if (old_handler == SIG_IGN)
 95	{
 96	  /* this is undefined if the signal was raised by anything other
 97	     than raise ().  */
 98	  signal (SIGSEGV, SIG_IGN);
 99	  action = 0; //EXCEPTION_CONTINUE_EXECUTION;
100	}
101      else if (old_handler != SIG_DFL)
102	{
103	  /* This means 'old' is a user defined function. Call it */
104	  (*old_handler) (SIGSEGV);
105	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
106	}
107      else
108        action = 4; /* EXCEPTION_EXECUTE_HANDLER; */
109      break;
110    case EXCEPTION_ILLEGAL_INSTRUCTION:
111    case EXCEPTION_PRIV_INSTRUCTION:
112      /* test if the user has set SIGILL */
113      old_handler = signal (SIGILL, SIG_DFL);
114      if (old_handler == SIG_IGN)
115	{
116	  /* this is undefined if the signal was raised by anything other
117	     than raise ().  */
118	  signal (SIGILL, SIG_IGN);
119	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
120	}
121      else if (old_handler != SIG_DFL)
122	{
123	  /* This means 'old' is a user defined function. Call it */
124	  (*old_handler) (SIGILL);
125	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
126	}
127      else
128        action = 4; /* EXCEPTION_EXECUTE_HANDLER;*/
129      break;
130    case EXCEPTION_FLT_INVALID_OPERATION:
131    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
132    case EXCEPTION_FLT_DENORMAL_OPERAND:
133    case EXCEPTION_FLT_OVERFLOW:
134    case EXCEPTION_FLT_UNDERFLOW:
135    case EXCEPTION_FLT_INEXACT_RESULT:
136      reset_fpu = 1;
137      /* fall through. */
138
139    case EXCEPTION_INT_DIVIDE_BY_ZERO:
140      /* test if the user has set SIGFPE */
141      old_handler = signal (SIGFPE, SIG_DFL);
142      if (old_handler == SIG_IGN)
143	{
144	  signal (SIGFPE, SIG_IGN);
145	  if (reset_fpu)
146	    _fpreset ();
147	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
148	}
149      else if (old_handler != SIG_DFL)
150	{
151	  /* This means 'old' is a user defined function. Call it */
152	  (*old_handler) (SIGFPE);
153	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
154	}
155      break;
156    case EXCEPTION_DATATYPE_MISALIGNMENT:
157    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
158    case EXCEPTION_FLT_STACK_CHECK:
159    case EXCEPTION_INT_OVERFLOW:
160    case EXCEPTION_INVALID_HANDLE:
161    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
162      action = 0; // EXCEPTION_CONTINUE_EXECUTION;
163      break;
164    default:
165      break;
166    }
167  return action;
168}
169
170#endif
171
172LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
173
174long CALLBACK
175_gnu_exception_handler (EXCEPTION_POINTERS *exception_data);
176
177#define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C' | (1U << 29))
178
179long CALLBACK
180_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
181{
182  void (*old_handler) (int);
183  long action = EXCEPTION_CONTINUE_SEARCH;
184  int reset_fpu = 0;
185
186#ifdef __SEH__
187  if ((exception_data->ExceptionRecord->ExceptionCode & 0x20ffffff) == GCC_MAGIC)
188    {
189      if ((exception_data->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == 0)
190        return EXCEPTION_CONTINUE_EXECUTION;
191    }
192#endif
193
194  switch (exception_data->ExceptionRecord->ExceptionCode)
195    {
196    case EXCEPTION_ACCESS_VIOLATION:
197      /* test if the user has set SIGSEGV */
198      old_handler = signal (SIGSEGV, SIG_DFL);
199      if (old_handler == SIG_IGN)
200	{
201	  /* this is undefined if the signal was raised by anything other
202	     than raise ().  */
203	  signal (SIGSEGV, SIG_IGN);
204	  action = EXCEPTION_CONTINUE_EXECUTION;
205	}
206      else if (old_handler != SIG_DFL)
207	{
208	  /* This means 'old' is a user defined function. Call it */
209	  (*old_handler) (SIGSEGV);
210	  action = EXCEPTION_CONTINUE_EXECUTION;
211	}
212      break;
213
214    case EXCEPTION_ILLEGAL_INSTRUCTION:
215    case EXCEPTION_PRIV_INSTRUCTION:
216      /* test if the user has set SIGILL */
217      old_handler = signal (SIGILL, SIG_DFL);
218      if (old_handler == SIG_IGN)
219	{
220	  /* this is undefined if the signal was raised by anything other
221	     than raise ().  */
222	  signal (SIGILL, SIG_IGN);
223	  action = EXCEPTION_CONTINUE_EXECUTION;
224	}
225      else if (old_handler != SIG_DFL)
226	{
227	  /* This means 'old' is a user defined function. Call it */
228	  (*old_handler) (SIGILL);
229	  action = EXCEPTION_CONTINUE_EXECUTION;
230	}
231      break;
232
233    case EXCEPTION_FLT_INVALID_OPERATION:
234    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
235    case EXCEPTION_FLT_DENORMAL_OPERAND:
236    case EXCEPTION_FLT_OVERFLOW:
237    case EXCEPTION_FLT_UNDERFLOW:
238    case EXCEPTION_FLT_INEXACT_RESULT:
239      reset_fpu = 1;
240      /* fall through. */
241
242    case EXCEPTION_INT_DIVIDE_BY_ZERO:
243      /* test if the user has set SIGFPE */
244      old_handler = signal (SIGFPE, SIG_DFL);
245      if (old_handler == SIG_IGN)
246	{
247	  signal (SIGFPE, SIG_IGN);
248	  if (reset_fpu)
249	    _fpreset ();
250	  action = EXCEPTION_CONTINUE_EXECUTION;
251	}
252      else if (old_handler != SIG_DFL)
253	{
254	  /* This means 'old' is a user defined function. Call it */
255	  (*old_handler) (SIGFPE);
256	  action = EXCEPTION_CONTINUE_EXECUTION;
257	}
258      break;
259#ifdef _WIN64
260    case EXCEPTION_DATATYPE_MISALIGNMENT:
261    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
262    case EXCEPTION_FLT_STACK_CHECK:
263    case EXCEPTION_INT_OVERFLOW:
264    case EXCEPTION_INVALID_HANDLE:
265    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
266      action = EXCEPTION_CONTINUE_EXECUTION;
267      break;
268#endif
269    default:
270      break;
271    }
272
273  if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
274    action = (*__mingw_oldexcpt_handler)(exception_data);
275  return action;
276}