X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-x86.c;h=732614236cae0d1ddb0dcb0a2057b2cfecd1d4fb;hb=9c7daac28fa91e15a0728d6eeffd8b1a2c038acf;hp=ebde3f0dbf203e0786af836c494e5f13f1f8ff49;hpb=7c5cf554582ab86cb8925dc1f53cb26836d34190;p=mono.git diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index ebde3f0dbf2..732614236ca 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -24,8 +24,10 @@ #include "mini.h" #include "mini-x86.h" +#include "tasklets.h" +#include "debug-mini.h" -#ifdef PLATFORM_WIN32 +#ifdef TARGET_WIN32 static void (*restore_stack) (void *); static MonoW32ExceptionHandler fpe_handler; @@ -35,7 +37,7 @@ static MonoW32ExceptionHandler segv_handler; static LPTOP_LEVEL_EXCEPTION_FILTER old_handler; #define W32_SEH_HANDLE_EX(_ex) \ - if (_ex##_handler) _ex##_handler((int)sctx) + if (_ex##_handler) _ex##_handler(0, er, sctx) /* * mono_win32_get_handle_stackoverflow (void): @@ -101,21 +103,22 @@ mono_win32_get_handle_stackoverflow (void) static void win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx) { - SYSTEM_INFO si; - DWORD page_size; + SYSTEM_INFO si; + DWORD page_size; MonoDomain *domain = mono_domain_get (); - MonoJitInfo *ji, rji; + MonoJitInfo rji; MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); MonoLMF *lmf = jit_tls->lmf; MonoContext initial_ctx; MonoContext ctx; guint32 free_stack = 0; + StackFrameInfo frame; /* convert sigcontext to MonoContext (due to reuse of stack walking helpers */ mono_arch_sigctx_to_monoctx (sctx, &ctx); /* get our os page size */ - GetSystemInfo(&si); + GetSystemInfo(&si); page_size = si.dwPageSize; /* Let's walk the stack to recover @@ -130,19 +133,19 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx) do { MonoContext new_ctx; - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, &ctx, &new_ctx, &lmf, NULL); - if (!ji) { + mono_arch_find_jit_info_ext (domain, jit_tls, &rji, &ctx, &new_ctx, &lmf, &frame); + if (!frame.ji) { g_warning ("Exception inside function without unwind info"); g_assert_not_reached (); } - if (ji != (gpointer)-1) { + if (frame.ji != (gpointer)-1) { free_stack = (guint8*)(MONO_CONTEXT_GET_BP (&ctx)) - (guint8*)(MONO_CONTEXT_GET_BP (&initial_ctx)); } /* todo: we should call abort if ji is -1 */ ctx = new_ctx; - } while (free_stack < 64 * 1024 && ji != (gpointer) -1); + } while (free_stack < 64 * 1024 && frame.ji != (gpointer) -1); /* convert into sigcontext to be used in mono_arch_handle_exception */ mono_arch_monoctx_to_sigctx (&ctx, sctx); @@ -250,7 +253,7 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) } } -#endif /* PLATFORM_WIN32 */ +#endif /* TARGET_WIN32 */ /* * mono_arch_get_restore_context: @@ -267,7 +270,7 @@ mono_arch_get_restore_context (void) return start; /* restore_contect (MonoContext *ctx) */ - /* we do not restore X86_EAX, X86_EDX */ + /* we do not restore X86_EDX */ start = code = mono_global_codeman_reserve (128); @@ -286,6 +289,8 @@ mono_arch_get_restore_context (void) x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4); /* restore EBP */ x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4); + /* restore EAX */ + x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4); /* jump to the saved IP */ x86_jump_reg (code, X86_EDX); @@ -361,10 +366,14 @@ mono_arch_get_call_filter (void) return start; } +/* + * mono_x86_throw_exception: + * + * C function called from the throw trampolines. + */ static void -throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx, - unsigned long esi, unsigned long edi, unsigned long ebp, MonoObject *exc, - unsigned long eip, unsigned long esp, gboolean rethrow) +mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, + mgreg_t eip, gboolean rethrow) { static void (*restore_context) (MonoContext *); MonoContext ctx; @@ -372,65 +381,168 @@ throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsign if (!restore_context) restore_context = mono_arch_get_restore_context (); - /* Pop argument and return address */ - ctx.esp = esp + (2 * sizeof (gpointer)); + ctx.esp = regs [X86_ESP]; ctx.eip = eip; - ctx.ebp = ebp; - ctx.edi = edi; - ctx.esi = esi; - ctx.ebx = ebx; - ctx.edx = edx; - ctx.ecx = ecx; - ctx.eax = eax; - - if (mono_debugger_throw_exception ((gpointer)(eip - 5), (gpointer)esp, exc)) { - /* - * The debugger wants us to stop on the `throw' instruction. - * By the time we get here, it already inserted a breakpoint on - * eip - 5 (which is the address of the call). - */ - ctx.eip = eip - 5; - ctx.esp = esp + sizeof (gpointer); - restore_context (&ctx); - g_assert_not_reached (); - } - - /* adjust eip so that it point into the call instruction */ - ctx.eip -= 1; + ctx.ebp = regs [X86_EBP]; + ctx.edi = regs [X86_EDI]; + ctx.esi = regs [X86_ESI]; + ctx.ebx = regs [X86_EBX]; + ctx.edx = regs [X86_EDX]; + ctx.ecx = regs [X86_ECX]; + ctx.eax = regs [X86_EAX]; + +#ifdef __APPLE__ + /* The OSX ABI specifies 16 byte alignment at call sites */ + g_assert ((ctx.esp % MONO_ARCH_FRAME_ALIGNMENT) == 0); +#endif if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) 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, (gpointer)eip, FALSE); + restore_context (&ctx); g_assert_not_reached (); } +static void +mono_x86_throw_corlib_exception (mgreg_t *regs, guint32 ex_token_index, + mgreg_t eip, gint32 pc_offset) +{ + guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index; + MonoException *ex; + + ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token); + + eip -= pc_offset; + + mono_x86_throw_exception (regs, (MonoObject*)ex, eip, FALSE); +} + +/* + * get_throw_exception: + * + * Generate a call to mono_x86_throw_exception/ + * mono_x86_throw_corlib_exception. + * If LLVM is true, generate code which assumes the caller is LLVM generated code, + * which doesn't push the arguments. + */ static guint8* -get_throw_exception (gboolean rethrow) +get_throw_exception (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib) { guint8 *start, *code; + GSList *unwind_ops = NULL; + int i, stack_size, stack_offset, arg_offsets [5], regs_offset; - start = code = mono_global_codeman_reserve (64); + start = code = mono_global_codeman_reserve (128); - x86_push_reg (code, X86_ESP); - x86_push_membase (code, X86_ESP, 4); /* IP */ - x86_push_membase (code, X86_ESP, 12); /* exception */ - x86_push_reg (code, X86_EBP); - x86_push_reg (code, X86_EDI); - x86_push_reg (code, X86_ESI); - x86_push_reg (code, X86_EBX); - x86_push_reg (code, X86_EDX); - x86_push_reg (code, X86_ECX); - x86_push_reg (code, X86_EAX); - x86_call_code (code, throw_exception); - /* we should never reach this breakpoint */ + stack_size = 128; + + /* + * On apple, the stack is misaligned by the pushing of the return address. + */ + if (!llvm && corlib) + /* On OSX, we don't generate alignment code to save space */ + stack_size += 4; + else + stack_size += MONO_ARCH_FRAME_ALIGNMENT - 4; + + /* + * The stack looks like this: + * (only if corlib is TRUE) + * / + * <- esp (unaligned on apple) + */ + + mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4); + mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4); + + /* Alloc frame */ + x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size); + mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 4); + + arg_offsets [0] = 0; + arg_offsets [1] = 4; + arg_offsets [2] = 8; + arg_offsets [3] = 12; + regs_offset = 16; + + /* Save registers */ + for (i = 0; i < X86_NREG; ++i) + if (i != X86_ESP) + x86_mov_membase_reg (code, X86_ESP, regs_offset + (i * 4), i, 4); + /* Calculate the offset between the current sp and the sp of the caller */ + if (llvm) { + /* LLVM doesn't push the arguments */ + stack_offset = stack_size + 4; + } else { + if (corlib) { + /* Two arguments */ + stack_offset = stack_size + 4 + 8; +#ifdef __APPLE__ + /* We don't generate stack alignment code on osx to save space */ +#endif + } else { + /* One argument */ + stack_offset = stack_size + 4 + 4; +#ifdef __APPLE__ + /* Pop the alignment added by OP_THROW too */ + stack_offset += MONO_ARCH_FRAME_ALIGNMENT - 4; +#endif + } + } + /* Save ESP */ + x86_lea_membase (code, X86_EAX, X86_ESP, stack_offset); + x86_mov_membase_reg (code, X86_ESP, regs_offset + (X86_ESP * 4), X86_EAX, 4); + + /* Set arg1 == regs */ + x86_lea_membase (code, X86_EAX, X86_ESP, regs_offset); + x86_mov_membase_reg (code, X86_ESP, arg_offsets [0], X86_EAX, 4); + /* Set arg2 == exc */ + x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 4, 4); + x86_mov_membase_reg (code, X86_ESP, arg_offsets [1], X86_EAX, 4); + /* Set arg3 == eip */ + x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size, 4); + x86_mov_membase_reg (code, X86_ESP, arg_offsets [2], X86_EAX, 4); + if (corlib) { + /* Set arg4 == offset */ + x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 8, 4); + x86_mov_membase_reg (code, X86_ESP, arg_offsets [3], X86_EAX, 4); + } else { + /* Set arg4 == rethrow */ + x86_mov_membase_imm (code, X86_ESP, arg_offsets [3], rethrow, 4); + } + /* Make the call */ + x86_call_code (code, corlib ? (gpointer)mono_x86_throw_corlib_exception : (gpointer)mono_x86_throw_exception); x86_breakpoint (code); - g_assert ((code - start) < 64); + g_assert ((code - start) < 128); + + mono_save_trampoline_xdebug_info (corlib ? "llvm_throw_corlib_exception_trampoline" : "llvm_throw_exception_trampoline", start, code - start, unwind_ops); return start; } @@ -450,73 +562,13 @@ get_throw_exception (gboolean rethrow) gpointer mono_arch_get_throw_exception (void) { - static guint8 *start; - static int inited = 0; - - if (inited) - return start; - - start = get_throw_exception (FALSE); - - inited = 1; - - return start; + return get_throw_exception ("throw_exception_trampoline", FALSE, FALSE, FALSE); } gpointer mono_arch_get_rethrow_exception (void) { - static guint8 *start; - static int inited = 0; - - if (inited) - return start; - - start = get_throw_exception (TRUE); - - inited = 1; - - return start; -} - -/** - * mono_arch_get_throw_exception_by_name: - * - * Returns a function pointer which can be used to raise - * corlib exceptions. The returned function has the following - * signature: void (*func) (gpointer ip, char *exc_name); - * For example to raise an arithmetic exception you can use: - * - * x86_push_imm (code, "ArithmeticException"); - * x86_push_imm (code, ) - * x86_jump_code (code, arch_get_throw_exception_by_name ()); - * - */ -gpointer -mono_arch_get_throw_exception_by_name (void) -{ - static guint8* start; - static int inited = 0; - guint8 *code; - - if (inited) - return start; - - inited = 1; - code = start = mono_global_codeman_reserve (32); - - x86_push_membase (code, X86_ESP, 4); /* exception name */ - x86_push_imm (code, "System"); - x86_push_imm (code, mono_defaults.exception_class->image); - x86_call_code (code, mono_exception_from_name); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 12); - /* save the newly create object (overwrite exception name)*/ - x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4); - x86_jump_code (code, mono_arch_get_throw_exception ()); - - g_assert ((code - start) < 32); - - return start; + return get_throw_exception ("rethrow_exception_trampoline", TRUE, FALSE, FALSE); } /** @@ -532,63 +584,40 @@ mono_arch_get_throw_exception_by_name (void) gpointer mono_arch_get_throw_corlib_exception (void) { - static guint8* start; - static int inited = 0; - guint8 *code; + return get_throw_exception ("throw_corlib_exception_trampoline", FALSE, FALSE, TRUE); +} - if (inited) - return start; +void +mono_arch_exceptions_init (void) +{ + guint8 *tramp; - inited = 1; - code = start = mono_global_codeman_reserve (64); + /* LLVM needs different throw trampolines */ + tramp = get_throw_exception ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE); - x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4); /* token */ - x86_alu_reg_imm (code, X86_ADD, X86_EAX, MONO_TOKEN_TYPE_DEF); - x86_push_reg (code, X86_EAX); - x86_push_imm (code, mono_defaults.exception_class->image); - x86_call_code (code, mono_exception_from_token); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8); - /* Compute caller ip */ - x86_pop_reg (code, X86_ECX); - /* Pop token */ - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); - x86_pop_reg (code, X86_EDX); - x86_alu_reg_reg (code, X86_SUB, X86_ECX, X86_EDX); - /* Push exception object */ - x86_push_reg (code, X86_EAX); - /* Push throw IP */ - x86_push_reg (code, X86_ECX); - x86_jump_code (code, mono_arch_get_throw_exception ()); + mono_register_jit_icall (tramp, "mono_arch_llvm_throw_exception", NULL, TRUE); - g_assert ((code - start) < 64); + tramp = get_throw_exception ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE); - return start; + mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception", NULL, TRUE); } -/* mono_arch_find_jit_info: +/* + * mono_arch_find_jit_info_ext: * - * This function is used to gather information from @ctx. It return the - * MonoJitInfo of the corresponding function, unwinds one stack frame and - * stores the resulting context into @new_ctx. It also stores a string - * describing the stack location into @trace (if not NULL), and modifies - * the @lmf if necessary. @native_offset return the IP offset from the - * start of the function or -1 if that info is not available. + * See exceptions-amd64.c for docs. */ -MonoJitInfo * -mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, - MonoContext *new_ctx, MonoLMF **lmf, gboolean *managed) +gboolean +mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, + MonoContext *new_ctx, MonoLMF **lmf, + StackFrameInfo *frame) { - MonoJitInfo *ji; gpointer ip = MONO_CONTEXT_GET_IP (ctx); - /* Avoid costly table lookup during stack overflow */ - if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size))) - ji = prev_ji; - else - ji = mono_jit_info_table_find (domain, ip); - - if (managed) - *managed = FALSE; + memset (frame, 0, sizeof (StackFrameInfo)); + frame->ji = ji; + frame->managed = FALSE; *new_ctx = *ctx; @@ -598,9 +627,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf guint32 unwind_info_len; guint8 *unwind_info; - if (managed) - if (!ji->method->wrapper_type) - *managed = TRUE; + frame->type = FRAME_TYPE_MANAGED; + + if (!ji->method->wrapper_type || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) + frame->managed = TRUE; if (ji->from_aot) unwind_info = mono_aot_get_unwind_info (ji, &unwind_info_len); @@ -639,30 +669,51 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { /* remove any unused lmf */ - *lmf = (gpointer)(((guint32)(*lmf)->previous_lmf) & ~1); + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); } /* Pop arguments off the stack */ + /* + * FIXME: LLVM doesn't push these, we can't use ji->from_llvm as it describes + * the caller. + */ +#ifndef ENABLE_LLVM { MonoJitArgumentInfo *arg_info = g_newa (MonoJitArgumentInfo, mono_method_signature (ji->method)->param_count + 1); guint32 stack_to_pop = mono_arch_get_argument_info (mono_method_signature (ji->method), mono_method_signature (ji->method)->param_count, arg_info); new_ctx->esp += stack_to_pop; } +#endif - return ji; + return TRUE; } else if (*lmf) { - - *new_ctx = *ctx; - if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) { + 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)); + + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); + + frame->type = FRAME_TYPE_DEBUGGER_INVOKE; + + return TRUE; + } + + if ((ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL))) { } else { if (!((guint32)((*lmf)->previous_lmf) & 1)) /* Top LMF entry */ - return (gpointer)-1; + return FALSE; /* Trampoline lmf frame */ - memset (res, 0, sizeof (MonoJitInfo)); - res->method = (*lmf)->method; + frame->method = (*lmf)->method; } new_ctx->esi = (*lmf)->esi; @@ -671,6 +722,9 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf new_ctx->ebp = (*lmf)->ebp; new_ctx->eip = (*lmf)->eip; + frame->ji = ji; + frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; + /* Check if we are in a trampoline LMF frame */ if ((guint32)((*lmf)->previous_lmf) & 1) { /* lmf->esp is set by the trampoline code */ @@ -679,6 +733,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf /* Pop arguments off the stack */ /* FIXME: Handle the delegate case too ((*lmf)->method == NULL) */ /* FIXME: Handle the IMT/vtable case too */ +#ifndef ENABLE_LLVM if ((*lmf)->method && (*lmf)->method != MONO_FAKE_IMT_METHOD && (*lmf)->method != MONO_FAKE_VTABLE_METHOD) { MonoMethod *method = (*lmf)->method; MonoJitArgumentInfo *arg_info = g_newa (MonoJitArgumentInfo, mono_method_signature (method)->param_count + 1); @@ -686,18 +741,19 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf guint32 stack_to_pop = mono_arch_get_argument_info (mono_method_signature (method), mono_method_signature (method)->param_count, arg_info); new_ctx->esp += stack_to_pop; } +#endif } else /* the lmf is always stored on the stack, so the following * expression points to a stack location which can be used as ESP */ new_ctx->esp = (unsigned long)&((*lmf)->eip); - *lmf = (gpointer)(((guint32)(*lmf)->previous_lmf) & ~1); + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); - return ji ? ji : res; + return TRUE; } - return NULL; + return FALSE; } #ifdef __sun @@ -791,6 +847,9 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) mono_arch_sigctx_to_monoctx (sigctx, &mctx); + if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) + return TRUE; + mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only); mono_arch_monoctx_to_sigctx (&mctx, sigctx); @@ -832,6 +891,13 @@ altstack_handle_and_restore (void *sigctx, gpointer obj, gboolean stack_ovf) restore_context = mono_arch_get_restore_context (); mono_arch_sigctx_to_monoctx (sigctx, &mctx); + + if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) { + if (stack_ovf) + prepare_for_guard_pages (&mctx); + restore_context (&mctx); + } + mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, FALSE); if (stack_ovf) prepare_for_guard_pages (&mctx); @@ -844,7 +910,7 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean #ifdef MONO_ARCH_USE_SIGACTION MonoException *exc = NULL; ucontext_t *ctx = (ucontext_t*)sigctx; - MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (gpointer)UCONTEXT_REG_EIP (ctx)); + MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)UCONTEXT_REG_EIP (ctx), NULL); gpointer *sp; int frame_size; @@ -854,7 +920,7 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean */ if (!ji && fault_addr == (gpointer)UCONTEXT_REG_EIP (ctx)) { glong *sp = (gpointer)UCONTEXT_REG_ESP (ctx); - ji = mono_jit_info_table_find (mono_domain_get (), (gpointer)sp [0]); + ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)sp [0], NULL); if (ji) UCONTEXT_REG_EIP (ctx) = sp [0]; } @@ -893,3 +959,45 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean #endif } +#if MONO_SUPPORT_TASKLETS +MonoContinuationRestore +mono_tasklets_arch_restore (void) +{ + static guint8* saved = NULL; + guint8 *code, *start; + + if (saved) + return (MonoContinuationRestore)saved; + code = start = mono_global_codeman_reserve (48); + /* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */ + /* put cont in edx */ + x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4); + /* setup the copy of the stack */ + x86_mov_reg_membase (code, X86_ECX, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4); + x86_shift_reg_imm (code, X86_SHR, X86_ECX, 2); + x86_cld (code); + x86_mov_reg_membase (code, X86_ESI, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, saved_stack), 4); + x86_mov_reg_membase (code, X86_EDI, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, return_sp), 4); + x86_prefix (code, X86_REP_PREFIX); + x86_movsl (code); + + /* now restore the registers from the LMF */ + x86_mov_reg_membase (code, X86_ECX, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, lmf), 4); + x86_mov_reg_membase (code, X86_EBX, X86_ECX, G_STRUCT_OFFSET (MonoLMF, ebx), 4); + x86_mov_reg_membase (code, X86_EBP, X86_ECX, G_STRUCT_OFFSET (MonoLMF, ebp), 4); + x86_mov_reg_membase (code, X86_ESI, X86_ECX, G_STRUCT_OFFSET (MonoLMF, esi), 4); + x86_mov_reg_membase (code, X86_EDI, X86_ECX, G_STRUCT_OFFSET (MonoLMF, edi), 4); + + /* restore the lmf chain */ + /*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4); + x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/ + + /* state in eax, so it's setup as the return value */ + x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4); + x86_jump_membase (code, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, return_ip)); + g_assert ((code - start) <= 48); + saved = start; + return (MonoContinuationRestore)saved; +} +#endif +