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 }
/* * This is the function called from the signal handler */ gboolean mono_arch_handle_exception (void *ctx, gpointer obj) { #if defined(MONO_CROSS_COMPILE) || !defined(MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX) g_assert_not_reached (); #elif defined(MONO_ARCH_USE_SIGACTION) arm_ucontext *sigctx = ctx; /* * 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); guint64 sp = UCONTEXT_REG_SP (sigctx); /* Pass the ctx parameter in TLS */ mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); /* The others in registers */ UCONTEXT_REG_R0 (sigctx) = (gsize)obj; /* Allocate a stack frame */ sp -= 16; UCONTEXT_REG_SP (sigctx) = sp; UCONTEXT_REG_PC (sigctx) = (gsize)get_handle_signal_exception_addr (); #ifdef UCONTEXT_REG_CPSR if ((gsize)UCONTEXT_REG_PC (sigctx) & 1) /* Transition to thumb */ UCONTEXT_REG_CPSR (sigctx) |= (1 << 5); else /* Transition to ARM */ UCONTEXT_REG_CPSR (sigctx) &= ~(1 << 5); #endif return TRUE; #else MonoContext mctx; gboolean result; mono_arch_sigctx_to_monoctx (ctx, &mctx); result = mono_handle_exception (&mctx, obj); /* restore the context so that returning from the signal handler will invoke * the catch clause */ mono_arch_monoctx_to_sigctx (&mctx, ctx); return result; #endif }
gboolean mono_arch_handle_exception (void *ctx, gpointer obj) { #if defined(MONO_ARCH_USE_SIGACTION) && defined(UCONTEXT_REG_Rn) /* * 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); mgreg_t sp; void *sigctx = ctx; int frame_size; void *uc = sigctx; /* Pass the ctx parameter in TLS */ mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); /* The others in registers */ UCONTEXT_REG_Rn (sigctx, PPC_FIRST_ARG_REG) = (gsize)obj; /* Allocate a stack frame below the red zone */ /* Similar to mono_arch_handle_altstack_exception () */ frame_size = 224; frame_size += 15; frame_size &= ~15; sp = (mgreg_t)(UCONTEXT_REG_Rn(uc, 1) & ~15); sp = (mgreg_t)(sp - frame_size); UCONTEXT_REG_Rn(uc, 1) = (mgreg_t)sp; setup_ucontext_return (uc, handle_signal_exception); return TRUE; #else MonoContext mctx; gboolean result; mono_arch_sigctx_to_monoctx (ctx, &mctx); result = mono_handle_exception (&mctx, obj); /* restore the context so that returning from the signal handler will invoke * the catch clause */ mono_arch_monoctx_to_sigctx (&mctx, ctx); return result; #endif }
static void altstack_handle_and_restore (void *sigctx, gpointer obj) { MonoContext mctx; mono_arch_sigctx_to_monoctx (sigctx, &mctx); mono_handle_exception (&mctx, obj); mono_restore_context (&mctx); }
/* Special hack to workaround the fact that the * when the SEH handler is called the stack is * to small to recover. * * Stack walking part of this method is from mono_handle_exception * * The idea is simple; * - walk the stack to free some space (64k) * - set esp to new stack location * - call mono_arch_handle_exception with stack overflow exception * - set esp to SEH handlers stack * - done */ static void win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx) { SYSTEM_INFO si; DWORD page_size; MonoDomain *domain = mono_domain_get (); MonoJitInfo rji; MonoJitTlsData *jit_tls = mono_native_tls_get_value (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); page_size = si.dwPageSize; /* Let's walk the stack to recover * the needed stack space (if possible) */ memset (&rji, 0, sizeof (rji)); initial_ctx = ctx; free_stack = (guint8*)(MONO_CONTEXT_GET_BP (&ctx)) - (guint8*)(MONO_CONTEXT_GET_BP (&initial_ctx)); /* try to free 64kb from our stack */ do { MonoContext new_ctx; mono_arch_find_jit_info (domain, jit_tls, &rji, &ctx, &new_ctx, &lmf, NULL, &frame); if (!frame.ji) { g_warning ("Exception inside function without unwind info"); g_assert_not_reached (); } 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 && frame.ji != (gpointer) -1); /* convert into sigcontext to be used in mono_arch_handle_exception */ mono_arch_monoctx_to_sigctx (&ctx, sctx); /* todo: install new stack-guard page */ /* use the new stack and call mono_arch_handle_exception () */ restore_stack (sctx); }
/* * This is the function called from the signal handler */ gboolean mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only) { #if defined(MONO_CROSS_COMPILE) g_assert_not_reached (); #elif defined(MONO_ARCH_USE_SIGACTION) arm_ucontext *sigctx = ctx; /* * 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_SP (sigctx); /* Pass the ctx parameter in TLS */ mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); /* The others in registers */ UCONTEXT_REG_R0 (sigctx) = (gsize)obj; UCONTEXT_REG_R1 (sigctx) = test_only; /* Allocate a stack frame */ sp -= 16; UCONTEXT_REG_SP (sigctx) = sp; UCONTEXT_REG_PC (sigctx) = (gsize)handle_signal_exception; return TRUE; #else MonoContext mctx; gboolean result; mono_arch_sigctx_to_monoctx (ctx, &mctx); result = mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only); /* restore the context so that returning from the signal handler will invoke * the catch clause */ mono_arch_monoctx_to_sigctx (&mctx, ctx); return result; #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; }
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 }
static void SIG_HANDLER_SIGNATURE (sigprof_signal_handler) { int call_chain_depth = mono_profiler_stat_get_call_chain_depth (); MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy (); GET_CONTEXT; if (call_chain_depth == 0) { mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx); } else { MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); int current_frame_index = 1; MonoContext mono_context; guchar *ips [call_chain_depth + 1]; mono_arch_sigctx_to_monoctx (ctx, &mono_context); ips [0] = MONO_CONTEXT_GET_IP (&mono_context); if (jit_tls != NULL) { if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) { #if FULL_STAT_PROFILER_BACKTRACE guchar *current_frame; guchar *stack_bottom; guchar *stack_top; stack_bottom = jit_tls->end_of_stack; stack_top = MONO_CONTEXT_GET_SP (&mono_context); current_frame = MONO_CONTEXT_GET_BP (&mono_context); while ((current_frame_index <= call_chain_depth) && (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) && ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) { ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame); current_frame_index ++; stack_top = current_frame; current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame); } #else call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC; #endif } if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) { #if GLIBC_PROFILER_BACKTRACE current_frame_index = backtrace ((void**) & ips [1], call_chain_depth); #else call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED; #endif } if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) { MonoDomain *domain = mono_domain_get (); if (domain != NULL) { MonoLMF *lmf = NULL; MonoJitInfo *ji; MonoJitInfo res; MonoContext new_mono_context; int native_offset; ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, &new_mono_context, NULL, &lmf, &native_offset, NULL); while ((ji != NULL) && (current_frame_index <= call_chain_depth)) { ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context); current_frame_index ++; mono_context = new_mono_context; ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, &new_mono_context, NULL, &lmf, &native_offset, NULL); } } } } mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx); } mono_chain_signal (SIG_HANDLER_PARAMS); }