void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) { os_ucontext *uc = sigctx; UCONTEXT_REG_NIP(uc) = mctx->sc_ir; UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp; memcpy (&UCONTEXT_REG_Rn(uc, 13), &mctx->regs, sizeof (mgreg_t) * MONO_SAVED_GREGS); memcpy (&UCONTEXT_REG_FPRn(uc, 14), &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS); }
void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { os_ucontext *uc = sigctx; mctx->sc_ir = UCONTEXT_REG_NIP(uc); mctx->sc_sp = UCONTEXT_REG_Rn(uc, 1); memcpy (&mctx->regs, &UCONTEXT_REG_Rn(uc, 0), sizeof (mgreg_t) * MONO_MAX_IREGS); memcpy (&mctx->fregs, &UCONTEXT_REG_FPRn(uc, 0), sizeof (double) * MONO_MAX_FREGS); }
void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) { os_ucontext *uc = sigctx; memcpy (&UCONTEXT_REG_Rn(uc, 0), &mctx->regs, sizeof (mgreg_t) * MONO_MAX_IREGS); memcpy (&UCONTEXT_REG_FPRn(uc, 0), &mctx->fregs, sizeof (double) * MONO_MAX_FREGS); /* The valid values for pc and sp are stored here and not in regs array */ UCONTEXT_REG_NIP(uc) = mctx->sc_ir; UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp; }
void mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); #else os_ucontext *uc = ctx; UCONTEXT_REG_NIP(uc) = mctx->sc_ir; UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp; memcpy (&UCONTEXT_REG_Rn(uc, 13), &mctx->regs, sizeof (mgreg_t) * MONO_SAVED_GREGS); memcpy (&UCONTEXT_REG_FPRn(uc, 14), &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS); #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_tls_get_jit_tls (); mgreg_t sp; void *sigctx = ctx; int frame_size; void *uc = sigctx; /* Pass the ctx parameter in TLS */ mono_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_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_monoctx_to_sigctx (&mctx, ctx); return result; #endif }
static void setup_ucontext_return (void *uc, gpointer func) { #if !defined(MONO_CROSS_COMPILE) UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc); #ifdef PPC_USES_FUNCTION_DESCRIPTOR { MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)func; UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code; UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc; } #else UCONTEXT_REG_NIP(uc) = (unsigned long)func; #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) func; #endif #endif #endif }
void mono_ppc_set_func_into_sigctx (void *sigctx, void *func) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); #elif defined(PPC_USES_FUNCTION_DESCRIPTOR) /* Have to set both the ip and the TOC reg */ os_ucontext *uc = sigctx; UCONTEXT_REG_NIP(uc) = ((gsize*)func) [0]; UCONTEXT_REG_Rn (uc, 2) = ((gsize*)func)[1]; #else g_assert_not_reached (); #endif }
static void setup_ucontext_return (void *uc, gpointer func) { #if !defined(MONO_CROSS_COMPILE) UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc); #ifdef PPC_USES_FUNCTION_DESCRIPTOR { MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)func; UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code; UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc; } #else UCONTEXT_REG_NIP(uc) = (unsigned long)func; #endif #endif }
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 */ }