X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-x86.c;h=0fa01593b9df3e32dd86d2d041d15960820fb0df;hb=424595ea7043f30b0553f2842654db13baeda3ca;hp=c97f28f39f49a7e2ea7fc0f23d6a5601855fa399;hpb=cbbd71101794e66ab7477db65cfbd61d67e08305;p=mono.git diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index c97f28f39f4..0fa01593b9d 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -8,6 +8,13 @@ */ #include + +#if _WIN32_WINNT < 0x0501 +/* Required for Vectored Exception Handling. */ +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif /* _WIN32_WINNT < 0x0501 */ + #include #include #include @@ -25,7 +32,6 @@ #include "mini.h" #include "mini-x86.h" #include "tasklets.h" -#include "debug-mini.h" static gpointer signal_exception_trampoline; @@ -40,8 +46,9 @@ static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; -guint64 mono_win_chained_exception_filter_result; -gboolean mono_win_chained_exception_filter_didrun; +gpointer mono_win_vectored_exception_handle; +extern gboolean mono_win_chained_exception_needs_run; +extern int (*gUnhandledExceptionHandler)(EXCEPTION_POINTERS*); #ifndef PROCESS_CALLBACK_FILTER_ENABLED # define PROCESS_CALLBACK_FILTER_ENABLED 1 @@ -50,6 +57,19 @@ gboolean mono_win_chained_exception_filter_didrun; #define W32_SEH_HANDLE_EX(_ex) \ if (_ex##_handler) _ex##_handler(0, ep, sctx) +LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) +{ +#ifndef MONO_CROSS_COMPILE + if (mono_old_win_toplevel_exception_filter) { + return (*mono_old_win_toplevel_exception_filter)(ep); + } +#endif + + mono_handle_native_sigsegv (SIGSEGV, NULL); + + return EXCEPTION_CONTINUE_SEARCH; +} + /* * mono_win32_get_handle_stackoverflow (void): * @@ -170,14 +190,14 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx) * Unhandled Exception Filter * Top-level per-process exception handler. */ -LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) +LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) { EXCEPTION_RECORD* er; CONTEXT* ctx; struct sigcontext* sctx; LONG res; - mono_win_chained_exception_filter_didrun = FALSE; + mono_win_chained_exception_needs_run = FALSE; res = EXCEPTION_CONTINUE_EXECUTION; er = ep->ExceptionRecord; @@ -217,21 +237,30 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) break; } - /* Copy context back */ - ctx->Eax = sctx->eax; - ctx->Ebx = sctx->ebx; - ctx->Ecx = sctx->ecx; - ctx->Edx = sctx->edx; - ctx->Ebp = sctx->ebp; - ctx->Esp = sctx->esp; - ctx->Esi = sctx->esi; - ctx->Edi = sctx->edi; - ctx->Eip = sctx->eip; - - g_free (sctx); + if (mono_win_chained_exception_needs_run) { + /* Don't copy context back if we chained exception + * as the handler may have modfied the EXCEPTION_POINTERS + * directly. We don't pass sigcontext to chained handlers. + * Return continue search so the UnhandledExceptionFilter + * can correctly chain the exception. + */ + res = EXCEPTION_CONTINUE_SEARCH; + } else { + /* Copy context back */ + ctx->Eax = sctx->eax; + ctx->Ebx = sctx->ebx; + ctx->Ecx = sctx->ecx; + ctx->Edx = sctx->edx; + ctx->Ebp = sctx->ebp; + ctx->Esp = sctx->esp; + ctx->Esi = sctx->esi; + ctx->Edi = sctx->edi; + ctx->Eip = sctx->eip; + } - if (mono_win_chained_exception_filter_didrun) - res = mono_win_chained_exception_filter_result; + /* TODO: Find right place to free this in stack overflow case */ + if (er->ExceptionCode != EXCEPTION_STACK_OVERFLOW) + g_free (sctx); return res; } @@ -242,12 +271,14 @@ void win32_seh_init() if (!restore_stack) restore_stack = mono_win32_get_handle_stackoverflow (); - mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_handler); + mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_unhandled_exception_filter); + mono_win_vectored_exception_handle = AddVectoredExceptionHandler (1, seh_vectored_exception_handler); } void win32_seh_cleanup() { if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter); + RemoveVectoredExceptionHandler (seh_unhandled_exception_filter); } void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) @@ -289,27 +320,53 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) /* load ctx */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4); - /* get return address, stored in ECX */ - x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4); /* restore EBX */ x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4); + /* restore EDI */ x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4); + /* restore ESI */ x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4); - /* restore ESP */ - x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4); - /* save the return addr to the restored stack */ - x86_push_reg (code, X86_ECX); - /* restore EBP */ - x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4); - /* restore ECX */ - x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ecx), 4); + /* restore EDX */ x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoContext, edx), 4); - /* restore EAX */ - x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4); + /* + * The context resides on the stack, in the stack frame of the + * caller of this function. The stack pointer that we need to + * restore is potentially many stack frames higher up, so the + * distance between them can easily be more than the red zone + * size. Hence the stack pointer can be restored only after + * we have finished loading everything from the context. + */ + + /* load ESP into EBP */ + x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4); + /* load return address into ECX */ + x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4); + /* save the return addr to the restored stack - 4 */ + x86_mov_membase_reg (code, X86_EBP, -4, X86_ECX, 4); + + /* load EBP into ECX */ + x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4); + /* save EBP to the restored stack - 8 */ + x86_mov_membase_reg (code, X86_EBP, -8, X86_ECX, 4); + + /* load EAX into ECX */ + x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4); + /* save EAX to the restored stack - 12 */ + x86_mov_membase_reg (code, X86_EBP, -12, X86_ECX, 4); + + /* restore ECX */ + x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ecx), 4); + + /* restore ESP - 12 */ + x86_lea_membase (code, X86_ESP, X86_EBP, -12); + /* restore EAX */ + x86_pop_reg (code, X86_EAX); + /* restore EBP */ + x86_pop_reg (code, X86_EBP); /* jump to the saved IP */ x86_ret (code); @@ -415,12 +472,8 @@ void mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, mgreg_t eip, gboolean rethrow) { - static void (*restore_context) (MonoContext *); MonoContext ctx; - if (!restore_context) - restore_context = mono_get_restore_context (); - ctx.esp = regs [X86_ESP]; ctx.eip = eip; ctx.ebp = regs [X86_EBP]; @@ -442,29 +495,12 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, mono_ex->stack_trace = NULL; } - if (mono_debug_using_mono_debugger ()) { - guint8 buf [16], *code; - - mono_breakpoint_clean_code (NULL, (gpointer)eip, 8, buf, sizeof (buf)); - code = buf + 8; - - if (buf [3] == 0xe8) { - MonoContext ctx_cp = ctx; - ctx_cp.eip = eip - 5; - - if (mono_debugger_handle_exception (&ctx_cp, exc)) { - restore_context (&ctx_cp); - g_assert_not_reached (); - } - } - } - /* adjust eip so that it point into the call instruction */ ctx.eip -= 1; mono_handle_exception (&ctx, exc); - restore_context (&ctx); + mono_restore_context (&ctx); g_assert_not_reached (); } @@ -765,10 +801,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, frame->type = FRAME_TYPE_MANAGED; - if (ji->from_aot) - unwind_info = mono_aot_get_unwind_info (ji, &unwind_info_len); - else - unwind_info = mono_get_cached_unwind_info (ji->used_regs, &unwind_info_len); + unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len); regs [X86_EAX] = new_ctx->eax; regs [X86_EBX] = new_ctx->ebx; @@ -801,9 +834,19 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /* Adjust IP */ new_ctx->eip --; - if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { - /* remove any unused lmf */ - *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); + if (*lmf && ((*lmf) != jit_tls->first_lmf)) { + gboolean is_tramp = ((guint32)((*lmf)->previous_lmf) & 1); + gpointer lmf_esp; + + if (is_tramp) + /* lmf->esp is only set in trampoline frames */ + lmf_esp = (gpointer)(*lmf)->esp; + else + /* In non-trampoline frames, ebp is the frame pointer */ + lmf_esp = (gpointer)(*lmf)->ebp; + if (MONO_CONTEXT_GET_SP (ctx) >= lmf_esp) + /* remove any unused lmf */ + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); } /* Pop arguments off the stack */ @@ -931,19 +974,12 @@ handle_signal_exception (gpointer obj) { MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); MonoContext ctx; - static void (*restore_context) (MonoContext *); - - if (!restore_context) - restore_context = mono_get_restore_context (); memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext)); - if (mono_debugger_handle_exception (&ctx, (MonoObject *)obj)) - return; - mono_handle_exception (&ctx, obj); - restore_context (&ctx); + mono_restore_context (&ctx); } /* @@ -1051,9 +1087,6 @@ mono_arch_handle_exception (void *sigctx, gpointer obj) mono_arch_sigctx_to_monoctx (sigctx, &mctx); - if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) - return TRUE; - mono_handle_exception (&mctx, obj); mono_arch_monoctx_to_sigctx (&mctx, sigctx); @@ -1091,22 +1124,14 @@ prepare_for_guard_pages (MonoContext *mctx) static void altstack_handle_and_restore (MonoContext *ctx, gpointer obj, gboolean stack_ovf) { - void (*restore_context) (MonoContext *); MonoContext mctx; - restore_context = mono_get_restore_context (); mctx = *ctx; - if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) { - if (stack_ovf) - prepare_for_guard_pages (&mctx); - restore_context (&mctx); - } - mono_handle_exception (&mctx, obj); if (stack_ovf) prepare_for_guard_pages (&mctx); - restore_context (&mctx); + mono_restore_context (&mctx); } void