X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-amd64.c;h=bf5a35b71dcc0e4272ef32d9946e9ac5b4df8e01;hb=4db06151bebcc81ad062d68d361ea03d50f455fb;hp=846ad9744f59c5f30b8987af7d8ac4f822ba4ec2;hpb=91ae1664061e8ac2d370da57c57d450bb00d64de;p=mono.git diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 846ad9744f5..bf5a35b71dc 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -13,6 +13,11 @@ #include +// Secret password to unlock wcscat_s on mxe, must happen before string.h included +#ifdef __MINGW32__ +#define MINGW_HAS_SECURE_API 1 +#endif + #include #include @@ -42,6 +47,7 @@ #define ALIGN_TO(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) #ifdef TARGET_WIN32 +static void (*restore_stack) (void); static MonoW32ExceptionHandler fpe_handler; static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; @@ -65,6 +71,50 @@ static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) return EXCEPTION_CONTINUE_SEARCH; } +static gpointer +get_win32_restore_stack (void) +{ + static guint8 *start = NULL; + guint8 *code; + + if (start) + return start; + + /* restore_stack (void) */ + start = code = mono_global_codeman_reserve (128); + + amd64_push_reg (code, AMD64_RBP); + amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, 8); + + /* push 32 bytes of stack space for Win64 calling convention */ + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 32); + + /* restore guard page */ + amd64_mov_reg_imm (code, AMD64_R11, _resetstkoflw); + amd64_call_reg (code, AMD64_R11); + + /* get jit_tls with context to restore */ + amd64_mov_reg_imm (code, AMD64_R11, mono_tls_get_jit_tls); + amd64_call_reg (code, AMD64_R11); + + /* move jit_tls from return reg to arg reg */ + amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, 8); + + /* retrieve pointer to saved context */ + amd64_alu_reg_imm (code, X86_ADD, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, stack_restore_ctx)); + + /* this call does not return */ + amd64_mov_reg_imm (code, AMD64_R11, mono_restore_context); + amd64_call_reg (code, AMD64_R11); + + g_assert ((code - start) < 128); + + mono_arch_flush_icache (start, code - start); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); + + return start; +} + /* * Unhandled Exception Filter * Top-level per-process exception handler. @@ -75,6 +125,7 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) CONTEXT* ctx; LONG res; MonoJitTlsData *jit_tls = mono_tls_get_jit_tls (); + MonoDomain* domain = mono_domain_get (); /* If the thread is not managed by the runtime return early */ if (!jit_tls) @@ -87,6 +138,19 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) ctx = ep->ContextRecord; switch (er->ExceptionCode) { + case EXCEPTION_STACK_OVERFLOW: + if (!mono_aot_only) { + if (mono_arch_handle_exception (ctx, domain->stack_overflow_ex)) { + /* need to restore stack protection once stack is unwound + * restore_stack will restore stack protection and then + * resume control to the saved stack_restore_ctx */ + mono_sigctx_to_monoctx (ctx, &jit_tls->stack_restore_ctx); + ctx->Rip = (guint64)restore_stack; + } + } else { + jit_tls->mono_win_chained_exception_needs_run = TRUE; + } + break; case EXCEPTION_ACCESS_VIOLATION: W32_SEH_HANDLE_EX(segv); break; @@ -121,6 +185,9 @@ static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) void win32_seh_init() { + if (!mono_aot_only) + restore_stack = get_win32_restore_stack (); + mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_unhandled_exception_filter); mono_win_vectored_exception_handle = AddVectoredExceptionHandler (1, seh_vectored_exception_handler); } @@ -198,7 +265,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) amd64_jump_reg (code, AMD64_R11); mono_arch_flush_icache (start, code - start); - mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops); @@ -286,7 +353,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) g_assert ((code - start) < kMaxCodeSize); mono_arch_flush_icache (start, code - start); - mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops); @@ -469,7 +536,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g g_assert ((code - start) < kMaxCodeSize); g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE)); - mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); if (info) *info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops); @@ -582,20 +649,24 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, guint64 rip; if (((guint64)(*lmf)->previous_lmf) & 2) { - /* - * This LMF entry is created by the soft debug code to mark transitions to - * managed code done during invokes. - */ MonoLMFExt *ext = (MonoLMFExt*)(*lmf); - g_assert (ext->debugger_invoke); - - memcpy (new_ctx, &ext->ctx, sizeof (MonoContext)); + if (ext->debugger_invoke) { + /* + * This LMF entry is created by the soft debug code to mark transitions to + * managed code done during invokes. + */ + frame->type = FRAME_TYPE_DEBUGGER_INVOKE; + memcpy (new_ctx, &ext->ctx, sizeof (MonoContext)); + } else if (ext->interp_exit) { + frame->type = FRAME_TYPE_INTERP_TO_MANAGED; + frame->interp_exit_data = ext->interp_exit_data; + } else { + g_assert_not_reached (); + } *lmf = (MonoLMF *)(((guint64)(*lmf)->previous_lmf) & ~7); - frame->type = FRAME_TYPE_DEBUGGER_INVOKE; - return TRUE; } @@ -895,6 +966,7 @@ mono_arch_exceptions_init (void) } } +// Implies defined(TARGET_WIN32) #ifdef MONO_ARCH_HAVE_UNWIND_TABLE static void @@ -1471,7 +1543,7 @@ mono_arch_unwindinfo_find_rt_func_in_table (const gpointer code, gsize code_size return found_rt_func; } -inline PRUNTIME_FUNCTION +static inline PRUNTIME_FUNCTION mono_arch_unwindinfo_find_pc_rt_func_in_table (const gpointer pc) { return mono_arch_unwindinfo_find_rt_func_in_table (pc, 0); @@ -1815,7 +1887,7 @@ mono_tasklets_arch_restore (void) g_assert ((code - start) <= kMaxCodeSize); mono_arch_flush_icache (start, code - start); - mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); saved = start; return (MonoContinuationRestore)saved;