void mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf) { #ifdef MONO_ARCH_USE_SIGACTION MonoException *exc = NULL; ucontext_t *ctx = (ucontext_t*)sigctx; MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)UCONTEXT_REG_EIP (ctx), NULL); gpointer *sp; int frame_size; /* if we didn't find a managed method for the ip address and it matches the fault * address, we assume we followed a broken pointer during an indirect call, so * we try the lookup again with the return address pushed on the stack */ if (!ji && fault_addr == (gpointer)UCONTEXT_REG_EIP (ctx)) { glong *sp = (gpointer)UCONTEXT_REG_ESP (ctx); ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)sp [0], NULL); if (ji) UCONTEXT_REG_EIP (ctx) = sp [0]; } if (stack_ovf) exc = mono_domain_get ()->stack_overflow_ex; 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. * If this was a stack overflow the caller already ensured the stack pages * needed have been unprotected. * The frame looks like: * ucontext struct * test_only arg * exception arg * ctx arg * return ip */ // FIXME: test_only is no more. frame_size = sizeof (MonoContext) + sizeof (gpointer) * 4; frame_size += 15; frame_size &= ~15; sp = (gpointer)(UCONTEXT_REG_ESP (ctx) & ~15); sp = (gpointer)((char*)sp - frame_size); /* the incoming arguments are aligned to 16 bytes boundaries, so the return address IP * goes at sp [-1] */ sp [-1] = (gpointer)UCONTEXT_REG_EIP (ctx); sp [0] = sp + 4; sp [1] = exc; sp [2] = (gpointer)stack_ovf; mono_sigctx_to_monoctx (sigctx, (MonoContext*)(sp + 4)); /* at the return form the signal handler execution starts in altstack_handle_and_restore() */ UCONTEXT_REG_EIP (ctx) = (unsigned long)altstack_handle_and_restore; UCONTEXT_REG_ESP (ctx) = (unsigned long)(sp - 1); #endif }
LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) { #ifndef MONO_CROSS_COMPILE if (mono_old_win_toplevel_exception_filter) { return (*mono_old_win_toplevel_exception_filter)(ep); } #endif mono_handle_native_crash ("SIGSEGV", NULL, NULL); return EXCEPTION_CONTINUE_SEARCH; }
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); } }
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 */ }