X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-s390x.c;h=17bb8b044d0ea92945ed50c96f4d9c0cf3dfeedc;hb=073752949f4e7846f3a9de365660077d44e22082;hp=91d7859f5795e203ccc0e5177091213d8f0437a9;hpb=12fa03bd49cf9249ec9e48ccd4781761ab80b442;p=mono.git diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c index 91d7859f579..17bb8b044d0 100644 --- a/mono/mini/exceptions-s390x.c +++ b/mono/mini/exceptions-s390x.c @@ -27,14 +27,18 @@ #define S390_THROWSTACK_ACCPRM S390_MINIMAL_STACK_SIZE #define S390_THROWSTACK_FPCPRM (S390_THROWSTACK_ACCPRM+sizeof(gpointer)) -#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_FPCPRM+sizeof(gint32)) +#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_FPCPRM+sizeof(gulong)) #define S390_THROWSTACK_INTREGS (S390_THROWSTACK_RETHROW+sizeof(gboolean)) #define S390_THROWSTACK_FLTREGS (S390_THROWSTACK_INTREGS+(16*sizeof(gulong))) #define S390_THROWSTACK_ACCREGS (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble))) #define S390_THROWSTACK_SIZE (S390_THROWSTACK_ACCREGS+(16*sizeof(gint32))) +#define S390_REG_SAVE_R13 (S390_REG_SAVE_OFFSET+(7*sizeof(gulong))) + #define SZ_THROW 384 +#define setup_context(ctx) + /*========================= End of Defines =========================*/ /*------------------------------------------------------------------*/ @@ -65,8 +69,7 @@ /*------------------------------------------------------------------*/ gboolean mono_arch_handle_exception (void *ctx, - gpointer obj, - gboolean test_only); + gpointer obj); /*========================= End of Prototypes ======================*/ @@ -74,24 +77,12 @@ gboolean mono_arch_handle_exception (void *ctx, /* G l o b a l V a r i a b l e s */ /*------------------------------------------------------------------*/ -/*====================== End of Global Variables ===================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_has_unwind_info */ -/* */ -/* Function - Tests if a function has a DWARF exception table */ -/* that is able to restore all caller saved registers*/ -/* */ -/*------------------------------------------------------------------*/ - -gboolean -mono_arch_has_unwind_info (gconstpointer addr) -{ - return FALSE; -} +typedef enum { + by_none, + by_token +} throwType; -/*========================= End of Function ========================*/ +/*====================== End of Global Variables ===================*/ /*------------------------------------------------------------------*/ /* */ @@ -105,12 +96,16 @@ mono_arch_has_unwind_info (gconstpointer addr) /*------------------------------------------------------------------*/ gpointer -mono_arch_get_call_filter (void) +mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) { static guint8 *start; static int inited = 0; guint8 *code; int alloc_size, pos, i; + GSList *unwind_ops = NULL; + MonoJumpInfo *ji = NULL; + + g_assert (!aot); if (inited) return start; @@ -128,21 +123,21 @@ mono_arch_get_call_filter (void) /*------------------------------------------------------*/ /* save general registers on stack */ /*------------------------------------------------------*/ - s390_stmg (code, s390_r0, s390_r13, STK_BASE, S390_CALLFILTER_INTREGS); + s390_stmg (code, s390_r0, STK_BASE, STK_BASE, S390_CALLFILTER_INTREGS); /*------------------------------------------------------*/ /* save floating point registers on stack */ /*------------------------------------------------------*/ -// pos = S390_CALLFILTER_FLTREGS; -// for (i = 0; i < 16; ++i) { -// s390_std (code, i, 0, STK_BASE, pos); -// pos += sizeof (gdouble); -// } + pos = S390_CALLFILTER_FLTREGS; + for (i = 0; i < 16; ++i) { + s390_std (code, i, 0, STK_BASE, pos); + pos += sizeof (gdouble); + } /*------------------------------------------------------*/ /* save access registers on stack */ /*------------------------------------------------------*/ -// s390_stam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS); + s390_stam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS); /*------------------------------------------------------*/ /* Get A(Context) */ @@ -169,9 +164,20 @@ mono_arch_get_call_filter (void) s390_ld (code, i, 0, s390_r13, pos); pos += sizeof(gdouble); } - + +#if 0 + /*------------------------------------------------------*/ + /* We need to preserve current SP before calling filter */ + /* with SP from the context */ + /*------------------------------------------------------*/ + s390_lgr (code, s390_r14, STK_BASE); + s390_lg (code, STK_BASE, 0, s390_r13, + G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[15])); + s390_lgr (code, s390_r13, s390_r14); +#endif + /*------------------------------------------------------*/ - /* Point at the copied stack frame and call the filter */ + /* Go call filter */ /*------------------------------------------------------*/ s390_lgr (code, s390_r1, s390_r0); s390_basr (code, s390_r14, s390_r1); @@ -181,23 +187,36 @@ mono_arch_get_call_filter (void) /*------------------------------------------------------*/ s390_lgr (code, s390_r14, s390_r2); +#if 0 + /*------------------------------------------------------*/ + /* Reload our stack register with value saved in context*/ + /*------------------------------------------------------*/ + s390_lgr (code, STK_BASE, s390_r13); +#endif + /*------------------------------------------------------*/ /* Restore all the regs from the stack */ /*------------------------------------------------------*/ s390_lmg (code, s390_r0, s390_r13, STK_BASE, S390_CALLFILTER_INTREGS); -// pos = S390_CALLFILTER_FLTREGS; -// for (i = 0; i < 16; ++i) { -// s390_ld (code, i, 0, STK_BASE, pos); -// pos += sizeof (gdouble); -// } + pos = S390_CALLFILTER_FLTREGS; + for (i = 0; i < 16; ++i) { + s390_ld (code, i, 0, STK_BASE, pos); + pos += sizeof (gdouble); + } s390_lgr (code, s390_r2, s390_r14); -// s390_lam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS); + s390_lam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS); s390_aghi (code, s390_r15, alloc_size); s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (code, s390_r14); g_assert ((code - start) < SZ_THROW); + + if (info) + *info = mono_tramp_info_create ("call_filter", + start, code - start, ji, + unwind_ops); + return start; } @@ -218,13 +237,13 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, { MonoContext ctx; int iReg; - + memset(&ctx, 0, sizeof(ctx)); - getcontext(&ctx); + setup_context(&ctx); /* adjust eip so that it point into the call instruction */ - ip -= 6; + ip -= 2; for (iReg = 0; iReg < 16; iReg++) { ctx.uc_mcontext.gregs[iReg] = int_regs[iReg]; @@ -242,8 +261,9 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, if (!rethrow) mono_ex->stack_trace = NULL; } - mono_arch_handle_exception (&ctx, exc, FALSE); - setcontext(&ctx); +// mono_arch_handle_exception (&ctx, exc, FALSE); + mono_handle_exception (&ctx, exc); + mono_restore_context(&ctx); g_assert_not_reached (); } @@ -263,31 +283,32 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, /*------------------------------------------------------------------*/ static gpointer -get_throw_exception_generic (guint8 *start, int size, - int by_name, gboolean rethrow) +mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, + int corlib, gboolean rethrow, gboolean aot) { - guint8 *code; + guint8 *code, *start; int alloc_size, pos, i; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; - code = start; + code = start = mono_global_codeman_reserve(size); s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); alloc_size = S390_ALIGN(S390_THROWSTACK_SIZE, S390_STACK_ALIGNMENT); s390_lgr (code, s390_r14, STK_BASE); s390_aghi (code, STK_BASE, -alloc_size); s390_stg (code, s390_r14, 0, STK_BASE, 0); - if (by_name) { - s390_lgr (code, s390_r4, s390_r2); + s390_lgr (code, s390_r3, s390_r2); + if (corlib) { s390_basr (code, s390_r13, 0); - s390_j (code, 14); - s390_llong(code, mono_defaults.corlib); - s390_llong(code, "System"); - s390_llong(code, mono_exception_from_name); + s390_j (code, 10); + s390_llong(code, mono_defaults.exception_class->image); + s390_llong(code, mono_exception_from_token); s390_lg (code, s390_r2, 0, s390_r13, 4); - s390_lg (code, s390_r3, 0, s390_r13, 12); - s390_lg (code, s390_r1, 0, s390_r13, 20); + s390_lg (code, s390_r1, 0, s390_r13, 12); s390_basr (code, s390_r14, s390_r1); } + /*------------------------------------------------------*/ /* save the general registers on the stack */ /*------------------------------------------------------*/ @@ -314,10 +335,11 @@ get_throw_exception_generic (guint8 *start, int size, s390_stam (code, s390_r0, s390_r15, STK_BASE, S390_THROWSTACK_ACCREGS); /*------------------------------------------------------*/ - /* call throw_exception (exc, ip, sp, gr, fr, ar) */ - /* exc is already in place in r2 */ + /* call throw_exception (tkn, ip, sp, gr, fr, ar, re) */ + /* - r2 already contains *exc */ /*------------------------------------------------------*/ s390_lgr (code, s390_r4, s390_r1); /* caller sp */ + /*------------------------------------------------------*/ /* pointer to the saved int regs */ /*------------------------------------------------------*/ @@ -325,7 +347,7 @@ get_throw_exception_generic (guint8 *start, int size, s390_la (code, s390_r6, 0, STK_BASE, S390_THROWSTACK_FLTREGS); s390_la (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCREGS); s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCPRM); - s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM); + s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM+4); s390_lghi (code, s390_r7, rethrow); s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW); s390_basr (code, s390_r13, 0); @@ -336,6 +358,13 @@ get_throw_exception_generic (guint8 *start, int size, /* we should never reach this breakpoint */ s390_break (code); g_assert ((code - start) < size); + + if (info) + *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" + : (rethrow ? "rethrow_exception" + : "throw_exception"), + start, code - start, ji, unwind_ops); + return start; } @@ -352,18 +381,15 @@ get_throw_exception_generic (guint8 *start, int size, /* */ /*------------------------------------------------------------------*/ -gpointer -mono_arch_get_throw_exception (void) +gpointer +mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - static guint8 *start; - static int inited = 0; - if (inited) - return start; - start = mono_global_codeman_reserve (SZ_THROW); - get_throw_exception_generic (start, SZ_THROW, FALSE, FALSE); - inited = 1; - return start; + g_assert (!aot); + if (info) + *info = NULL; + + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot)); } /*========================= End of Function ========================*/ @@ -380,44 +406,36 @@ mono_arch_get_throw_exception (void) /*------------------------------------------------------------------*/ gpointer -mono_arch_get_rethrow_exception (void) +mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - static guint8 *start; - static int inited = 0; + g_assert (!aot); + if (info) + *info = NULL; - if (inited) - return start; - start = mono_global_codeman_reserve (SZ_THROW); - get_throw_exception_generic (start, SZ_THROW, FALSE, TRUE); - inited = 1; - return start; + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot)); } /*========================= End of Function ========================*/ /*------------------------------------------------------------------*/ /* */ -/* Name - arch_get_throw_exception_by_name */ +/* Name - arch_get_corlib_exception */ /* */ /* Function - Return a function pointer which can be used to */ /* raise corlib exceptions. The return function has */ /* the following signature: */ -/* void (*func) (char *exc_name); */ +/* void (*func) (guint32 token, guint32 offset) */ /* */ /*------------------------------------------------------------------*/ -gpointer -mono_arch_get_throw_exception_by_name (void) +gpointer +mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - static guint8 *start; - static int inited = 0; + g_assert (!aot); + if (info) + *info = NULL; - if (inited) - return start; - start = mono_global_codeman_reserve (SZ_THROW); - get_throw_exception_generic (start, SZ_THROW, TRUE, FALSE); - inited = 1; - return start; + return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot)); } /*========================= End of Function ========================*/ @@ -426,84 +444,84 @@ mono_arch_get_throw_exception_by_name (void) /* */ /* Name - mono_arch_find_jit_info */ /* */ -/* Function - This function is used to gather information from */ -/* @ctx. It returns the MonoJitInfo of the corres- */ -/* ponding 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 returns the IP off- */ -/* set from the start of the function or -1 if that */ -/* information is not available. */ +/* Function - See exceptions-amd64.c for docs. */ /* */ /*------------------------------------------------------------------*/ -MonoJitInfo * +gboolean 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, MonoContext *ctx, + MonoContext *new_ctx, MonoLMF **lmf, + mgreg_t **save_locations, + StackFrameInfo *frame) { - MonoJitInfo *ji; gpointer ip = (gpointer) MONO_CONTEXT_GET_IP (ctx); MonoS390StackFrame *sframe; - 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; + *new_ctx = *ctx; if (ji != NULL) { gint64 address; + guint8 *cfa; + guint32 unwind_info_len; + guint8 *unwind_info; + mgreg_t regs[16]; - *new_ctx = *ctx; + frame->type = FRAME_TYPE_MANAGED; - if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) { + 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); + + if (*lmf && ((*lmf) != jit_tls->first_lmf) && + (MONO_CONTEXT_GET_SP (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; - - sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_SP (ctx); - MONO_CONTEXT_SET_BP (new_ctx, sframe->prev); - sframe = (MonoS390StackFrame *) sframe->prev; - MONO_CONTEXT_SET_IP (new_ctx, sframe->return_address); - memcpy (&new_ctx->uc_mcontext.gregs[6], sframe->regs, (8*sizeof(gint64))); - return ji; - + memcpy(®s, &ctx->uc_mcontext.gregs, sizeof(regs)); + mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, + (guint8 *) ji->code_start + ji->code_size, + ip, regs, 16, save_locations, + MONO_MAX_IREGS, &cfa); + memcpy (&new_ctx->uc_mcontext.gregs, ®s, sizeof(regs)); + MONO_CONTEXT_SET_IP(new_ctx, regs[14] - 2); + MONO_CONTEXT_SET_BP(new_ctx, cfa); + + if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) { + /* remove any unused lmf */ + *lmf = (*lmf)->previous_lmf; + } + return TRUE; } else if (*lmf) { - - *new_ctx = *ctx; - if (!(*lmf)->method) - return (gpointer)-1; - - 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) { + if (!(*lmf)->method) + return FALSE; + + frame->method = (*lmf)->method; } + frame->ji = ji; + frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; + memcpy(new_ctx->uc_mcontext.gregs, (*lmf)->gregs, sizeof((*lmf)->gregs)); memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs)); - MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp); - MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip); + MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip - 2); *lmf = (*lmf)->previous_lmf; - return ji ? ji : res; + return TRUE; } - return NULL; + return FALSE; } /*========================= End of Function ========================*/ @@ -516,15 +534,46 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /* */ /* Parameters - ctx - Saved processor state */ /* obj - The exception object */ -/* test_only - Only test if the exception is caught, */ -/* but don't call handlers */ /* */ /*------------------------------------------------------------------*/ gboolean -mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only) +mono_arch_handle_exception (void *uc, gpointer obj) +{ + return mono_handle_exception (uc, obj); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_sigctx_to_monoctx. */ +/* */ +/* Function - Called from the signal handler to convert signal */ +/* context to MonoContext. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx) { - return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc), test_only); + mono_sigctx_to_monoctx(ctx, mctx); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_monoctx_to_sigctx. */ +/* */ +/* Function - Convert MonoContext structure to signal context. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx) +{ + mono_monoctx_to_sigctx(mctx, ctx); } /*========================= End of Function ========================*/ @@ -550,7 +599,7 @@ mono_arch_ip_from_context (void *sigctx) /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_get_restore_context */ +/* Name - mono_arch_get_restore_context */ /* */ /* Function - Return the address of the routine that will rest- */ /* ore the context. */ @@ -558,12 +607,15 @@ mono_arch_ip_from_context (void *sigctx) /*------------------------------------------------------------------*/ gpointer -mono_arch_get_restore_context () +mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) { + g_assert (!aot); + if (info) + *info = NULL; + return setcontext; } - /*========================= End of Function ========================*/ /*------------------------------------------------------------------*/