2003-08-19 Nick Drochak <ndrochak@gol.com>
[mono.git] / mono / jit / win32-exception.c
1 /*
2  * win32-exception.c: Win32 SEH filter.
3  *
4  * (C) 2002 Ximian, Inc.
5  */
6
7 #include "win32-exception.h"
8
9 #ifdef PLATFORM_WIN32
10
11 #include <glib.h>
12
13
14 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep);
15
16 static MonoW32ExceptionHandler fpe_handler;
17 static MonoW32ExceptionHandler ill_handler;
18 static MonoW32ExceptionHandler segv_handler;
19
20 static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
21
22 #define W32_SEH_COPY_CONTEXT \
23         sctx->eax = ctx->Eax;\
24         sctx->ebx = ctx->Ebx;\
25         sctx->ecx = ctx->Ecx;\
26         sctx->edx = ctx->Edx;\
27         sctx->ebp = ctx->Ebp;\
28         sctx->esp = ctx->Esp;\
29         sctx->esi = ctx->Esi;\
30         sctx->edi = ctx->Edi;\
31         sctx->eip = ctx->Eip;
32
33 #define W32_SEH_HANDLE_EX(_ex) \
34         if (_ex##_handler) _ex##_handler((int)sctx)
35
36 /*
37  * Unhandled Exception Filter
38  * Top-level per-process exception handler.
39  */
40 LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep)
41 {
42         EXCEPTION_RECORD* er;
43         CONTEXT* ctx;
44         struct sigcontext* sctx;
45         LONG res;
46
47         res = EXCEPTION_CONTINUE_SEARCH;
48
49         er = ep->ExceptionRecord;
50         ctx = ep->ContextRecord;
51         sctx = g_malloc(sizeof(struct sigcontext));
52         W32_SEH_COPY_CONTEXT
53
54         switch (er->ExceptionCode) {
55         case EXCEPTION_ACCESS_VIOLATION:
56                 W32_SEH_HANDLE_EX(segv);
57                 break;
58         case EXCEPTION_ILLEGAL_INSTRUCTION:
59                 W32_SEH_HANDLE_EX(ill);
60                 break;
61         case EXCEPTION_INT_DIVIDE_BY_ZERO:
62         case EXCEPTION_INT_OVERFLOW:
63         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
64         case EXCEPTION_FLT_OVERFLOW:
65         case EXCEPTION_FLT_UNDERFLOW:
66         case EXCEPTION_FLT_INEXACT_RESULT:
67                 W32_SEH_HANDLE_EX(fpe);
68                 break;
69         default:
70                 break;
71         }
72
73         return res;
74 }
75
76 void win32_seh_init()
77 {
78         old_handler = SetUnhandledExceptionFilter(seh_handler);
79 }
80
81 void win32_seh_cleanup()
82 {
83         if (old_handler) SetUnhandledExceptionFilter(old_handler);
84 }
85
86 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
87 {
88         switch (type) {
89         case SIGFPE:
90                 fpe_handler = handler;
91                 break;
92         case SIGILL:
93                 ill_handler = handler;
94                 break;
95         case SIGSEGV:
96                 segv_handler = handler;
97                 break;
98         default:
99                 break;
100         }
101 }
102
103 #endif /* PLATFORM_WIN32 */
104