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
}
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));
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;
}
}
/*
- * 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);
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;
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];
}
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 --;
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
#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)
{
#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;
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
}
*(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);
}
}
}
#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);
+}