X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-arm.c;h=ae949430b35e661ddacf0200e5d939fa63478e40;hb=d4fdf2c56446b843692279e0cd0cb6494bc92593;hp=7191c3f2fcd8210da70516ec9975bc9eb7b8fba1;hpb=9d61782c6e2392d7ceec2006b35be582598a70ae;p=mono.git diff --git a/mono/mini/exceptions-arm.c b/mono/mini/exceptions-arm.c index 7191c3f2fcd..ae949430b35 100644 --- a/mono/mini/exceptions-arm.c +++ b/mono/mini/exceptions-arm.c @@ -77,6 +77,24 @@ typedef struct ucontext { */ +/* + * So, it turns out that the ucontext struct defined by libc is incorrect. + * We define our own version here and use it instead. + */ + +typedef struct my_ucontext { + unsigned long uc_flags; + struct my_ucontext *uc_link; + struct { + void *p; + int flags; + size_t size; + } sstack_data; + struct sigcontext sig_ctx; + /* some 2.6.x kernel has fp data here after a few other fields + * we don't use them for now... + */ +} my_ucontext; #define restore_regs_from_context(ctx_reg,ip_reg,tmp_reg) do { \ int reg; \ @@ -109,6 +127,8 @@ mono_arch_get_restore_context (void) restore_regs_from_context (ARMREG_R0, ARMREG_R1, ARMREG_R2); /* restore also the stack pointer, FIXME: handle sp != fp */ ARM_LDR_IMM (code, ARMREG_SP, ARMREG_R0, G_STRUCT_OFFSET (MonoContext, ebp)); + ARM_LDR_IMM (code, ARMREG_FP, ARMREG_R0, G_STRUCT_OFFSET (MonoContext, esp)); + /* jump to the saved IP */ ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1); /* never reached */ @@ -178,6 +198,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong * /*printf ("stack in throw: %p\n", esp);*/ MONO_CONTEXT_SET_BP (&ctx, esp); + MONO_CONTEXT_SET_SP (&ctx, esp); MONO_CONTEXT_SET_IP (&ctx, eip); memcpy (&ctx.regs, int_regs, sizeof (gulong) * 8); /* memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS); */ @@ -319,25 +340,6 @@ mono_arch_get_throw_exception_by_name (void) 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: * * This function is used to gather information from @ctx. It return the @@ -386,8 +388,8 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { memcpy (&new_ctx->regs [0], &(*lmf)->iregs [4], sizeof (gulong) * MONO_SAVED_GREGS); } - new_ctx->esp = (*lmf)->iregs [13]; - new_ctx->eip = (*lmf)->iregs [14]; + new_ctx->esp = (*lmf)->iregs [12]; + new_ctx->eip = (*lmf)->iregs [13]; new_ctx->ebp = new_ctx->esp; } else { int i; @@ -435,8 +437,8 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf } memcpy (&new_ctx->regs [0], &(*lmf)->iregs [4], sizeof (gulong) * MONO_SAVED_GREGS); - new_ctx->esp = (*lmf)->iregs [13]; - new_ctx->eip = (*lmf)->iregs [14]; + new_ctx->esp = (*lmf)->iregs [12]; + new_ctx->eip = (*lmf)->iregs [13]; new_ctx->ebp = new_ctx->esp; *lmf = (*lmf)->previous_lmf; @@ -447,37 +449,73 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf return NULL; } +void +mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) +{ +#if BROKEN_LINUX + struct ucontext *uc = sigctx; + + mctx->eip = uc->uc_mcontext.gregs [ARMREG_PC]; + mctx->ebp = uc->uc_mcontext.gregs [ARMREG_SP]; + memcpy (&mctx->regs, &uc->uc_mcontext.gregs [ARMREG_R4], sizeof (gulong) * 8); + /* memcpy (&mctx->fregs, &uc->uc_mcontext.uc_regs->fpregs.fpregs [14], sizeof (double) * MONO_SAVED_FREGS);*/ +#else + my_ucontext *my_uc = sigctx; + + mctx->eip = my_uc->sig_ctx.arm_pc; + mctx->ebp = my_uc->sig_ctx.arm_sp; + memcpy (&mctx->regs, &my_uc->sig_ctx.arm_r4, sizeof (gulong) * 8); +#endif +} + +void +mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx) +{ +#if BROKEN_LINUX + struct ucontext *uc = ctx; + + uc->uc_mcontext.gregs [ARMREG_PC] = mctx->eip; + uc->uc_mcontext.gregs [ARMREG_SP] = mctx->ebp; + memcpy (&uc->uc_mcontext.gregs [ARMREG_R4], &mctx->regs, sizeof (gulong) * 8); + /* memcpy (&uc->uc_mcontext.uc_regs->fpregs.fpregs [14], &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS);*/ +#else + my_ucontext *my_uc = ctx; + + my_uc->sig_ctx.arm_pc = mctx->eip; + my_uc->sig_ctx.arm_sp = mctx->ebp; + memcpy (&my_uc->sig_ctx.arm_r4, &mctx->regs, sizeof (gulong) * 8); +#endif +} + /* * This is the function called from the signal handler */ gboolean mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only) { - struct ucontext *uc = ctx; MonoContext mctx; gboolean result; - mctx.eip = uc->uc_mcontext.gregs [ARMREG_PC]; - mctx.ebp = uc->uc_mcontext.gregs [ARMREG_SP]; - memcpy (&mctx.regs, &uc->uc_mcontext.gregs [ARMREG_R4], sizeof (gulong) * 8); - /* memcpy (&mctx.fregs, &uc->uc_mcontext.uc_regs->fpregs.fpregs [14], sizeof (double) * MONO_SAVED_FREGS);*/ + mono_arch_sigctx_to_monoctx (ctx, &mctx); result = mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only); /* restore the context so that returning from the signal handler will invoke * the catch clause */ - uc->uc_mcontext.gregs [ARMREG_PC] = mctx.eip; - uc->uc_mcontext.gregs [ARMREG_SP] = mctx.ebp; - memcpy (&uc->uc_mcontext.gregs [ARMREG_R4], &mctx.regs, sizeof (gulong) * 8); - /* memcpy (&uc->uc_mcontext.uc_regs->fpregs.fpregs [14], &mctx.fregs, sizeof (double) * MONO_SAVED_FREGS);*/ + mono_arch_monoctx_to_sigctx (&mctx, ctx); return result; } gpointer mono_arch_ip_from_context (void *sigctx) { +#if BROKEN_LINUX struct ucontext *uc = sigctx; return (gpointer)uc->uc_mcontext.gregs [ARMREG_PC]; +#else + my_ucontext *my_uc = sigctx; + return (void*)my_uc->sig_ctx.arm_pc; +#endif } gboolean