/* * mono_arch_find_jit_info: * * See exceptions-amd64.c for docs. */ gboolean mono_arch_find_jit_info (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; 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 (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, lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS); memcpy (&new_ctx->regs, 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 = 0; i < MONO_SAVED_GREGS; ++i) regs [ppc_r13 + 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 = 0; i < MONO_SAVED_GREGS; ++i) new_ctx->regs [i] = regs [ppc_r13 + 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, (*lmf)->iregs, sizeof (mgreg_t) * MONO_SAVED_GREGS); memcpy (&new_ctx->fregs, (*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, and store it in @frame_info. * It unwinds one stack frame, and stores the resulting context into @new_ctx. @lmf * is modified if needed. * Returns TRUE on success, FALSE otherwise. */ gboolean mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, mgreg_t **save_locations, StackFrameInfo *frame) { memset (frame, 0, sizeof (StackFrameInfo)); frame->ji = ji; *new_ctx = *ctx; if (ji != NULL) { int i; gpointer ip = MONO_CONTEXT_GET_IP (ctx); mgreg_t regs [MONO_MAX_IREGS + 1]; guint8 *cfa; guint32 unwind_info_len; guint8 *unwind_info; frame->type = FRAME_TYPE_MANAGED; if (ji->from_aot) unwind_info = mono_aot_get_unwind_info (ji, &unwind_info_len); else unwind_info = mono_get_cached_unwind_info (ji->used_regs, &unwind_info_len); for (i = 0; i < MONO_MAX_IREGS; ++i) regs [i] = new_ctx->sc_regs [i]; mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, ip, regs, MONO_MAX_IREGS, save_locations, MONO_MAX_IREGS, &cfa); for (i = 0; i < MONO_MAX_IREGS; ++i) new_ctx->sc_regs [i] = regs [i]; new_ctx->sc_pc = regs [mips_ra]; new_ctx->sc_regs [mips_sp] = (mgreg_t)cfa; if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->iregs [mips_sp])) { /* remove any unused lmf */ *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); } /* we substract 8, so that the IP points into the call instruction */ MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_pc - 8); /* Sanity check -- we should have made progress here */ g_assert (MONO_CONTEXT_GET_SP (new_ctx) != MONO_CONTEXT_GET_SP (ctx)); return TRUE; } else if (*lmf) { if (((mgreg_t)(*lmf)->previous_lmf) & 2) { /* * This LMF entry is created by the soft debug code to mark transitions to * managed code done during invokes. */ MonoLMFExt *ext = (MonoLMFExt*)(*lmf); g_assert (ext->debugger_invoke); memcpy (new_ctx, &ext->ctx, sizeof (MonoContext)); *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); frame->type = FRAME_TYPE_DEBUGGER_INVOKE; return TRUE; } if (!(*lmf)->method) { #ifdef DEBUG_EXCEPTIONS g_print ("mono_arch_find_jit_info: bad lmf @ %p\n", (void *) *lmf); #endif return FALSE; } g_assert (((*lmf)->magic == MIPS_LMF_MAGIC1) || ((*lmf)->magic == MIPS_LMF_MAGIC2)); ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL); if (!ji) { // FIXME: This can happen with multiple appdomains (bug #444383) return FALSE; } frame->ji = ji; frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; memcpy (&new_ctx->sc_regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS); memcpy (&new_ctx->sc_fpregs, (*lmf)->fregs, sizeof (float) * MONO_SAVED_FREGS); MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip); /* ensure that we've made progress */ g_assert (new_ctx->sc_pc != ctx->sc_pc); *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); return TRUE; } return FALSE; }
/* * mono_arch_setup_resume_sighandler_ctx: * * Setup CTX so execution continues at FUNC. */ void mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) { MONO_CONTEXT_SET_IP (ctx,func); }
/* * mono_arch_unwind_frame: * * This function is used to gather information from @ctx, and store it in @frame_info. * It unwinds one stack frame, and stores the resulting context into @new_ctx. @lmf * is modified if needed. * Returns TRUE on success, FALSE otherwise. */ gboolean mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf, host_mgreg_t **save_locations, StackFrameInfo *frame) { memset (frame, 0, sizeof (StackFrameInfo)); frame->ji = ji; *new_ctx = *ctx; if (ji != NULL) { int i; gpointer ip = MONO_CONTEXT_GET_IP (ctx); host_mgreg_t regs [MONO_MAX_IREGS + 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); for (i = 0; i < MONO_MAX_IREGS; ++i) regs [i] = new_ctx->sc_regs [i]; gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, ip, NULL, regs, MONO_MAX_IREGS, save_locations, MONO_MAX_IREGS, &cfa); if (!success) return FALSE; for (i = 0; i < MONO_MAX_IREGS; ++i) new_ctx->sc_regs [i] = regs [i]; new_ctx->sc_pc = regs [mips_ra]; new_ctx->sc_regs [mips_sp] = (host_mgreg_t)(gsize)cfa; /* we substract 8, so that the IP points into the call instruction */ MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_pc - 8); /* Sanity check -- we should have made progress here */ g_assert (MONO_CONTEXT_GET_SP (new_ctx) != MONO_CONTEXT_GET_SP (ctx)); return TRUE; } else if (*lmf) { g_assert ((((guint64)(*lmf)->previous_lmf) & 2) == 0); if (!(*lmf)->method) { #ifdef DEBUG_EXCEPTIONS g_print ("mono_arch_unwind_frame: bad lmf @ %p\n", (void *) *lmf); #endif return FALSE; } g_assert (((*lmf)->magic == MIPS_LMF_MAGIC1) || ((*lmf)->magic == MIPS_LMF_MAGIC2)); ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL); if (!ji) { // FIXME: This can happen with multiple appdomains (bug #444383) return FALSE; } frame->ji = ji; frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; memcpy (&new_ctx->sc_regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS); memcpy (&new_ctx->sc_fpregs, (*lmf)->fregs, sizeof (float) * MONO_SAVED_FREGS); MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip); /* ensure that we've made progress */ g_assert (new_ctx->sc_pc != ctx->sc_pc); *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); return TRUE; } return FALSE; }