X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Fexceptions-amd64.c;h=e683bf2a11fcf6080ab66869911056d967764151;hb=4d662ad4a5e4ee7f00c7345363454bb47fb89918;hp=cf5dbf1fedfbcc05e984c2b7770ac34bc671d690;hpb=7b7e7a3233b82371a17b20826c178e00a85b8eb9;p=mono.git diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index cf5dbf1fedf..e683bf2a11f 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -415,11 +415,13 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g code = start; - unwind_ops = mono_arch_get_cie_program (); + if (info) + unwind_ops = mono_arch_get_cie_program (); /* Alloc frame */ amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, stack_size); - mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 8); + if (info) + mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 8); /* * To hide linux/windows calling convention differences, we pass all arguments on @@ -470,7 +472,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g } if (aot) { - ji = mono_patch_info_list_prepend (ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, corlib ? (llvm_abs ? "mono_amd64_throw_corlib_exception_abs" : "mono_amd64_throw_corlib_exception") : "mono_amd64_throw_exception"); + ji = mono_patch_info_list_prepend (ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, corlib ? "mono_amd64_throw_corlib_exception" : "mono_amd64_throw_exception"); amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8); } else { amd64_mov_reg_imm (code, AMD64_R11, resume_unwind ? (mono_amd64_resume_unwind) : (corlib ? (gpointer)mono_amd64_throw_corlib_exception : (gpointer)mono_amd64_throw_exception)); @@ -482,10 +484,8 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g g_assert ((code - start) < buf_size); - mono_save_trampoline_xdebug_info (tramp_name, start, code - start, unwind_ops); - if (info) - *info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops); + *info = mono_tramp_info_create (g_strdup (tramp_name), start, code - start, ji, unwind_ops); return start; } @@ -527,19 +527,18 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) } /* - * mono_arch_find_jit_info_ext: + * 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. - * This function is a version of mono_arch_find_jit_info () where all the results are - * returned in a StackFrameInfo structure. */ gboolean -mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, +mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *ji, MonoContext *ctx, - MonoContext *new_ctx, MonoLMF **lmf, + MonoContext *new_ctx, MonoLMF **lmf, + mgreg_t **save_locations, StackFrameInfo *frame) { gpointer ip = MONO_CONTEXT_GET_IP (ctx); @@ -565,6 +564,9 @@ mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, 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); + + frame->unwind_info = unwind_info; + frame->unwind_info_len = unwind_info_len; regs [AMD64_RAX] = new_ctx->rax; regs [AMD64_RBX] = new_ctx->rbx; @@ -582,7 +584,8 @@ mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, (guint8*)ji->code_start + ji->code_size, - ip, regs, MONO_MAX_IREGS + 1, &cfa); + ip, regs, MONO_MAX_IREGS + 1, + save_locations, MONO_MAX_IREGS, &cfa); new_ctx->rax = regs [AMD64_RAX]; new_ctx->rbx = regs [AMD64_RBX]; @@ -656,10 +659,14 @@ mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, } ji = mini_jit_info_table_find (domain, (gpointer)rip, NULL); - if (!ji) { - // FIXME: This can happen with multiple appdomains (bug #444383) + /* + * FIXME: ji == NULL can happen when a managed-to-native wrapper is interrupted + * in the soft debugger suspend code, since (*lmf)->rsp no longer points to the + * return address. + */ + //g_assert (ji); + if (!ji) return FALSE; - } /* Adjust IP */ rip --; @@ -723,29 +730,31 @@ handle_signal_exception (gpointer obj, gboolean test_only) gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { -#if defined(MONO_ARCH_USE_SIGACTION) && defined(UCONTEXT_GREGS) +#if defined(MONO_ARCH_USE_SIGACTION) + ucontext_t *ctx = (ucontext_t*)sigctx; + /* * 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 = TlsGetValue (mono_jit_tls_id); - guint64 sp = UCONTEXT_REG_RSP (sigctx); + guint64 sp = UCONTEXT_REG_RSP (ctx); /* Pass the ctx parameter in TLS */ - mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); + mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx); /* The others in registers */ - UCONTEXT_REG_RDI (sigctx) = (guint64)obj; - UCONTEXT_REG_RSI (sigctx) = test_only; + UCONTEXT_REG_RDI (ctx) = (guint64)obj; + UCONTEXT_REG_RSI (ctx) = test_only; /* Allocate a stack frame below the red zone */ sp -= 128; /* The stack should be unaligned */ if (sp % 8 == 0) sp -= 8; - UCONTEXT_REG_RSP (sigctx) = sp; + UCONTEXT_REG_RSP (ctx) = sp; - UCONTEXT_REG_RIP (sigctx) = (guint64)handle_signal_exception; + UCONTEXT_REG_RIP (ctx) = (guint64)handle_signal_exception; return TRUE; #else @@ -764,13 +773,6 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) #endif } -#if defined(MONO_ARCH_USE_SIGACTION) && defined(UCONTEXT_GREGS) -static inline guint64* -gregs_from_ucontext (ucontext_t *ctx) -{ - return (guint64 *) UCONTEXT_GREGS (ctx); -} -#endif void mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { @@ -913,8 +915,7 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean #if defined(MONO_ARCH_USE_SIGACTION) && defined(UCONTEXT_GREGS) MonoException *exc = NULL; ucontext_t *ctx = (ucontext_t*)sigctx; - guint64 *gregs = gregs_from_ucontext (ctx); - MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)gregs [REG_RIP], NULL); + MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)UCONTEXT_REG_RIP (sigctx), NULL); gpointer *sp; int frame_size; @@ -934,18 +935,18 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean frame_size = sizeof (ucontext_t) + sizeof (gpointer) * 4 + 128; frame_size += 15; frame_size &= ~15; - sp = (gpointer)(gregs [REG_RSP] & ~15); + sp = (gpointer)(UCONTEXT_REG_RSP (sigctx) & ~15); sp = (gpointer)((char*)sp - frame_size); /* the arguments must be aligned */ - sp [-1] = (gpointer)gregs [REG_RIP]; + sp [-1] = (gpointer)UCONTEXT_REG_RIP (sigctx); /* may need to adjust pointers in the new struct copy, depending on the OS */ memcpy (sp + 4, ctx, sizeof (ucontext_t)); /* at the return form the signal handler execution starts in altstack_handle_and_restore() */ - gregs [REG_RIP] = (unsigned long)altstack_handle_and_restore; - gregs [REG_RSP] = (unsigned long)(sp - 1); - gregs [REG_RDI] = (unsigned long)(sp + 4); - gregs [REG_RSI] = (guint64)exc; - gregs [REG_RDX] = stack_ovf; + UCONTEXT_REG_RIP (sigctx) = (unsigned long)altstack_handle_and_restore; + UCONTEXT_REG_RSP (sigctx) = (unsigned long)(sp - 1); + UCONTEXT_REG_RDI (sigctx) = (unsigned long)(sp + 4); + UCONTEXT_REG_RSI (sigctx) = (guint64)exc; + UCONTEXT_REG_RDX (sigctx) = stack_ovf; #endif } @@ -1105,26 +1106,55 @@ mono_arch_notify_pending_exc (void) *(gpointer*)(lmf->rsp - 8) = throw_pending_exception; } +GSList* +mono_amd64_get_exception_trampolines (gboolean aot) +{ + MonoTrampInfo *info; + GSList *tramps = NULL; + + mono_arch_get_throw_pending_exception (&info, aot); + tramps = g_slist_prepend (tramps, info); + + /* LLVM needs different throw trampolines */ + get_throw_trampoline (&info, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", aot); + tramps = g_slist_prepend (tramps, info); + + get_throw_trampoline (&info, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", aot); + tramps = g_slist_prepend (tramps, info); + + get_throw_trampoline (&info, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", FALSE); + tramps = g_slist_prepend (tramps, info); + + return tramps; +} + void mono_arch_exceptions_init (void) { - guint8 *tramp; + GSList *tramps, *l; + gpointer tramp; if (mono_aot_only) { throw_pending_exception = mono_aot_get_trampoline ("throw_pending_exception"); + tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_trampoline"); + mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE); + tramp = mono_aot_get_trampoline ("llvm_throw_corlib_exception_abs_trampoline"); + mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE); + tramp = mono_aot_get_trampoline ("llvm_resume_unwind_trampoline"); + mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE); } else { /* Call this to avoid initialization races */ throw_pending_exception = mono_arch_get_throw_pending_exception (NULL, FALSE); - /* LLVM needs different throw trampolines */ - tramp = get_throw_trampoline (NULL, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception", FALSE); - mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception", NULL, TRUE); - - tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs", FALSE); - mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception_abs", NULL, TRUE); + tramps = mono_amd64_get_exception_trampolines (FALSE); + for (l = tramps; l; l = l->next) { + MonoTrampInfo *info = l->data; - tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, TRUE, "mono_llvm_resume_unwind_trampoline", FALSE); - mono_register_jit_icall (tramp, "mono_llvm_resume_unwind_trampoline", NULL, TRUE); + mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE); + mono_save_trampoline_xdebug_info (info); + mono_tramp_info_free (info); + } + g_slist_free (tramps); } } @@ -1425,3 +1455,19 @@ mono_tasklets_arch_restore (void) } #endif +/* + * mono_arch_setup_resume_sighandler_ctx: + * + * Setup CTX so execution continues at FUNC. + */ +void +mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) +{ + /* + * When resuming from a signal handler, the stack should be misaligned, just like right after + * a call. + */ + if ((((guint64)MONO_CONTEXT_GET_SP (ctx)) % 16) == 0) + MONO_CONTEXT_SET_SP (ctx, (guint64)MONO_CONTEXT_GET_SP (ctx) - 8); + MONO_CONTEXT_SET_IP (ctx, func); +}