[runtime] GetModuleFileNameEx
[mono.git] / mono / mini / mini-exceptions.c
index 47162f83ee36a845004c5e9dc7e6fd9e49d777ec..26fccf0d08ee0864712e5eb1ee2075a06e8bd3ae 100644 (file)
 #include <sys/syscall.h>
 #endif
 
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/threads.h>
@@ -94,13 +98,13 @@ mono_exceptions_init (void)
                MonoTrampInfo *info;
 
                restore_context_func = mono_arch_get_restore_context (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                call_filter_func = mono_arch_get_call_filter (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                throw_exception_func = mono_arch_get_throw_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
                rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
        }
 #ifdef MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT
        try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
@@ -161,7 +165,7 @@ mono_get_throw_corlib_exception (void)
                code = mono_aot_get_trampoline ("throw_corlib_exception");
        else {
                code = mono_arch_get_throw_corlib_exception (&info, FALSE);
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
        }
 
        mono_memory_barrier ();
@@ -201,7 +205,7 @@ is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip)
 /*
  * find_jit_info:
  *
- * Translate between the mono_arch_find_jit_info function and the old API.
+ * Translate between the mono_arch_unwind_frame function and the old API.
  */
 static MonoJitInfo *
 find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, 
@@ -221,7 +225,7 @@ find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, Mo
        if (managed)
                *managed = FALSE;
 
