void mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs) { MonoContext ctx; gboolean rethrow = pc & 1; pc &= ~1; /* clear the optional rethrow bit */ /* adjust eip so that it point into the call instruction */ pc -= 4; /*printf ("stack in throw: %p\n", esp);*/ MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]); MONO_CONTEXT_SET_SP (&ctx, sp); MONO_CONTEXT_SET_IP (&ctx, pc); memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t)); memcpy (&ctx.fregs, fp_regs, sizeof (double) * 16); if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) mono_ex->stack_trace = NULL; } mono_handle_exception (&ctx, exc); mono_restore_context (&ctx); g_assert_not_reached (); }
void mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow) { MonoError error; MonoContext ctx; /* adjust eip so that it point into the call instruction */ eip -= 4; setup_context (&ctx); /*printf ("stack in throw: %p\n", esp);*/ MONO_CONTEXT_SET_BP (&ctx, esp); MONO_CONTEXT_SET_IP (&ctx, eip); memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_MAX_IREGS); memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_MAX_FREGS); if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } } mono_error_assert_ok (&error); mono_handle_exception (&ctx, exc); mono_restore_context (&ctx); g_assert_not_reached (); }
void mono_arm_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong *int_regs, gdouble *fp_regs) { static void (*restore_context) (MonoContext *); MonoContext ctx; gboolean rethrow = eip & 1; if (!restore_context) restore_context = mono_get_restore_context (); eip &= ~1; /* clear the optional rethrow bit */ /* adjust eip so that it point into the call instruction */ eip -= 4; /*printf ("stack in throw: %p\n", esp);*/ MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]); MONO_CONTEXT_SET_SP (&ctx, esp); MONO_CONTEXT_SET_IP (&ctx, eip); memcpy (((guint8*)&ctx.regs) + (4 * 4), int_regs, sizeof (gulong) * 8); /* memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS); */ if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) mono_ex->stack_trace = NULL; } mono_handle_exception (&ctx, exc, (gpointer)(eip + 4), FALSE); restore_context (&ctx); g_assert_not_reached (); }
// FIX ME: This is not complete void mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data) { uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx); sp -= PPC_MINIMAL_STACK_SIZE; *(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx); MONO_CONTEXT_SET_BP(ctx, sp); MONO_CONTEXT_SET_IP(ctx, (unsigned long) async_cb); }
// FIX ME: This is not complete void mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data) { uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx); ctx->regs [PPC_FIRST_ARG_REG] = user_data; sp -= PPC_MINIMAL_STACK_SIZE; *(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx); MONO_CONTEXT_SET_BP(ctx, sp); mono_arch_setup_resume_sighandler_ctx(ctx, (unsigned long) async_cb); }
void mono_arm_resume_unwind (guint32 dummy1, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs) { MonoContext ctx; pc &= ~1; /* clear the optional rethrow bit */ /* adjust eip so that it point into the call instruction */ pc -= 4; MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]); MONO_CONTEXT_SET_SP (&ctx, sp); MONO_CONTEXT_SET_IP (&ctx, pc); memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t)); mono_resume_unwind (&ctx); }
static void mono_arm_resume_unwind (guint32 dummy1, unsigned long eip, unsigned long esp, gulong *int_regs, gdouble *fp_regs) { MonoContext ctx; eip &= ~1; /* clear the optional rethrow bit */ /* adjust eip so that it point into the call instruction */ eip -= 4; MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]); MONO_CONTEXT_SET_SP (&ctx, esp); MONO_CONTEXT_SET_IP (&ctx, eip); memcpy (((guint8*)&ctx.regs) + (4 * 4), int_regs, sizeof (gulong) * 8); mono_resume_unwind (&ctx); }
/* * mono_arch_unwind_frame: * * See exceptions-amd64.c for docs. */ gboolean mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, mgreg_t **save_locations, StackFrameInfo *frame) { gpointer ip = MONO_CONTEXT_GET_IP (ctx); MonoPPCStackFrame *sframe; memset (frame, 0, sizeof (StackFrameInfo)); frame->ji = ji; *new_ctx = *ctx; setup_context (new_ctx); if (ji != NULL) { int i; mgreg_t regs [ppc_lr + 1]; guint8 *cfa; guint32 unwind_info_len; guint8 *unwind_info; if (ji->is_trampoline) frame->type = FRAME_TYPE_TRAMPOLINE; else frame->type = FRAME_TYPE_MANAGED; unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len); sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx); MONO_CONTEXT_SET_BP (new_ctx, sframe->sp); if (!ji->is_trampoline && jinfo_get_method (ji)->save_lmf) { /* sframe->sp points just past the end of the LMF */ guint8 *lmf_addr = (guint8*)sframe->sp - sizeof (MonoLMF); memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS); memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, iregs), sizeof (mgreg_t) * MONO_SAVED_GREGS); /* the calling IP is in the parent frame */ sframe = (MonoPPCStackFrame*)sframe->sp; /* we substract 4, so that the IP points into the call instruction */ MONO_CONTEXT_SET_IP (new_ctx, sframe->lr - 4); } else { regs [ppc_lr] = ctx->sc_ir; regs [ppc_sp] = ctx->sc_sp; for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i) regs [i] = ctx->regs [i]; mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, ip, NULL, regs, ppc_lr + 1, save_locations, MONO_MAX_IREGS, &cfa); /* we substract 4, so that the IP points into the call instruction */ MONO_CONTEXT_SET_IP (new_ctx, regs [ppc_lr] - 4); MONO_CONTEXT_SET_BP (new_ctx, cfa); for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i) new_ctx->regs [i] = regs [i]; } return TRUE; } else if (*lmf) { if ((ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL))) { } else { if (!(*lmf)->method) return FALSE; /* Trampoline lmf frame */ frame->method = (*lmf)->method; } /*sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx); MONO_CONTEXT_SET_BP (new_ctx, sframe->sp); MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/ MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp); MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip); memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], (*lmf)->iregs, sizeof (mgreg_t) * MONO_SAVED_GREGS); memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS); frame->ji = ji; frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; /* FIXME: what about trampoline LMF frames? see exceptions-x86.c */ *lmf = (*lmf)->previous_lmf; return TRUE; } return FALSE; }
/* mono_arch_find_jit_info: * * This function is used to gather information from @ctx. It returns the * MonoJitInfo of the corresponding function, unwinds one stack frame and * stores the resulting context into @new_ctx. It also stores a string * describing the stack location into @trace (if not NULL), and modifies * the @lmf if necessary. @native_offset return the IP offset from the * start of the function or -1 if that info is not available. */ MonoJitInfo * mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, gboolean *managed) { MonoJitInfo *ji; gpointer ip = MONO_CONTEXT_GET_IP (ctx); gpointer fp = MONO_CONTEXT_GET_BP (ctx); guint32 sp; /* Avoid costly table lookup during stack overflow */ if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size))) ji = prev_ji; else ji = mini_jit_info_table_find (domain, ip, NULL); if (managed) *managed = FALSE; memcpy (new_ctx, ctx, sizeof (MonoContext)); if (ji != NULL) { int i; gint32 address; int offset = 0; if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { /* remove any unused lmf */ *lmf = (*lmf)->previous_lmf; } address = (char *)ip - (char *)ji->code_start; if (managed) if (!ji->method->wrapper_type) *managed = TRUE; /* My stack frame */ fp = MONO_CONTEXT_GET_BP (ctx); /* Compute the previous stack frame */ sp = (guint32)(fp) - (short)(*(guint32 *)(ji->code_start)); /* Sanity check the frame */ if (!sp || (sp == 0xffffffff) || (sp & 0x07) || (sp < 64*1024)) { #ifdef DEBUG_EXCEPTIONS g_print ("mono_arch_find_jit_info: bad stack sp=%p\n", (void *) sp); #endif return (gpointer)-1; } if (ji->method->save_lmf && 0) { /* only enable this when prologue stops emitting * normal save of s-regs when save_lmf is true. * Will have to sync with prologue code at that point. */ memcpy (&new_ctx->sc_fpregs, (char*)sp - sizeof (float) * MONO_SAVED_FREGS, sizeof (float) * MONO_SAVED_FREGS); memcpy (&new_ctx->sc_regs, (char*)sp - sizeof (float) * MONO_SAVED_FREGS - sizeof (gulong) * MONO_SAVED_GREGS, sizeof (gulong) * MONO_SAVED_GREGS); } else if (ji->used_regs) { guint32 *insn; guint32 mask = ji->used_regs; /* these all happen before adjustment of fp */ /* Look for sw ??, ????(sp) */ insn = ((guint32 *)ji->code_start) + 1; while (!*insn || ((*insn & 0xffe00000) == 0xafa00000) || ((*insn & 0xffe00000) == 0xffa00000)) { int reg = (*insn >> 16) & 0x1f; guint32 addr = (((guint32)fp) + (short)(*insn & 0x0000ffff)); mask &= ~(1 << reg); if ((*insn & 0xffe00000) == 0xafa00000) new_ctx->sc_regs [reg] = *(guint32 *)addr; else new_ctx->sc_regs [reg] = *(guint64 *)addr; insn++; } MONO_CONTEXT_SET_SP (new_ctx, sp); MONO_CONTEXT_SET_BP (new_ctx, sp); /* assert that we found all registers we were supposed to */ g_assert (!mask); }