Merge pull request #1936 from esdrubal/DotNetRelativeOrAbsolute
[mono.git] / mono / mini / exceptions-x86.c
old mode 100755 (executable)
new mode 100644 (file)
index 615b3f2..3db25ca
@@ -12,6 +12,9 @@
 #include <glib.h>
 #include <signal.h>
 #include <string.h>
+#ifdef HAVE_UCONTEXT_H
+#include <ucontext.h>
+#endif
 
 #include <mono/metadata/abi-details.h>
 #include <mono/arch/x86/x86-codegen.h>
@@ -31,7 +34,7 @@
 static gpointer signal_exception_trampoline;
 
 gpointer
-mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
+mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot);
 
 #ifdef TARGET_WIN32
 static void (*restore_stack) (void *);
@@ -59,7 +62,7 @@ LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
        }
 #endif
 
-       mono_handle_native_sigsegv (SIGSEGV, NULL);
+       mono_handle_native_sigsegv (SIGSEGV, NULL, NULL);
 
        return EXCEPTION_CONTINUE_SEARCH;
 }
@@ -96,7 +99,7 @@ mono_win32_get_handle_stackoverflow (void)
        x86_call_code (code, mono_domain_get);
 
        /* get stack overflow exception from domain object */
-       x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoDomain, stack_overflow_ex), 4);
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoDomain, stack_overflow_ex), 4);
 
        /* call mono_arch_handle_exception (sctx, stack_overflow_exception_obj) */
        x86_push_reg (code, X86_EAX);
@@ -109,6 +112,9 @@ mono_win32_get_handle_stackoverflow (void)
        /* return */
        x86_ret (code);
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        return start;
 }
 
@@ -139,8 +145,7 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx)
        guint32 free_stack = 0;
        StackFrameInfo frame;
 
-       /* convert sigcontext to MonoContext (due to reuse of stack walking helpers */
-       mono_arch_sigctx_to_monoctx (sctx, &ctx);
+       mono_sigctx_to_monoctx (sctx, &ctx);
        
        /* get our os page size */
        GetSystemInfo(&si);
@@ -158,7 +163,7 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx)
        do {
                MonoContext new_ctx;
 
-               mono_arch_find_jit_info (domain, jit_tls, &rji, &ctx, &new_ctx, &lmf, NULL, &frame);
+               mono_arch_unwind_frame (domain, jit_tls, &rji, &ctx, &new_ctx, &lmf, NULL, &frame);
                if (!frame.ji) {
                        g_warning ("Exception inside function without unwind info");
                        g_assert_not_reached ();
@@ -172,8 +177,7 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx)
                ctx = new_ctx;
        } while (free_stack < 64 * 1024 && frame.ji != (gpointer) -1);
 
-       /* convert into sigcontext to be used in mono_arch_handle_exception */
-       mono_arch_monoctx_to_sigctx (&ctx, sctx);
+       mono_monoctx_to_sigctx (&ctx, sctx);
 
        /* todo: install new stack-guard page */
 
@@ -356,6 +360,9 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
                g_slist_free (unwind_ops);
        }
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        return start;
 }
 
@@ -433,6 +440,9 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
                g_slist_free (unwind_ops);
        }
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        g_assert ((code - start) < kMaxCodeSize);
        return start;
 }
@@ -465,8 +475,10 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
 
        if (mono_object_isinst (exc, mono_defaults.exception_class)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow)
+               if (!rethrow) {
                        mono_ex->stack_trace = NULL;
+                       mono_ex->trace_ips = NULL;
+               }
        }
 
        /* adjust eip so that it point into the call instruction */
@@ -552,8 +564,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
         * <return addr> <- esp (unaligned on apple)
         */
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       unwind_ops = mono_arch_get_cie_program ();
 
        /* Alloc frame */
        x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size);
@@ -655,6 +666,9 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
                g_slist_free (unwind_ops);
        }
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        return start;
 }
 
@@ -702,13 +716,14 @@ void
 mono_arch_exceptions_init (void)
 {
        guint8 *tramp;
+       MonoTrampInfo *tinfo;
 
 /* 
  * If we're running WoW64, we need to set the usermode exception policy 
  * for SEHs to behave. This requires hotfix http://support.microsoft.com/kb/976038
  * or (eventually) Windows 7 SP1.
  */
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
        DWORD flags;
        FARPROC getter;
        FARPROC setter;
@@ -730,31 +745,37 @@ mono_arch_exceptions_init (void)
        }
 
        /* LLVM needs different throw trampolines */
-       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_rethrow_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (NULL, FALSE);
+       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (&tinfo, FALSE);
+       mono_tramp_info_register (tinfo, NULL);
 }
 
 /*
- * mono_arch_find_jit_info:
+ * mono_arch_unwind_frame:
  *
  * See exceptions-amd64.c for docs.
  */
 gboolean
-mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, 
+mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, 
                                                         MonoJitInfo *ji, MonoContext *ctx, 
                                                         MonoContext *new_ctx, MonoLMF **lmf,
                                                         mgreg_t **save_locations,
@@ -773,7 +794,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
@@ -828,14 +852,12 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
 
                        return TRUE;
                }
-               
+
                if ((ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL))) {
+                       frame->ji = ji;
                } else {
-                       if (!((guint32)((*lmf)->previous_lmf) & 1))
-                               /* Top LMF entry */
+                       if (!(*lmf)->method)
                                return FALSE;
-                       g_assert_not_reached ();
-                       /* Trampoline lmf frame */
                        frame->method = (*lmf)->method;
                }
 
@@ -848,28 +870,12 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
                /* Adjust IP */
                new_ctx->eip --;
 
-               frame->ji = ji;
                frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
 
                /* Check if we are in a trampoline LMF frame */
                if ((guint32)((*lmf)->previous_lmf) & 1) {
                        /* lmf->esp is set by the trampoline code */
                        new_ctx->esp = (*lmf)->esp;
-
-                       /* Pop arguments off the stack */
-                       /* FIXME: Handle the delegate case too ((*lmf)->method == NULL) */
-                       /* FIXME: Handle the IMT/vtable case too */
-#if 0
-#ifndef ENABLE_LLVM
-                       if ((*lmf)->method) {
-                               MonoMethod *method = (*lmf)->method;
-                               MonoJitArgumentInfo *arg_info = g_newa (MonoJitArgumentInfo, mono_method_signature (method)->param_count + 1);
-
-                               guint32 stack_to_pop = mono_arch_get_argument_info (NULL, mono_method_signature (method), mono_method_signature (method)->param_count, arg_info);
-                               new_ctx->esp += stack_to_pop;
-                       }
-#endif
-#endif
                }
                else
                        /* the lmf is always stored on the stack, so the following
@@ -884,22 +890,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
        return FALSE;
 }
 
-void
-mono_arch_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
-{
-       mono_sigctx_to_monoctx (sigctx, mctx);
-}
-
-void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
-{
-       mono_monoctx_to_sigctx (mctx, sigctx);
-}
-
 gpointer
 mono_arch_ip_from_context (void *sigctx)
 {
-#if defined(__native_client__)
+#if defined(__native_client__) || defined(HOST_WATCHOS)
        printf("WARNING: mono_arch_ip_from_context() called!\n");
        return (NULL);
 #elif defined(MONO_ARCH_USE_SIGACTION)
@@ -946,11 +940,12 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
 
        start = code = mono_global_codeman_reserve (128);
 
+       /* FIXME no unwind before we push ip */
        /* Caller ip */
        x86_push_reg (code, X86_ECX);
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, start, X86_ESP, 4);
+       mono_add_unwind_op_offset (unwind_ops, code, start, X86_NREG, -4);
 
        /* Fix the alignment to be what apple expects */
        stack_size = 12;
@@ -975,6 +970,9 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
                g_slist_free (unwind_ops);
        }
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        return start;
 }
 
@@ -1012,7 +1010,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
 
        /* Pass the ctx parameter in TLS */
-       mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
+       mono_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
 
        mctx = jit_tls->ex_ctx;
        mono_setup_async_callback (&mctx, handle_signal_exception, obj);
@@ -1024,7 +1022,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        struct sigcontext *ctx = (struct sigcontext *)sigctx;
 
-       mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+       mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
 
        mctx = jit_tls->ex_ctx;
        mono_setup_async_callback (&mctx, handle_signal_exception, obj);
@@ -1034,11 +1032,11 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
 #else
        MonoContext mctx;
 
-       mono_arch_sigctx_to_monoctx (sigctx, &mctx);
+       mono_sigctx_to_monoctx (sigctx, &mctx);
 
        mono_handle_exception (&mctx, obj);
 
-       mono_arch_monoctx_to_sigctx (&mctx, sigctx);
+       mono_monoctx_to_sigctx (&mctx, sigctx);
 
        return TRUE;
 #endif
@@ -1084,7 +1082,7 @@ altstack_handle_and_restore (MonoContext *ctx, gpointer obj, gboolean stack_ovf)
 }
 
 void
-mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean stack_ovf)
+mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf)
 {
 #ifdef MONO_ARCH_USE_SIGACTION
        MonoException *exc = NULL;
@@ -1106,7 +1104,7 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean
        if (stack_ovf)
                exc = mono_domain_get ()->stack_overflow_ex;
        if (!ji)
-               mono_handle_native_sigsegv (SIGSEGV, sigctx);
+               mono_handle_native_sigsegv (SIGSEGV, sigctx, siginfo);
        /* setup a call frame on the real stack so that control is returned there
         * and exception handling can continue.
         * If this was a stack overflow the caller already ensured the stack pages