#include "mini.h"
#include "mini-x86.h"
+#ifdef PLATFORM_WIN32
+
+#include <windows.h>
+
+/* use SIG* defines if possible */
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+/* sigcontext surrogate */
+struct sigcontext {
+ unsigned int eax;
+ unsigned int ebx;
+ unsigned int ecx;
+ unsigned int edx;
+ unsigned int ebp;
+ unsigned int esp;
+ unsigned int esi;
+ unsigned int edi;
+ unsigned int eip;
+};
+
+
+typedef void (* MonoW32ExceptionHandler) (int);
+void win32_seh_init(void);
+void win32_seh_cleanup(void);
+void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
+
+#ifndef SIGFPE
+#define SIGFPE 4
+#endif
+
+#ifndef SIGILL
+#define SIGILL 8
+#endif
+
+#ifndef SIGSEGV
+#define SIGSEGV 11
+#endif
+
+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 */
+
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# define SC_EAX sc_eax
# define SC_EBX sc_ebx
# define SC_ESI esi
#endif
+gboolean mono_arch_handle_exception (struct sigcontext *ctx, gpointer obj, gboolean test_only);
+
typedef struct sigcontext MonoContext;
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->SC_EIP = (long)ip; } while (0);
return start;
inited = 1;
- /* call_filter (struct sigcontext *ctx, unsigned long eip, gpointer exc) */
+ /* call_filter (struct sigcontext *ctx, unsigned long eip) */
code = start;
x86_push_reg (code, X86_EBP);
x86_mov_reg_membase (code, X86_ECX, X86_EBP, 12, 4);
/* save EBP */
x86_push_reg (code, X86_EBP);
- /* push exc */
- x86_push_membase (code, X86_EBP, 16);
+
/* set new EBP */
x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBP), 4);
/* restore registers used by global register allocation (EBX & ESI) */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EBX), 4);
x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_ESI), 4);
x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (struct sigcontext, SC_EDI), 4);
- /* save the ESP - this is used by endfinally */
- x86_mov_membase_reg (code, X86_EBP, mono_exc_esp_offset, X86_ESP, 4);
+
/* call the handler */
x86_call_reg (code, X86_ECX);
- x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
+
/* restore EBP */
x86_pop_reg (code, X86_EBP);
+
/* restore saved regs */
x86_pop_reg (code, X86_ESI);
x86_pop_reg (code, X86_EDI);
*managed = TRUE;
if (trace) {
- source_location = mono_debug_source_location_from_address (ji->method, address, NULL);
- iloffset = mono_debug_il_offset_from_address (ji->method, address);
+ source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain);
+ iloffset = mono_debug_il_offset_from_address (ji->method, address, domain);
if (iloffset < 0)
tmpaddr = g_strdup_printf ("<0x%05x>", address);
sf->method = mono_method_get_object (domain, ji->method, NULL);
sf->native_offset = (char *)ip - (char *)ji->code_start;
- sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset);
+ sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
if (need_file_info) {
gchar *filename;
- filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line);
+ filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
sf->filename = filename? mono_string_new (domain, filename): NULL;
sf->column = 0;
if (ji == (gpointer)-1)
return;
- il_offset = mono_debug_il_offset_from_address (ji->method, native_offset);
+ il_offset = mono_debug_il_offset_from_address (ji->method, native_offset, domain);
if (func (ji->method, native_offset, il_offset, managed, user_data))
return;
if (!ji || ji == (gpointer)-1 || MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack)
return FALSE;
- if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)
+ /* skip all wrappers ??*/
+ if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
+ ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
+ ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
continue;
skip--;
} while (skip >= 0);
*method = mono_method_get_object (domain, ji->method, NULL);
- *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset);
+ *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain);
if (need_file_info) {
gchar *filename;
- filename = mono_debug_source_location_from_address (ji->method, *native_offset, line);
+ filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain);
*file = filename? mono_string_new (domain, filename): NULL;
*column = 0;
{
MonoDomain *domain = mono_domain_get ();
MonoJitInfo *ji, rji;
- static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
+ static int (*call_filter) (MonoContext *, gpointer) = NULL;
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
MonoLMF *lmf = jit_tls->lmf;
GList *trace_ips = NULL;
if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) {
/* catch block */
+
+ if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) {
+ /* store the exception object int cfg->excvar */
+ g_assert (ji->exvar_offset);
+ *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj;
+ }
+
if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE &&
mono_object_isinst (obj, mono_class_get (ji->method->klass->image, ei->data.token))) ||
((ei->flags == MONO_EXCEPTION_CLAUSE_FILTER &&
- call_filter (ctx, ei->data.filter, obj)))) {
+ call_filter (ctx, ei->data.filter)))) {
if (test_only) {
((MonoException*)obj)->trace_ips = glist_to_array (trace_ips);
g_list_free (trace_ips);
+ g_free (trace);
return TRUE;
}
if (mono_jit_trace_calls)
g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
- *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj;
jit_tls->lmf = lmf;
+ g_free (trace);
return 0;
}
if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
(ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
if (mono_jit_trace_calls)
g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- call_filter (ctx, ei->handler_start, NULL);
+ call_filter (ctx, ei->handler_start);
}
}