X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-mips.c;h=abfe26ce30021bdf7b6fa949ad21c3cff9180236;hb=8f09dad4353bb75afebf96ad58d08f7e7f3bf56d;hp=e2af85b9c57eb8a7c9367fd349ff952edf289803;hpb=10727c04b7e60451d56b79e6711dc9d456d18178;p=mono.git diff --git a/mono/mini/exceptions-mips.c b/mono/mini/exceptions-mips.c index e2af85b9c57..abfe26ce300 100644 --- a/mono/mini/exceptions-mips.c +++ b/mono/mini/exceptions-mips.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -31,26 +30,6 @@ #define GENERIC_EXCEPTION_SIZE 256 -/* XXX */ -#if 1 -#define restore_regs_from_context(ctx_reg,ip_reg,tmp_reg) do { \ - } while (0) -#else -#define restore_regs_from_context(ctx_reg,pc,tmp_reg) do { \ - int reg; \ - ppc_lwz (code, pc, G_STRUCT_OFFSET (MonoContext, sc_pc), ctx_reg); \ - ppc_lmw (code, ppc_r13, ctx_reg, G_STRUCT_OFFSET (MonoContext, sc_regs)); \ - for (reg = 0; reg < MONO_SAVED_FREGS; ++reg) { \ - ppc_lfd (code, (14 + reg), G_STRUCT_OFFSET(MonoLMF, sc_fpregs) + reg * sizeof (gdouble), ctx_reg); \ - } \ - } while (0) -#endif - -/* nothing to do */ -#define setup_context(ctx) do { \ - memset ((ctx), 0, sizeof(*(ctx))); \ - } while (0); - /* * mono_arch_get_restore_context: * @@ -62,7 +41,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) { int i; guint8 *code; - static guint8 start [128]; + static guint8 start [512]; static int inited = 0; guint32 iregs_to_restore; @@ -75,16 +54,19 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) inited = 1; code = start; + mips_move (code, mips_at, mips_a0); + iregs_to_restore = (MONO_ARCH_CALLEE_SAVED_REGS \ | (1 << mips_sp) | (1 << mips_ra)); for (i = 0; i < MONO_SAVED_GREGS; ++i) { - if (iregs_to_restore & (1 << i)) { - MIPS_LW (code, i, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_regs[i])); + //if (iregs_to_restore & (1 << i)) { + if (i != mips_zero && i != mips_at) { + MIPS_LW (code, i, mips_at, G_STRUCT_OFFSET (MonoContext, sc_regs[i])); } } /* Get the address to return to */ - mips_lw (code, mips_t9, mips_a0, G_STRUCT_OFFSET (MonoContext, sc_pc)); + mips_lw (code, mips_t9, mips_at, G_STRUCT_OFFSET (MonoContext, sc_pc)); /* jump to the saved IP */ mips_jr (code, mips_t9); @@ -192,7 +174,6 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) static void throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow) { - static void (*restore_context) (MonoContext *); MonoContext ctx; #ifdef DEBUG_EXCEPTIONS @@ -200,13 +181,10 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean exc, (void *)eip, (void *) esp, rethrow); #endif - if (!restore_context) - restore_context = mono_get_restore_context (); - /* adjust eip so that it point into the call instruction */ eip -= 8; - setup_context (&ctx); + memset (&ctx, 0, sizeof (MonoContext)); /*g_print ("stack in throw: %p\n", esp);*/ memcpy (&ctx.sc_regs, (void *)(esp + MIPS_STACK_PARAM_OFFSET), @@ -219,13 +197,13 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean if (!rethrow) mono_ex->stack_trace = NULL; } - mono_handle_exception (&ctx, exc, (void *)eip, FALSE); + mono_handle_exception (&ctx, exc); #ifdef DEBUG_EXCEPTIONS g_print ("throw_exception: restore to pc=%p sp=%p fp=%p ctx=%p\n", (void *) ctx.sc_pc, (void *) ctx.sc_regs[mips_sp], (void *) ctx.sc_regs[mips_fp], &ctx); #endif - restore_context (&ctx); + mono_restore_context (&ctx); g_assert_not_reached (); } @@ -396,220 +374,204 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE); inited = 1; return start; -} - -static MonoArray * -glist_to_array (GList *list, MonoClass *eclass) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - int len, i; - - if (!list) - return NULL; - - len = g_list_length (list); - res = mono_array_new (domain, eclass, len); - - for (i = 0; list; list = list->next, i++) - mono_array_set (res, gpointer, i, list->data); - - return res; } -/* mono_arch_find_jit_info: +/* + * 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. + * 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. */ -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) +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) { - 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); + memset (frame, 0, sizeof (StackFrameInfo)); + frame->ji = ji; - if (managed) - *managed = FALSE; - - memcpy (new_ctx, ctx, sizeof (MonoContext)); + *new_ctx = *ctx; if (ji != NULL) { int i; - gint32 address; - int offset = 0; + gpointer ip = MONO_CONTEXT_GET_IP (ctx); + mgreg_t regs [MONO_MAX_IREGS + 1]; + guint8 *cfa; + guint32 unwind_info_len; + guint8 *unwind_info; - if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { - /* remove any unused lmf */ - *lmf = (*lmf)->previous_lmf; - } + frame->type = FRAME_TYPE_MANAGED; - address = (char *)ip - (char *)ji->code_start; + unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len); - if (managed) - if (!ji->method->wrapper_type) - *managed = TRUE; + for (i = 0; i < MONO_MAX_IREGS; ++i) + regs [i] = new_ctx->sc_regs [i]; - /* My stack frame */ - fp = MONO_CONTEXT_GET_BP (ctx); + 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); - /* Compute the previous stack frame */ - sp = (guint32)(fp) - (short)(*(guint32 *)(ji->code_start)); + 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; - /* 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 (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->iregs [mips_sp])) { + /* remove any unused lmf */ + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); } - 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); - } /* we substract 8, so that the IP points into the call instruction */ - MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_regs[mips_ra] - 8); + MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_pc - 8); /* Sanity check -- we should have made progress here */ - g_assert (new_ctx->sc_pc != ctx->sc_pc); - return ji; + 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 (gpointer)-1; + return FALSE; } g_assert (((*lmf)->magic == MIPS_LMF_MAGIC1) || ((*lmf)->magic == MIPS_LMF_MAGIC2)); - if ((ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL))) { - } else { - memset (res, 0, MONO_SIZEOF_JIT_INFO); - res->method = (*lmf)->method; + 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 = (*lmf)->previous_lmf; - return ji ? ji : res; + *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3); + + return TRUE; } - return NULL; + return FALSE; } void mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { - int i; - struct sigcontext *ctx = (struct sigcontext *)sigctx; - - mctx->sc_pc = ctx->sc_pc; - for (i = 0; i < 32; ++i) { - mctx->sc_regs[i] = ctx->sc_regs[i]; - mctx->sc_fpregs[i] = ctx->sc_fpregs[i]; - } + mono_sigctx_to_monoctx (sigctx, mctx); } void mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) { - int i; - struct sigcontext *ctx = (struct sigcontext *)sigctx; - - ctx->sc_pc = mctx->sc_pc; - for (i = 0; i < 32; ++i) { - ctx->sc_regs[i] = mctx->sc_regs[i]; - ctx->sc_fpregs[i] = mctx->sc_fpregs[i]; - } -} + mono_monoctx_to_sigctx (mctx, sigctx); +} gpointer mono_arch_ip_from_context (void *sigctx) { - struct sigcontext *ctx = (struct sigcontext *)sigctx; - return (gpointer)(guint32)ctx->sc_pc; + return (gpointer)(gsize)UCONTEXT_REG_PC (sigctx); +} + +/* + * handle_exception: + * + * Called by resuming from a signal handler. + */ +static void +handle_signal_exception (gpointer obj) +{ + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); + MonoContext ctx; + + memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext)); + + mono_handle_exception (&ctx, obj); + + mono_restore_context (&ctx); } /* * This is the function called from the signal handler */ gboolean -mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only) +mono_arch_handle_exception (void *ctx, gpointer obj) { +#if defined(MONO_CROSS_COMPILE) + g_assert_not_reached (); +#elif defined(MONO_ARCH_USE_SIGACTION) + void *sigctx = ctx; + + /* + * 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_native_tls_get_value (mono_jit_tls_id); + guint64 sp = UCONTEXT_GREGS (sigctx) [mips_sp]; + + /* Pass the ctx parameter in TLS */ + mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); + /* The others in registers */ + UCONTEXT_GREGS (sigctx)[mips_a0] = (gsize)obj; + + /* Allocate a stack frame */ + sp -= 256; + UCONTEXT_GREGS (sigctx)[mips_sp] = sp; + + UCONTEXT_REG_PC (sigctx) = (gsize)handle_signal_exception; + + return TRUE; +#else MonoContext mctx; gboolean result; - + mono_arch_sigctx_to_monoctx (ctx, &mctx); -#ifdef DEBUG_EXCEPTIONS - g_print ("mono_arch_handle_exception: pc=%p\n", (void *) mctx.sc_pc); -#endif - mono_handle_exception (&mctx, obj, (gpointer)mctx.sc_pc, test_only); - result = TRUE; -#ifdef DEBUG_EXCEPTIONS - g_print ("mono_arch_handle_exception: restore pc=%p\n", (void *)mctx.sc_pc); -#endif - /* restore the context so that returning from the signal handler - * will invoke the catch clause + result = mono_handle_exception (&mctx, obj); + /* restore the context so that returning from the signal handler will invoke + * the catch clause */ mono_arch_monoctx_to_sigctx (&mctx, ctx); - return result; +#endif } - -gboolean -mono_arch_has_unwind_info (gconstpointer addr) +/* + * mono_arch_setup_resume_sighandler_ctx: + * + * Setup CTX so execution continues at FUNC. + */ +void +mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) { - return FALSE; + MONO_CONTEXT_SET_IP (ctx,func); } -