/* * win32-exception.c: Win32 SEH filter. * * (C) 2002 Ximian, Inc. */ #include "win32-exception.h" #ifdef PLATFORM_WIN32 #include LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep); static MonoW32ExceptionHandler fpe_handler; static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; static LPTOP_LEVEL_EXCEPTION_FILTER old_handler; #define W32_SEH_COPY_CONTEXT \ sctx->eax = ctx->Eax;\ sctx->ebx = ctx->Ebx;\ sctx->ecx = ctx->Ecx;\ sctx->edx = ctx->Edx;\ sctx->ebp = ctx->Ebp;\ sctx->esp = ctx->Esp;\ sctx->esi = ctx->Esi;\ sctx->edi = ctx->Edi;\ sctx->eip = ctx->Eip; #define W32_SEH_HANDLE_EX(_ex) \ if (_ex##_handler) _ex##_handler((int)sctx) /* * Unhandled Exception Filter * Top-level per-process exception handler. */ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) { EXCEPTION_RECORD* er; CONTEXT* ctx; struct sigcontext* sctx; LONG res; res = EXCEPTION_CONTINUE_SEARCH; er = ep->ExceptionRecord; ctx = ep->ContextRecord; sctx = g_malloc(sizeof(struct sigcontext)); W32_SEH_COPY_CONTEXT switch (er->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: W32_SEH_HANDLE_EX(segv); break; case EXCEPTION_ILLEGAL_INSTRUCTION: W32_SEH_HANDLE_EX(ill); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_OVERFLOW: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_UNDERFLOW: case EXCEPTION_FLT_INEXACT_RESULT: W32_SEH_HANDLE_EX(fpe); break; default: break; } return res; } void win32_seh_init() { old_handler = SetUnhandledExceptionFilter(seh_handler); } void win32_seh_cleanup() { if (old_handler) SetUnhandledExceptionFilter(old_handler); } void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) { switch (type) { case SIGFPE: fpe_handler = handler; break; case SIGILL: ill_handler = handler; break; case SIGSEGV: segv_handler = handler; break; default: break; } } #endif /* PLATFORM_WIN32 */