X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-amd64.c;h=50be3d8839bf17395898c12882af3e153b3f5faf;hb=8112493a2869b4d0dec8ae0c137e6b9aaa1f9e70;hp=441eea21a8974f4791c2a420f015f2fbbd095c05;hpb=5cddeea03868b5710598fe925f5cafa6029f0467;p=mono.git diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 441eea21a89..50be3d8839b 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -292,11 +292,8 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) void mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, guint64 dummy5, guint64 dummy6, - MonoObject *exc, guint64 rip, guint64 rsp, - guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, - guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, - guint64 rax, guint64 rcx, guint64 rdx, - guint64 rethrow) + mgreg_t *regs, mgreg_t rip, + MonoObject *exc, gboolean rethrow) { static void (*restore_context) (MonoContext *); MonoContext ctx; @@ -304,19 +301,19 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin if (!restore_context) restore_context = mono_get_restore_context (); - ctx.rsp = rsp; + ctx.rsp = regs [AMD64_RSP]; ctx.rip = rip; - ctx.rbx = rbx; - ctx.rbp = rbp; - ctx.r12 = r12; - ctx.r13 = r13; - ctx.r14 = r14; - ctx.r15 = r15; - ctx.rdi = rdi; - ctx.rsi = rsi; - ctx.rax = rax; - ctx.rcx = rcx; - ctx.rdx = rdx; + ctx.rbx = regs [AMD64_RBX]; + ctx.rbp = regs [AMD64_RBP]; + ctx.r12 = regs [AMD64_R12]; + ctx.r13 = regs [AMD64_R13]; + ctx.r14 = regs [AMD64_R14]; + ctx.r15 = regs [AMD64_R15]; + ctx.rdi = regs [AMD64_RDI]; + ctx.rsi = regs [AMD64_RSI]; + ctx.rax = regs [AMD64_RAX]; + ctx.rcx = regs [AMD64_RCX]; + ctx.rdx = regs [AMD64_RDX]; if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; @@ -352,13 +349,9 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin void mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, - guint64 dummy5, guint64 dummy6, - guint32 ex_token_index, - guint64 rip, guint64 rsp, - guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, - guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, - guint64 rax, guint64 rcx, guint64 rdx, - gint32 pc_offset) + guint64 dummy5, guint64 dummy6, + mgreg_t *regs, mgreg_t rip, + guint32 ex_token_index, gint64 pc_offset) { guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index; MonoException *ex; @@ -367,7 +360,36 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy rip -= pc_offset; - mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, (MonoObject*)ex, rip, rsp, rbx, rbp, r12, r13, r14, r15, rdi, rsi, rax, rcx, rdx, FALSE); + /* Negate the ip adjustment done in mono_amd64_throw_exception () */ + rip += 1; + + mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, regs, rip, (MonoObject*)ex, FALSE); +} + +static void +mono_amd64_resume_unwind (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4, + guint64 dummy5, guint64 dummy6, + mgreg_t *regs, mgreg_t rip, + guint32 dummy7, gint64 dummy8) +{ + /* Only the register parameters are valid */ + MonoContext ctx; + + ctx.rsp = regs [AMD64_RSP]; + ctx.rip = rip; + ctx.rbx = regs [AMD64_RBX]; + ctx.rbp = regs [AMD64_RBP]; + ctx.r12 = regs [AMD64_R12]; + ctx.r13 = regs [AMD64_R13]; + ctx.r14 = regs [AMD64_R14]; + ctx.r15 = regs [AMD64_R15]; + ctx.rdi = regs [AMD64_RDI]; + ctx.rsi = regs [AMD64_RSI]; + ctx.rax = regs [AMD64_RAX]; + ctx.rcx = regs [AMD64_RCX]; + ctx.rdx = regs [AMD64_RDX]; + + mono_resume_unwind (&ctx); } /* @@ -377,81 +399,93 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy * mono_amd64_throw_corlib_exception. */ static gpointer -get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean aot) +get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, const char *tramp_name, gboolean aot) { guint8* start; guint8 *code; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; + int i, buf_size, stack_size, arg_offsets [16], regs_offset; - start = code = mono_global_codeman_reserve (64); + buf_size = 256; + start = code = mono_global_codeman_reserve (buf_size); - code = start; + /* The stack is unaligned on entry */ + stack_size = 192 + 8; - unwind_ops = mono_arch_get_cie_program (); + code = start; - amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, 8); + if (info) + unwind_ops = mono_arch_get_cie_program (); - /* reverse order */ - if (corlib) - amd64_push_reg (code, AMD64_ARG_REG2); - else - amd64_push_imm (code, rethrow); - amd64_push_reg (code, AMD64_RDX); - amd64_push_reg (code, AMD64_RCX); - amd64_push_reg (code, AMD64_RAX); - amd64_push_reg (code, AMD64_RSI); - amd64_push_reg (code, AMD64_RDI); - amd64_push_reg (code, AMD64_R15); - amd64_push_reg (code, AMD64_R14); - amd64_push_reg (code, AMD64_R13); - amd64_push_reg (code, AMD64_R12); - amd64_push_reg (code, AMD64_RBP); - amd64_push_reg (code, AMD64_RBX); + /* Alloc frame */ + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, stack_size); + if (info) + mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 8); - /* SP */ - amd64_lea_membase (code, AMD64_RAX, AMD64_R11, 8); - amd64_push_reg (code, AMD64_RAX); + /* + * To hide linux/windows calling convention differences, we pass all arguments on + * the stack by passing 6 dummy values in registers. + */ - /* IP */ - amd64_push_membase (code, AMD64_R11, 0); + arg_offsets [0] = 0; + arg_offsets [1] = sizeof (gpointer); + arg_offsets [2] = sizeof (gpointer) * 2; + arg_offsets [3] = sizeof (gpointer) * 3; + regs_offset = sizeof (gpointer) * 4; - if (corlib) - /* exc type token */ - amd64_push_reg (code, AMD64_ARG_REG1); + /* Save registers */ + for (i = 0; i < AMD64_NREG; ++i) + if (i != AMD64_RSP) + amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (i * sizeof (gpointer)), i, 8); + /* Save RSP */ + amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + sizeof (gpointer)); + amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * sizeof (gpointer)), X86_EAX, 8); + /* Set arg1 == regs */ + amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, regs_offset); + amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [0], AMD64_RAX, 8); + /* Set arg2 == eip */ + if (llvm_abs) + amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX); else - /* Exception */ - amd64_push_reg (code, AMD64_ARG_REG1); - - mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, (15 + 1) * sizeof (gpointer)); - -#ifdef TARGET_WIN32 - /* align stack */ - amd64_push_imm (code, 0); - amd64_push_imm (code, 0); - amd64_push_imm (code, 0); - amd64_push_imm (code, 0); - amd64_push_imm (code, 0); - amd64_push_imm (code, 0); -#endif + amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, 8); + amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [1], AMD64_RAX, 8); + /* Set arg3 == exc/ex_token_index */ + if (resume_unwind) + amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, 8); + else + amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG1, 8); + /* Set arg4 == rethrow/pc offset */ + if (resume_unwind) { + amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], 0, 8); + } else if (corlib) { + amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [3], AMD64_ARG_REG2, 8); + if (llvm_abs) + /* + * The caller is LLVM code which passes the absolute address not a pc offset, + * so compensate by passing 0 as 'rip' and passing the negated abs address as + * the pc offset. + */ + amd64_neg_membase (code, AMD64_RSP, arg_offsets [3]); + } else { + amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], rethrow, 8); + } if (aot) { - 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"); + 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"); amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8); } else { - amd64_mov_reg_imm (code, AMD64_R11, corlib ? (gpointer)mono_amd64_throw_corlib_exception : (gpointer)mono_amd64_throw_exception); + 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)); } amd64_call_reg (code, AMD64_R11); amd64_breakpoint (code); mono_arch_flush_icache (start, code - start); - g_assert ((code - start) < 64); - - mono_save_trampoline_xdebug_info ("throw_exception_trampoline", start, code - start, unwind_ops); + g_assert ((code - start) < buf_size); if (info) - *info = mono_tramp_info_create (g_strdup_printf (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception")), start, code - start, ji, unwind_ops); + *info = mono_tramp_info_create (g_strdup (tramp_name), start, code - start, ji, unwind_ops); return start; } @@ -467,13 +501,13 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, FALSE, aot); + return get_throw_trampoline (info, FALSE, FALSE, FALSE, FALSE, "throw_exception", aot); } gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, TRUE, FALSE, aot); + return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_exception", aot); } /** @@ -489,21 +523,19 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, TRUE, aot); + return get_throw_trampoline (info, FALSE, TRUE, FALSE, FALSE, "throw_corlib_exception", 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, StackFrameInfo *frame) @@ -689,29 +721,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 @@ -1074,11 +1108,23 @@ mono_arch_notify_pending_exc (void) void mono_arch_exceptions_init (void) { + guint8 *tramp; + if (mono_aot_only) { throw_pending_exception = mono_aot_get_trampoline ("throw_pending_exception"); } 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_trampoline", FALSE); + mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE); + + tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", FALSE); + mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE); + + tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", FALSE); + mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE); } }