X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-x86.c;h=0505633d1bcf17a15931be28beff90f6e43d4f5d;hb=dcc7a89be1bee430f05fe0c06bc448d2c7aaaf51;hp=2247b91a2abe39a3351df201a4a0ef77a815ee5c;hpb=4f021d81ca18b1aca6fd46165becb49bb9c63c25;p=mono.git diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index 2247b91a2ab..0505633d1bc 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -32,7 +32,6 @@ #include "mini.h" #include "mini-x86.h" #include "tasklets.h" -#include "debug-mini.h" static gpointer signal_exception_trampoline; @@ -48,7 +47,6 @@ static MonoW32ExceptionHandler segv_handler; LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; gpointer mono_win_vectored_exception_handle; -extern gboolean mono_win_chained_exception_needs_run; extern int (*gUnhandledExceptionHandler)(EXCEPTION_POINTERS*); #ifndef PROCESS_CALLBACK_FILTER_ENABLED @@ -197,8 +195,9 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) CONTEXT* ctx; struct sigcontext* sctx; LONG res; + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); - mono_win_chained_exception_needs_run = FALSE; + jit_tls->mono_win_chained_exception_needs_run = FALSE; res = EXCEPTION_CONTINUE_EXECUTION; er = ep->ExceptionRecord; @@ -238,7 +237,7 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) break; } - if (mono_win_chained_exception_needs_run) { + if (jit_tls->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. @@ -321,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); @@ -447,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]; @@ -474,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 (); } @@ -797,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; @@ -833,19 +834,41 @@ 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); } +#ifndef MONO_X86_NO_PUSHES /* Pop arguments off the stack */ - /* - * FIXME: LLVM doesn't push these, we can't use ji->from_llvm as it describes - * the callee. - */ -#ifndef ENABLE_LLVM - if (ji->has_arch_eh_info) - new_ctx->esp += mono_jit_info_get_arch_eh_info (ji)->stack_size; + if (ji->has_arch_eh_info) { + int stack_size; + + stack_size = mono_jit_info_get_arch_eh_info (ji)->stack_size; + + if (stack_size) { +#ifdef ENABLE_LLVM + MonoJitInfo *caller_ji; + + caller_ji = mini_jit_info_table_find (domain, (char*)new_ctx->eip, NULL); + /* LLVM doesn't push the arguments */ + if (caller_ji && !caller_ji->from_llvm) + new_ctx->esp += stack_size; +#else + new_ctx->esp += stack_size; +#endif + } + } #endif return TRUE; @@ -963,19 +986,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); } /* @@ -1083,9 +1099,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); @@ -1123,22 +1136,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