/* * mono_x86_throw_exception: * * C function called from the throw trampolines. */ 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]; 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); restore_context (&ctx); g_assert_not_reached (); }
/* * The first few arguments are dummy, to force the other arguments to be passed on * the stack, this avoids overwriting the argument registers in the throw trampoline. */ void mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, guint64 dummy5, guint64 dummy6, mgreg_t *regs, mgreg_t rip, MonoObject *exc, gboolean rethrow) { static void (*restore_context) (MonoContext *); MonoContext ctx; if (!restore_context) restore_context = mono_get_restore_context (); ctx.rsp = regs [AMD64_RSP]; ctx.rip = rip; ctx.rbx = regs [AMD64_RBX]; ctx.rbp = regs [AMD64_RBP]; ctx.r12 = regs [AMD64_R12]; ctx.r13 = regs [AMD64_R13]; ctx.r14 = regs [AMD64_R14]; ctx.r15 = regs [AMD64_R15]; ctx.rdi = regs [AMD64_RDI]; ctx.rsi = regs [AMD64_RSI]; ctx.rax = regs [AMD64_RAX]; ctx.rcx = regs [AMD64_RCX]; ctx.rdx = regs [AMD64_RDX]; 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]; mono_breakpoint_clean_code (NULL, (gpointer)rip, 8, buf, sizeof (buf)); if (buf [3] == 0xe8) { MonoContext ctx_cp = ctx; ctx_cp.rip = rip - 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.rip -= 1; mono_handle_exception (&ctx, exc); restore_context (&ctx); g_assert_not_reached (); }
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { #if defined(MONO_ARCH_USE_SIGACTION) MonoContext mctx; ucontext_t *ctx = (ucontext_t*)sigctx; /* * Handling the exception in the signal handler is problematic, since the original * signal is disabled, and we could run arbitrary code though the debugger. So * resume into the normal stack and do most work there if possible. */ MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); /* Pass the ctx parameter in TLS */ mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx); g_assert (!test_only); mctx = jit_tls->ex_ctx; mono_setup_async_callback (&mctx, handle_signal_exception, obj); mono_monoctx_to_sigctx (&mctx, sigctx); return TRUE; #elif defined (TARGET_WIN32) MonoContext mctx; MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); struct sigcontext *ctx = (struct sigcontext *)sigctx; mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); g_assert (!test_only); mctx = jit_tls->ex_ctx; mono_setup_async_callback (&mctx, handle_signal_exception, obj); mono_monoctx_to_sigctx (&mctx, sigctx); return TRUE; #else MonoContext mctx; 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); return TRUE; #endif }
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { MonoContext mctx; 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); return TRUE; }
/* * handle_exception: * * Called by resuming from a signal handler. */ static void 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); }
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); }
static void altstack_handle_and_restore (void *sigctx, gpointer obj, gboolean stack_ovf) { void (*restore_context) (MonoContext *); MonoContext mctx; restore_context = mono_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); restore_context (&mctx); }
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { #if defined(MONO_ARCH_USE_SIGACTION) ucontext_t *ctx = (ucontext_t*)sigctx; /* * Handling the exception in the signal handler is problematic, since the original * signal is disabled, and we could run arbitrary code though the debugger. So * resume into the normal stack and do most work there if possible. */ MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); guint64 sp = UCONTEXT_REG_ESP (ctx); /* Pass the ctx parameter in TLS */ mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx); /* * Can't pass the obj on the stack, since we are executing on the * same stack. Can't save it into MonoJitTlsData, since it needs GC tracking. * So put it into a register, and branch to a trampoline which * pushes it. */ g_assert (!test_only); UCONTEXT_REG_EAX (ctx) = (gsize)obj; UCONTEXT_REG_ECX (ctx) = UCONTEXT_REG_EIP (ctx); UCONTEXT_REG_EDX (ctx) = (gsize)handle_signal_exception; /* Allocate a stack frame, align it to 16 bytes which is needed on apple */ sp -= 16; sp &= ~15; UCONTEXT_REG_ESP (ctx) = sp; UCONTEXT_REG_EIP (ctx) = (gsize)signal_exception_trampoline; return TRUE; #elif defined (TARGET_WIN32) MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); struct sigcontext *ctx = (struct sigcontext *)sigctx; guint64 sp = ctx->SC_ESP; mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); /* * Can't pass the obj on the stack, since we are executing on the * same stack. Can't save it into MonoJitTlsData, since it needs GC tracking. * So put it into a register, and branch to a trampoline which * pushes it. */ g_assert (!test_only); ctx->SC_EAX = (gsize)obj; ctx->SC_ECX = ctx->SC_EIP; ctx->SC_EDX = (gsize)handle_signal_exception; /* Allocate a stack frame, align it to 16 bytes which is needed on apple */ sp -= 16; sp &= ~15; ctx->SC_ESP = sp; ctx->SC_EIP = (gsize)signal_exception_trampoline; return TRUE; #else MonoContext mctx; 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); return TRUE; #endif }