Merge pull request #1654 from alexanderkyte/xunit-fixes
[mono.git] / mono / mini / mini-exceptions.c
index ec8699bc4fbfcbbb26df74ad50996c340a16d57b..fef21b9958159dd295540dd98047413905cc09f8 100644 (file)
@@ -700,6 +700,8 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
                }
                else
                        MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
+
+               sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
                sf->method_address = (gsize) ji->code_start;
                sf->native_offset = (char *)ip - (char *)ji->code_start;
 
@@ -713,7 +715,7 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
                        sf->il_offset = location->il_offset;
                } else {
                        SeqPoint sp;
-                       if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
+                       if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
                                sf->il_offset = sp.il_offset;
                        else
                                sf->il_offset = -1;
@@ -758,7 +760,7 @@ void
 mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
 {
        MonoContext extra_ctx;
-       MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
        MONO_ARCH_CONTEXT_DEF
 
        if (!thread || !thread->jit_data)
@@ -872,7 +874,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
                                il_offset = source->il_offset;
                        } else {
                                SeqPoint sp;
-                               if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
+                               if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
                                        il_offset = sp.il_offset;
                                else
                                        il_offset = -1;
@@ -977,121 +979,6 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
        return TRUE;
 }
 
-typedef struct {
-       guint32 skips;
-       MonoSecurityFrame *frame;
-} MonoFrameSecurityInfo;
-
-static gboolean
-callback_get_first_frame_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
-{
-       MonoFrameSecurityInfo *si = (MonoFrameSecurityInfo*) data;
-       MonoJitInfo *ji = frame->ji;
-       MonoMethod *method;
-
-       if (!ji)
-               return FALSE;
-
-       /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
-       method = jinfo_get_method (ji);
-       if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
-           method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
-           method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
-           method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
-           method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
-               return FALSE;
-       }
-
-       if (si->skips > 0) {
-               si->skips--;
-               return FALSE;
-       }
-
-       si->frame = mono_declsec_create_frame (frame->domain, ji);
-
-       /* Stop - we only want the first frame (e.g. LinkDemand and InheritanceDemand) */
-       return TRUE;
-}
-
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityFrame:
- * @skip: the number of stack frames to skip
- *
- * This function returns a the security informations of a single stack frame 
- * (after the skipped ones). This is required for [NonCas]LinkDemand[Choice]
- * and [NonCas]InheritanceDemand[Choice] as only the caller security is 
- * evaluated.
- */
-MonoSecurityFrame*
-ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip)
-{
-       MonoFrameSecurityInfo si;
-
-       si.skips = skip;
-       si.frame = NULL;
-
-       mono_walk_stack (callback_get_first_frame_security_info, MONO_UNWIND_DEFAULT, &si);
-
-       return (si.skips == 0) ? si.frame : NULL;
-}
-
-
-typedef struct {
-       guint32 skips;
-       MonoArray *stack;
-       guint32 count;
-       guint32 maximum;
-} MonoSecurityStack;
-
-static void
-grow_array (MonoSecurityStack *stack)
-{
-       MonoDomain *domain = mono_domain_get ();
-       guint32 newsize = (stack->maximum << 1);
-       MonoArray *newstack = mono_array_new (domain, mono_defaults.runtimesecurityframe_class, newsize);
-       int i;
-       for (i=0; i < stack->maximum; i++) {
-               gpointer frame = mono_array_get (stack->stack, gpointer, i);
-               mono_array_setref (newstack, i, frame);
-       }
-       stack->maximum = newsize;
-       stack->stack = newstack;
-}
-
-static gboolean
-callback_get_stack_frames_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
-{
-       MonoSecurityStack *ss = (MonoSecurityStack*) data;
-       MonoJitInfo *ji = frame->ji;
-       MonoMethod *method;
-
-       if (!ji)
-               return FALSE;
-
-       /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
-       method = jinfo_get_method (ji);
-       if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
-           method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
-           method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
-           method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
-           method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
-               return FALSE;
-       }
-
-       if (ss->skips > 0) {
-               ss->skips--;
-               return FALSE;
-       }
-
-       if (ss->count == ss->maximum)
-               grow_array (ss);
-
-       mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (frame->domain, ji));
-
-       /* continue down the stack */
-       return FALSE;
-}
-
 static MonoArray *
 glist_to_array (GList *list, MonoClass *eclass) 
 {
@@ -1111,33 +998,6 @@ glist_to_array (GList *list, MonoClass *eclass)
        return res;
 }
 
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityStack:
- * @skip: the number of stack frames to skip
- *
- * This function returns an managed array of containing the security
- * informations for each frame (after the skipped ones). This is used for
- * [NonCas]Demand[Choice] where the complete evaluation of the stack is 
- * required.
- */
-MonoArray*
-ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
-{
-       MonoSecurityStack ss;
-
-#if    defined(__ia64__) || defined(__s390__) || defined(__s390x__)
-       skip--;
-#endif
-
-       ss.skips = skip;
-       ss.count = 0;
-       ss.maximum = MONO_CAS_INITIAL_STACK_SIZE;
-       ss.stack = mono_array_new (mono_domain_get (), mono_defaults.runtimesecurityframe_class, ss.maximum);
-       mono_walk_stack (callback_get_stack_frames_security_info, MONO_UNWIND_DEFAULT, &ss);
-       /* g_warning ("STACK RESULT: %d out of %d", ss.count, ss.maximum); */
-       return ss.stack;
-}
-
 static MonoClass*
 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
 {
@@ -1167,14 +1027,14 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex
 }
 
 /*
- * mini_jit_info_table_find:
+ * mini_jit_info_table_find_ext:
  *
  *   Same as mono_jit_info_table_find, but search all the domains of the current thread
  * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
  * OUT_DOMAIN if it is not NULL.
  */
 MonoJitInfo*
-mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
+mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain)
 {
        MonoJitInfo *ji;
        MonoInternalThread *t = mono_thread_internal_current ();
@@ -1183,7 +1043,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
        if (out_domain)
                *out_domain = NULL;
 
-       ji = mono_jit_info_table_find (domain, addr);
+       ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines);
        if (ji) {
                if (out_domain)
                        *out_domain = domain;
@@ -1192,7 +1052,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
 
        /* maybe it is shared code, so we also search in the root domain */
        if (domain != mono_get_root_domain ()) {
-               ji = mono_jit_info_table_find (mono_get_root_domain (), addr);
+               ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines);
                if (ji) {
                        if (out_domain)
                                *out_domain = mono_get_root_domain ();
@@ -1206,7 +1066,7 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
        refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL;
        for (; refs && *refs; refs++) {
                if (*refs != domain && *refs != mono_get_root_domain ()) {
-                       ji = mono_jit_info_table_find ((MonoDomain*) *refs, addr);
+                       ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines);
                        if (ji) {
                                if (out_domain)
                                        *out_domain = (MonoDomain*) *refs;
@@ -1218,6 +1078,12 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
        return NULL;
 }
 
+MonoJitInfo*
+mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
+{
+       return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain);
+}
+
 /*
  * wrap_non_exception_throws:
  *
@@ -1481,16 +1347,28 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3
                                        if (is_user_frame)
                                                setup_managed_stacktrace_information ();
 
-                                       if (ji->from_llvm) {
 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
+                                       if (ji->from_llvm)
                                                MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
+                                       else
+                                               /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
+                                               *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
 #else
-                                               g_assert_not_reached ();
+                                       g_assert (!ji->from_llvm);
+                                       /* store the exception object in bp + ei->exvar_offset */
+                                       *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
+#endif
+
+#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
+                                       /*
+                                        * Pass the original il clause index to the landing pad so it can
+                                        * branch to the landing pad associated with the il clause.
+                                        * This is needed because llvm compiled code assumes that the EH
+                                        * code always branches to the innermost landing pad.
+                                        */
+                                       if (ji->from_llvm)
+                                               MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
 #endif
-                                       } else {
-                                               /* store the exception object in bp + ei->exvar_offset */
-                                               *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
-                                       }
 
                                        mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
                                        filtered = call_filter (ctx, ei->data.filter);
@@ -1775,18 +1653,20 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        ex_obj = obj;
 
                                if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
-                                       if (ji->from_llvm) {
 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
-                                               MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
+                                       MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
 #else
-                                               g_assert_not_reached ();
+                                       g_assert (!ji->from_llvm);
+                                       /* store the exception object in bp + ei->exvar_offset */
+                                       *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
 #endif
-                                       } else {
-                                               /* store the exception object in bp + ei->exvar_offset */
-                                               *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
-                                       }
                                }
 
+#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
+                               if (ji->from_llvm)
+                                       MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
+#endif
+
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                        /* 
                                         * Filter clauses should only be run in the 
@@ -2628,16 +2508,19 @@ gboolean
 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
 {
 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       if (!thread || !thread->jit_data) {
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
+       if (!thread) {
                ctx->valid = FALSE;
+               G_BREAKPOINT ();
                return FALSE;
        }
 
        if (sigctx)
                mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
        else
-#if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
+#if defined(MONO_CROSS_COMPILE)
+               ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
+#elif MONO_ARCH_HAS_MONO_CONTEXT
                MONO_CONTEXT_GET_CURRENT (ctx->ctx);
 #else
                g_error ("Use a null sigctx requires a working mono-context");
@@ -2657,8 +2540,8 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
 gboolean
 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
 {
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       if (!thread || !thread->jit_data) {
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
+       if (!thread) {
                ctx->valid = FALSE;
                return FALSE;
        }
@@ -2675,7 +2558,7 @@ mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mc
 gboolean
 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
 {
-       MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
        MONO_ARCH_CONTEXT_DEF
 
        mono_arch_flush_register_windows ();
@@ -2751,7 +2634,7 @@ mono_invoke_unhandled_exception_hook (MonoObject *exc)
                }
                mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
                g_free (msg);
-#if defined(__APPLE__) && defined(__arm__)
+#if defined(HOST_IOS)
                g_assertion_message ("Terminating runtime due to unhandled exception");
 #else
                exit (mono_environment_exitcode_get ());