-       err = mono_arch_find_jit_info (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
+       err = mono_arch_unwind_frame (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
        if (!err)
                return (gpointer)-1;
 
@@ -239,6 +243,8 @@ find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, Mo
                if (managed)
                        *managed = TRUE;
                return frame.ji;
+       case FRAME_TYPE_TRAMPOLINE:
+               return frame.ji;
        case FRAME_TYPE_MANAGED_TO_NATIVE:
                if (frame.ji)
                        return frame.ji;
@@ -297,10 +303,10 @@ mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *re
        if (ji == (gpointer)-1)
                return ji;
 
-       if (ji)
+       if (ji && !ji->is_trampoline)
                method = jinfo_get_method (ji);
 
-       if (managed2 || (ji && method->wrapper_type)) {
+       if (managed2 || (method && method->wrapper_type)) {
                const char *real_ip, *start;
                gint32 offset;
 
@@ -381,7 +387,7 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
        if (save_locations)
                memset (save_locations, 0, MONO_MAX_IREGS * sizeof (mgreg_t*));
 
-       err = mono_arch_find_jit_info (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
+       err = mono_arch_unwind_frame (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
        if (!err)
                return FALSE;
 
@@ -393,7 +399,7 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
                *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
        }
 
-       if (frame->ji && !frame->ji->async)
+       if (frame->ji && !frame->ji->is_trampoline && !frame->ji->async)
                method = jinfo_get_method (frame->ji);
 
        if (frame->type == FRAME_TYPE_MANAGED && method) {
@@ -447,6 +453,9 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
        return TRUE;
 }
 
+/*
+ * This function is async-safe.
+ */
 static gpointer
 get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
 {
@@ -507,7 +516,7 @@ static MonoGenericContext
 get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
 {
        MonoGenericContext context = { NULL, NULL };
-       MonoClass *class, *method_container_class;
+       MonoClass *klass, *method_container_class;
        MonoMethod *method;
 
        g_assert (generic_info);
@@ -517,15 +526,15 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
        if (mono_method_get_context (method)->method_inst) {
                MonoMethodRuntimeGenericContext *mrgctx = generic_info;
 
-               class = mrgctx->class_vtable->klass;
+               klass = mrgctx->class_vtable->klass;
                context.method_inst = mrgctx->method_inst;
                g_assert (context.method_inst);
        } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
                MonoVTable *vtable = generic_info;
 
-               class = vtable->klass;
+               klass = vtable->klass;
        } else {
-               class = generic_info;
+               klass = generic_info;
        }
 
        //g_assert (!method->klass->generic_container);
@@ -535,18 +544,18 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
                method_container_class = method->klass;
 
        /* class might refer to a subclass of method's class */
-       while (!(class == method->klass || (class->generic_class && class->generic_class->container_class == method_container_class))) {
-               class = class->parent;
-               g_assert (class);
+       while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
+               klass = klass->parent;
+               g_assert (klass);
        }
 
-       if (class->generic_class || class->generic_container)
-               context.class_inst = mini_class_get_context (class)->class_inst;
+       if (klass->generic_class || klass->generic_container)
+               context.class_inst = mini_class_get_context (klass)->class_inst;
 
-       if (class->generic_class)
-               g_assert (mono_class_has_parent_and_ignore_generics (class->generic_class->container_class, method_container_class));
+       if (klass->generic_class)
+               g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
        else
-               g_assert (mono_class_has_parent_and_ignore_generics (class, method_container_class));
+               g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
 
        return context;
 }
@@ -631,11 +640,11 @@ ves_icall_System_Exception_get_trace (MonoException *ex)
                gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
                gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
 
-               ji = mono_jit_info_table_find (domain, ip);
+               ji = mono_jit_info_table_find_internal (domain, ip, TRUE, TRUE);
                if (ji == NULL) {
                        /* Unmanaged frame */
                        g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip);
-               } else {
+               } else if (!ji->is_trampoline) {
                        gchar *location;
                        gint32 address;
                        MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
@@ -694,12 +703,14 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
                        char *s;
 
                        sf->method = NULL;
-                       s = mono_method_full_name (method, TRUE);
+                       s = mono_method_get_name_full (method, TRUE, MONO_TYPE_NAME_FORMAT_REFLECTION);
                        MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s));
                        g_free (s);
                }
                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,10 +724,10 @@ 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 = 0;
+                               sf->il_offset = -1;
                }
 
                if (need_file_info) {
@@ -758,7 +769,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)
@@ -864,7 +875,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
                if (!res)
                        return;
 
-               if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji) {
+               if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
                        MonoDebugSourceLocation *source;
 
                        source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
@@ -872,7 +883,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;
@@ -883,7 +894,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
 
                frame.il_offset = il_offset;
 
-               if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji) {
+               if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
                        frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
                } else {
                        frame.actual_method = frame.method;
@@ -938,7 +949,9 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
                if (!res)
                        return FALSE;
 
-               if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE)
+               if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                               frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                               frame.type == FRAME_TYPE_TRAMPOLINE)
                        continue;
 
                ji = frame.ji;
@@ -977,121 +990,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 +1009,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 +1038,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 +1054,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 +1063,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 +1077,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 +1089,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, TRUE, out_domain);
+}
+
 /*
  * wrap_non_exception_throws:
  *
@@ -1244,13 +1121,12 @@ wrap_non_exception_throws (MonoMethod *m)
                for (i = 0; i < attrs->num_attrs; ++i) {
                        MonoCustomAttrEntry *attr = &attrs->attrs [i];
                        const gchar *p;
-                       int len, num_named, named_type, data_type, name_len;
+                       int num_named, named_type, name_len;
                        char *name;
 
                        if (!attr->ctor || attr->ctor->klass != klass)
                                continue;
                        /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
-                       len = attr->data_size;
                        p = (const char*)attr->data;
                        g_assert (read16 (p) == 0x0001);
                        p += 2;
@@ -1260,7 +1136,7 @@ wrap_non_exception_throws (MonoMethod *m)
                        p += 2;
                        named_type = *p;
                        p ++;
-                       data_type = *p;
+                       /* data_type = *p; */
                        p ++;
                        /* Property */
                        if (named_type != 0x54)
@@ -1396,7 +1272,9 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3
 
                unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
                if (unwind_res) {
-                       if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+                       if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                                       frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                                       frame.type == FRAME_TYPE_TRAMPOLINE) {
                                *ctx = new_ctx;
                                continue;
                        }
