void mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data) { mgreg_t sp = (mgreg_t)MONO_CONTEXT_GET_SP (ctx); // FIXME: g_assert (!user_data); /* Allocate a stack frame */ sp -= 32; MONO_CONTEXT_SET_SP (ctx, sp); mono_arch_setup_resume_sighandler_ctx (ctx, async_cb); }
void mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data) { mgreg_t sp = (mgreg_t)MONO_CONTEXT_GET_SP (ctx); // FIXME: g_assert (!user_data); /* Allocate a stack frame */ sp -= 16; MONO_CONTEXT_SET_SP (ctx, sp); MONO_CONTEXT_SET_IP (ctx, async_cb); // FIXME: thumb/arm }
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_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); }