X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-exceptions.c;h=bc865e0d97f3aa4d7c263ccd546e0bf37a81dfa9;hb=1a4e073bafdcd9b79ab9f6217730b083d0c52302;hp=345c13135b9683ef20cddde91e9cb79eb4a76bf2;hpb=5f8ad4388627aa94a4eb7df451cf907fa9699b5b;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 345c13135b9..bc865e0d97f 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -38,6 +38,10 @@ #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + #include #include #include @@ -49,6 +53,7 @@ #include #include #include +#include #include #include @@ -94,13 +99,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 +166,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 +206,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 +226,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 +244,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 +304,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 +388,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 +400,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 +454,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 +517,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 +527,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 +545,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; } @@ -611,50 +621,6 @@ mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpoin return len > 0; } -MonoString * -ves_icall_System_Exception_get_trace (MonoException *ex) -{ - MonoDomain *domain = mono_domain_get (); - MonoString *res; - MonoArray *ta = ex->trace_ips; - int i, len; - GString *trace_str; - - if (ta == NULL) - /* Exception is not thrown yet */ - return NULL; - - len = mono_array_length (ta) >> 1; - trace_str = g_string_new (""); - for (i = 0; i < len; i++) { - MonoJitInfo *ji; - 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); - if (ji == NULL) { - /* Unmanaged frame */ - g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip); - } else { - gchar *location; - gint32 address; - MonoMethod *method = get_method_from_stack_frame (ji, generic_info); - - address = (char *)ip - (char *)ji->code_start; - location = mono_debug_print_stack_frame ( - method, address, ex->object.vtable->domain); - - g_string_append_printf (trace_str, "%s\n", location); - g_free (location); - } - } - - res = mono_string_new (ex->object.vtable->domain, trace_str->str); - g_string_free (trace_str, TRUE); - - return res; -} - MonoArray * ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info) { @@ -694,12 +660,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,7 +681,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; @@ -802,6 +770,10 @@ mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, g_assert (state->valid); + if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN]) + /* Not attached */ + return; + mono_walk_stack_full (func, &state->ctx, state->unwind_data [MONO_UNWIND_DATA_DOMAIN], @@ -864,7 +836,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 +844,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 +855,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 +910,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 +951,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 +970,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 +999,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 +1015,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 +1024,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 +1038,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 +1050,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: * @@ -1313,18 +1151,42 @@ build_native_trace (void) #endif } -#define setup_managed_stacktrace_information() do { \ - if (mono_ex && !initial_trace_ips) { \ - trace_ips = g_list_reverse (trace_ips); \ - MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class)); \ - MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ()); \ - if (has_dynamic_methods) \ - /* These methods could go away anytime, so compute the stack trace now */ \ - MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); \ - } \ - g_list_free (trace_ips); \ - trace_ips = NULL; \ -} while (0) +static void +setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *initial_trace_ips, GList **trace_ips) +{ + if (mono_ex && !initial_trace_ips) { + *trace_ips = g_list_reverse (*trace_ips); + MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (*trace_ips, mono_defaults.int_class)); + MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ()); + if (dynamic_methods) { + /* These methods could go away anytime, so save a reference to them in the exception object */ + GSList *l; + MonoMList *list = NULL; + + for (l = dynamic_methods; l; l = l->next) { + guint32 dis_link; + MonoDomain *domain = mono_domain_get (); + + if (domain->method_to_dyn_method) { + mono_domain_lock (domain); + dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, l->data); + mono_domain_unlock (domain); + if (dis_link) { + MonoObject *o = mono_gchandle_get_target (dis_link); + if (o) { + list = mono_mlist_prepend (list, o); + } + } + } + } + + MONO_OBJECT_SETREF (mono_ex, dynamic_methods, list); + } + } + g_list_free (*trace_ips); + *trace_ips = NULL; +} + /* * mono_handle_exception_internal_first_pass: * @@ -1342,12 +1204,12 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 MonoLMF *lmf = mono_get_lmf (); MonoArray *initial_trace_ips = NULL; GList *trace_ips = NULL; + GSList *dynamic_methods = NULL; MonoException *mono_ex; gboolean stack_overflow = FALSE; MonoContext initial_ctx; MonoMethod *method; int frame_count = 0; - gboolean has_dynamic_methods = FALSE; gint32 filter_idx; int i; MonoObject *ex_obj; @@ -1395,7 +1257,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; } @@ -1404,7 +1268,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 } if (!unwind_res) { - setup_managed_stacktrace_information (); + setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips); + g_slist_free (dynamic_methods); return FALSE; } @@ -1432,7 +1297,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 } if (method->dynamic) - has_dynamic_methods = TRUE; + dynamic_methods = g_slist_prepend (dynamic_methods, method); if (stack_overflow) { if (DOES_STACK_GROWS_UP) @@ -1479,18 +1344,30 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 FIXME Not 100% sure if it's a good idea even with user clauses. */ if (is_user_frame) - setup_managed_stacktrace_information (); + setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips); - 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); @@ -1503,7 +1380,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 if (filtered) { if (!is_user_frame) - setup_managed_stacktrace_information (); + setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips); + g_slist_free (dynamic_methods); /* mono_debugger_agent_handle_exception () needs this */ MONO_CONTEXT_SET_IP (ctx, ei->handler_start); return TRUE; @@ -1511,7 +1389,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 } if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) { - setup_managed_stacktrace_information (); + setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips); + g_slist_free (dynamic_methods); if (out_ji) *out_ji = ji; @@ -1678,18 +1557,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 @@ -1721,7 +1599,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; } @@ -1775,18 +1655,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 @@ -1848,8 +1730,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; @@ -1857,8 +1738,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; @@ -2161,7 +2041,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) { @@ -2214,7 +2094,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 ."); @@ -2228,7 +2108,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) { @@ -2247,7 +2127,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) { @@ -2334,7 +2214,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); @@ -2635,18 +2523,20 @@ mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx) return FALSE; } - if (sigctx) + if (sigctx) { mono_sigctx_to_monoctx (sigctx, &ctx->ctx); - else -#if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE) - 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->jit_data; + 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; + } + else { + mono_thread_state_init (ctx); + } + + if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF]) + return FALSE; + ctx->valid = TRUE; return TRUE; #else @@ -2655,6 +2545,26 @@ 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) {