@@ -1482,16 +1360,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);
@@ -1679,18 +1569,17 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                        gboolean unhandled = FALSE;
 
                        /*
-                        * The exceptions caught by the mono_runtime_invoke () calls in mono_async_invoke () needs to be treated as
-                        * unhandled (#669836).
-                        * FIXME: The check below is hackish, but its hard to distinguish these runtime invoke calls from others
-                        * in the runtime.
+                        * The exceptions caught by the mono_runtime_invoke () calls
+                        * in the threadpool needs to be treated as unhandled (#669836).
+                        *
+                        * FIXME: The check below is hackish, but its hard to distinguish
+                        * these runtime invoke calls from others in the runtime.
                         */
                        if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
-                               if (prev_ji) {
-                                       MonoInternalThread *thread = mono_thread_internal_current ();
-                                       if (jinfo_get_method (prev_ji) == thread->async_invoke_method)
-                                               unhandled = TRUE;
-                               }
+                               if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
+                                       unhandled = TRUE;
                        }
+
                        if (unhandled)
                                mono_debugger_agent_handle_exception (obj, ctx, NULL);
                        else
@@ -1722,7 +1611,9 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
 
                        unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
                        if (unwind_res) {
-                               if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+                               if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+                                               frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+                                               frame.type == FRAME_TYPE_TRAMPOLINE) {
                                        *ctx = new_ctx;
                                        continue;
                                }
@@ -1776,18 +1667,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 
@@ -1849,8 +1742,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
 
                                        return 0;
                                }
-                               if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
-                                       (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
@@ -1858,8 +1750,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        jit_tls->orig_ex_ctx_set = FALSE;
                                        call_filter (ctx, ei->handler_start);
                                }
-                               if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
-                                       (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
+                               if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
                                        jit_tls->orig_ex_ctx_set = TRUE;
@@ -2162,7 +2053,7 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da
        PrintOverflowUserData *user_data = data;
        gchar *location;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method) {
@@ -2215,7 +2106,7 @@ mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx,
 
        mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
 #else
-       if (ji && jinfo_get_method (ji))
+       if (ji && !ji->is_trampoline && jinfo_get_method (ji))
                mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
        else
                mono_runtime_printf_err ("At <unmanaged>.");
@@ -2229,7 +2120,7 @@ print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer d
 {
        MonoMethod *method = NULL;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method) {
@@ -2248,7 +2139,7 @@ print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer d
        GString *p = (GString*)data;
        MonoMethod *method = NULL;
 
-       if (frame->ji)
+       if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
                method = jinfo_get_method (frame->ji);
 
        if (method && frame->domain) {
@@ -2335,7 +2226,15 @@ mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *i
                 * it will deadlock. Call the syscall directly instead.
                 */
                pid = mono_runtime_syscall_fork ();
-
+#if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
+               if (pid > 0) {
+                       // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
+                       // a value other than 0 (the most permissive ptrace scope). Most modern Linux
+                       // distributions set the scope to 1 which allows attaching only to direct children of
+                       // the current process
+                       prctl (PR_SET_PTRACER, pid, 0, 0, 0);
+               }
+#endif
                if (pid == 0) {
                        dup2 (STDERR_FILENO, STDOUT_FILENO);
 
@@ -2629,16 +2528,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");
@@ -2647,6 +2549,10 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
        ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
        ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
        ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
+
+       if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
+               return FALSE;
+
        ctx->valid = TRUE;
        return TRUE;
 #else
@@ -2655,11 +2561,31 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
 #endif
 }
 
+void
+mono_thread_state_init (MonoThreadUnwindState *ctx)
+{
+       MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
+
+#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");
+#endif
+
+       ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
+       ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
+       ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
+       ctx->valid = TRUE;
+}
+
+
 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;
        }
@@ -2676,7 +2602,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 ();
@@ -2752,7 +2678,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 ());