SIG_HANDLER_FUNC (static, sigabrt_signal_handler) { MonoJitInfo *ji = NULL; GET_CONTEXT; if (mono_thread_internal_current ()) ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx)); if (!ji) { if (mono_chain_signal (SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGABRT, ctx); } }
MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler) { MonoJitInfo *ji = NULL; MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO (); MONO_SIG_HANDLER_GET_CONTEXT; if (mono_thread_internal_current ()) ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE); if (!ji) { if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_crash ("SIGABRT", ctx, info); } }
MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler) { int old_errno = errno; MONO_SIG_HANDLER_GET_CONTEXT; /* See the comment in mono_runtime_shutdown_stat_profiler (). */ if (mono_native_thread_id_get () == sampling_thread) { mono_atomic_inc_i32 (&profiler_interrupt_signals_received); return; } mono_atomic_inc_i32 (&profiler_signals_received); // Did a non-attached or detaching thread get the signal? if (mono_thread_info_get_small_id () == -1 || !mono_domain_get () || !mono_tls_get_jit_tls ()) { errno = old_errno; return; } // See the comment in sampling_thread_func (). mono_atomic_store_i32 (&mono_thread_info_current ()->profiler_signal_ack, 1); mono_atomic_inc_i32 (&profiler_signals_accepted); int hp_save_index = mono_hazard_pointer_save_for_signal_handler (); mono_thread_info_set_is_async_context (TRUE); MONO_PROFILER_RAISE (sample_hit, (mono_arch_ip_from_context (ctx), ctx)); mono_thread_info_set_is_async_context (FALSE); mono_hazard_pointer_restore_for_signal_handler (hp_save_index); errno = old_errno; mono_chain_signal (MONO_SIG_HANDLER_PARAMS); }
void mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); #else #ifdef MONO_ARCH_USE_SIGACTION os_ucontext *uc = (ucontext_t*)sigctx; os_ucontext *uc_copy; MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (sigctx), NULL); gpointer *sp; int frame_size; if (stack_ovf) { const char *method; /* we don't do much now, but we can warn the user with a useful message */ fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1)); if (ji && !ji->is_trampoline && jinfo_get_method (ji)) method = mono_method_full_name (jinfo_get_method (ji), TRUE); else method = "Unmanaged"; fprintf (stderr, "At %s\n", method); abort (); } if (!ji) mono_handle_native_crash ("SIGSEGV", sigctx, siginfo); /* setup a call frame on the real stack so that control is returned there * and exception handling can continue. * The frame looks like: * ucontext struct * ... * 224 is the size of the red zone */ frame_size = sizeof (ucontext_t) + sizeof (gpointer) * 16 + 224; frame_size += 15; frame_size &= ~15; sp = (gpointer)(UCONTEXT_REG_Rn(uc, 1) & ~15); sp = (gpointer)((char*)sp - frame_size); /* may need to adjust pointers in the new struct copy, depending on the OS */ uc_copy = (ucontext_t*)(sp + 16); memcpy (uc_copy, uc, sizeof (os_ucontext)); #if defined(__linux__) && !defined(__mono_ppc64__) uc_copy->uc_mcontext.uc_regs = (gpointer)((char*)uc_copy + ((char*)uc->uc_mcontext.uc_regs - (char*)uc)); #endif g_assert (mono_arch_ip_from_context (uc) == mono_arch_ip_from_context (uc_copy)); /* at the return form the signal handler execution starts in altstack_handle_and_restore() */ UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc); #ifdef PPC_USES_FUNCTION_DESCRIPTOR { MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)altstack_handle_and_restore; UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code; UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc; } #else UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore; #if _CALL_ELF == 2 /* ELF v2 ABI calling convention requires to put the target address into * r12 if we use the global entry point of a function. */ UCONTEXT_REG_Rn(uc, 12) = (unsigned long) altstack_handle_and_restore; #endif #endif UCONTEXT_REG_Rn(uc, 1) = (unsigned long)sp; UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG) = (unsigned long)(sp + 16); UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 1) = 0; UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 2) = 0; #endif #endif /* !MONO_CROSS_COMPILE */ }
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); }
static void SIG_HANDLER_SIGNATURE (sigusr1_signal_handler) { gboolean running_managed; MonoException *exc; MonoInternalThread *thread = mono_thread_internal_current (); MonoDomain *domain = mono_domain_get (); void *ji; GET_CONTEXT; if (!thread || !domain) /* The thread might not have started up yet */ /* FIXME: Specify the synchronization with start_wrapper () in threads.c */ return; if (thread->thread_dump_requested) { thread->thread_dump_requested = FALSE; mono_print_thread_dump (ctx); } /* * This is an async signal, so the code below must not call anything which * is not async safe. That includes the pthread locking functions. If we * know that we interrupted managed code, then locking is safe. */ /* * On OpenBSD, ctx can be NULL if we are interrupting poll (). */ if (ctx) { ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx)); running_managed = ji != NULL; if (mono_debugger_agent_thread_interrupt (ctx, ji)) return; } else { running_managed = FALSE; } /* We can't do handler block checking from metadata since it requires doing * a stack walk with context. * * FIXME add full-aot support. */ #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX if (!mono_aot_only && ctx) { MonoThreadUnwindState unwind_state; if (mono_thread_state_init_from_sigctx (&unwind_state, ctx)) { if (mono_install_handler_block_guard (&unwind_state)) { #ifndef HOST_WIN32 /*Clear current thread from been wapi interrupted otherwise things can go south*/ wapi_clear_interruption (); #endif return; } } } #endif exc = mono_thread_request_interruption (running_managed); if (!exc) return; mono_arch_handle_exception (ctx, exc, FALSE); }