X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Fmini-exceptions.c;h=77d5fdcb1ebf654bd4c6e43093bca0e30b232721;hb=ff49850dfc18f5991246a203184fa1e0b8a7c7ab;hp=835a6c9abbd1e58e632e281e82081e792055e26d;hpb=d37a42b83bec10a23ba88cb21640e88b88e1ecd3;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 835a6c9abbd..77d5fdcb1eb 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -52,7 +52,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -61,6 +63,8 @@ #include #include #include +#include +#include #include "mini.h" #include "trace.h" @@ -232,6 +236,48 @@ is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip) return TRUE; } +#ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE + +#if 0 +static gboolean show_native_addresses = TRUE; +#else +static gboolean show_native_addresses = FALSE; +#endif + +static _Unwind_Reason_Code +build_stack_trace (struct _Unwind_Context *frame_ctx, void *state) +{ + MonoDomain *domain = mono_domain_get (); + uintptr_t ip = _Unwind_GetIP (frame_ctx); + + if (show_native_addresses || mono_jit_info_table_find (domain, (char*)ip)) { + GList **trace_ips = (GList **)state; + *trace_ips = g_list_prepend (*trace_ips, (gpointer)ip); + } + + return _URC_NO_REASON; +} + +static GSList* +get_unwind_backtrace (void) +{ + GSList *ips = NULL; + + _Unwind_Backtrace (build_stack_trace, &ips); + + return g_slist_reverse (ips); +} + +#else + +static GSList* +get_unwind_backtrace (void) +{ + return NULL; +} + +#endif + /* * find_jit_info: * @@ -657,6 +703,7 @@ mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpoin MonoArray * ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoArray *res; MonoArray *ta = exc->trace_ips; @@ -674,7 +721,11 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info for (i = skip; i < len; i++) { MonoJitInfo *ji; - MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class); + MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0); gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1); MonoMethod *method; @@ -688,7 +739,11 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info g_assert (ji != NULL); - method = get_method_from_stack_frame (ji, generic_info); + if (mono_llvm_only) + /* Can't resolve actual method */ + method = jinfo_get_method (ji); + else + method = get_method_from_stack_frame (ji, generic_info); if (jinfo_get_method (ji)->wrapper_type) { char *s; @@ -697,8 +752,14 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info 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)); + else { + MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return NULL; + } + MONO_OBJECT_SETREF (sf, method, rm); + } sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff; sf->method_address = (gsize) ji->code_start; @@ -851,6 +912,37 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS; gboolean async = mono_thread_info_is_async_context (); + if (mono_llvm_only) { + GSList *l, *ips; + + if (async) + return; + + ips = get_unwind_backtrace (); + for (l = ips; l; l = l->next) { + guint8 *ip = (guint8*)l->data; + memset (&frame, 0, sizeof (StackFrameInfo)); + frame.ji = mini_jit_info_table_find (domain, (char*)ip, &frame.domain); + if (!frame.ji || frame.ji->is_trampoline) + continue; + frame.type = FRAME_TYPE_MANAGED; + frame.method = jinfo_get_method (frame.ji); + // FIXME: Cannot lookup the actual method + frame.actual_method = frame.method; + if (frame.type == FRAME_TYPE_MANAGED) { + if (!frame.method->wrapper_type || frame.method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) + frame.managed = TRUE; + } + frame.native_offset = ip - (guint8*)frame.ji->code_start; + frame.il_offset = -1; + + if (func (&frame, NULL, user_data)) + break; + } + g_free (ips); + return; + } + g_assert (start_ctx); g_assert (domain); g_assert (jit_tls); @@ -916,6 +1008,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, gint32 *iloffset, gint32 *native_offset, MonoString **file, gint32 *line, gint32 *column) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); MonoLMF *lmf = mono_get_lmf (); @@ -928,39 +1021,75 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, MONO_ARCH_CONTEXT_DEF; - mono_arch_flush_register_windows (); + if (mono_llvm_only) { + GSList *l, *ips; + MonoDomain *frame_domain; + guint8 *frame_ip = NULL; + + /* FIXME: Generalize this code with an interface which returns an array of StackFrame structures */ + jmethod = NULL; + ips = get_unwind_backtrace (); + for (l = ips; l && skip >= 0; l = l->next) { + guint8 *ip = (guint8*)l->data; + + frame_ip = ip; + + ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &frame_domain); + if (!ji || ji->is_trampoline) + continue; + + /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */ + jmethod = jinfo_get_method (ji); + if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE) + continue; + skip--; + } + g_slist_free (ips); + if (!jmethod || !l) + return FALSE; + /* No way to resolve generic instances */ + actual_method = jmethod; + *native_offset = frame_ip - (guint8*)ji->code_start; + } else { + mono_arch_flush_register_windows (); #ifdef MONO_INIT_CONTEXT_FROM_CURRENT - MONO_INIT_CONTEXT_FROM_CURRENT (&ctx); + MONO_INIT_CONTEXT_FROM_CURRENT (&ctx); #else - MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info); + MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info); #endif - new_ctx = ctx; - do { - ctx = new_ctx; - res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame); - if (!res) - return FALSE; + new_ctx = ctx; + do { + ctx = new_ctx; + res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame); + if (!res) + return FALSE; - if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || + if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_TRAMPOLINE) - continue; + continue; - ji = frame.ji; - *native_offset = frame.native_offset; + ji = frame.ji; + *native_offset = frame.native_offset; - /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */ - jmethod = jinfo_get_method (ji); - if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE) - continue; - skip--; - } while (skip >= 0); + /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */ + jmethod = jinfo_get_method (ji); + if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE) + continue; + skip--; + } while (skip >= 0); - actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx)); + actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx)); + } - mono_gc_wbarrier_generic_store (method, (MonoObject*) mono_method_get_object (domain, actual_method, NULL)); + MonoReflectionMethod *rm = mono_method_get_object_checked (domain, actual_method, NULL, &error); + if (!mono_error_ok (&error)) { + mono_error_set_pending_exception (&error); + return FALSE; + } + mono_gc_wbarrier_generic_store (method, (MonoObject*) rm); location = mono_debug_lookup_source_location (jmethod, *native_offset, domain); if (location) @@ -987,6 +1116,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, static MonoClass* get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx) { + MonoError error; MonoClass *catch_class = ei->data.catch_class; MonoType *inflated_type; MonoGenericContext context; @@ -1005,7 +1135,9 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex when the exception is actually thrown, so as not to waste space for exception clauses which might never be encountered. */ - inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context); + inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + catch_class = mono_class_from_mono_type (inflated_type); mono_metadata_free_type (inflated_type); @@ -1067,9 +1199,12 @@ mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_tra 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); + return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain); } +/* Class lazy loading functions */ +static GENERATE_GET_CLASS_WITH_CACHE (runtime_compat_attr, System.Runtime.CompilerServices, RuntimeCompatibilityAttribute) + /* * wrap_non_exception_throws: * @@ -1079,9 +1214,10 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai static gboolean wrap_non_exception_throws (MonoMethod *m) { + MonoError error; MonoAssembly *ass = m->klass->image->assembly; MonoCustomAttrInfo* attrs; - static MonoClass *klass; + MonoClass *klass; int i; gboolean val = FALSE; @@ -1089,9 +1225,10 @@ wrap_non_exception_throws (MonoMethod *m) if (ass->wrap_non_exception_throws_inited) return ass->wrap_non_exception_throws; - klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute"); + klass = mono_class_get_runtime_compat_attr_class (); - attrs = mono_custom_attrs_from_assembly (ass); + attrs = mono_custom_attrs_from_assembly_checked (ass, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ if (attrs) { for (i = 0; i < attrs->num_attrs; ++i) { MonoCustomAttrEntry *attr = &attrs->attrs [i]; @@ -1211,6 +1348,7 @@ setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *i static gboolean mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoJitInfo *ji = NULL; static int (*call_filter) (MonoContext *, gpointer) = NULL; @@ -1236,10 +1374,11 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi mono_ex = (MonoException*)obj; initial_trace_ips = mono_ex->trace_ips; - if (mono_object_isinst (obj, mono_defaults.exception_class)) { + if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) { mono_ex = (MonoException*)obj; initial_trace_ips = mono_ex->trace_ips; } else { + mono_error_assert_ok (&error); mono_ex = NULL; } @@ -1402,7 +1541,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi } } - if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) { + if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) { setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips); g_slist_free (dynamic_methods); @@ -1413,6 +1552,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi MONO_CONTEXT_SET_IP (ctx, ei->handler_start); return TRUE; } + mono_error_cleanup (&error); } } @@ -1431,6 +1571,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi static gboolean mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resume, MonoJitInfo **out_ji) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoJitInfo *ji, *prev_ji; static int (*call_filter) (MonoContext *, gpointer) = NULL; @@ -1467,9 +1608,11 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu obj = (MonoObject *)mono_get_exception_null_reference (); } - if (!mono_object_isinst (obj, mono_defaults.exception_class)) { + if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) { + mono_error_assert_ok (&error); non_exception = obj; - obj = (MonoObject *)mono_get_exception_runtime_wrapped (obj); + obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error); + mono_error_assert_ok (&error); } mono_ex = (MonoException*)obj; @@ -1480,9 +1623,10 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu ; } - if (mono_object_isinst (obj, mono_defaults.exception_class)) { + if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) { mono_ex = (MonoException*)obj; } else { + mono_error_assert_ok (&error); mono_ex = NULL; } @@ -1529,15 +1673,16 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu MonoObject *message; const char *type_name = mono_class_get_name (mono_object_class (mono_ex)); char *msg = NULL; - MonoObject *exc = NULL; if (get_message == NULL) { message = NULL; } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) { message = NULL; msg = g_strdup_printf ("(No exception message for: %s)\n", type_name); } else { - message = mono_runtime_invoke (get_message, obj, NULL, &exc); - + MonoObject *exc = NULL; + message = mono_runtime_try_invoke (get_message, obj, NULL, &exc, &error); + g_assert (exc == NULL); + mono_error_assert_ok (&error); } if (msg == NULL) { msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)"); @@ -1571,7 +1716,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu gboolean unhandled = FALSE; /* - * The exceptions caught by the mono_runtime_invoke () calls + * The exceptions caught by the mono_runtime_invoke_checked () calls * in the threadpool needs to be treated as unhandled (#669836). * * FIXME: The check below is hackish, but its hard to distinguish @@ -1692,8 +1837,9 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu filter_idx ++; } + mono_error_init (&error); if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && - mono_object_isinst (ex_obj, catch_class)) || filtered) { + mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) { /* * This guards against the situation that we abort a thread that is executing a finally clause * that was called by the EH machinery. It won't have a guard trampoline installed, so we must @@ -1744,6 +1890,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu return 0; } + mono_error_cleanup (&error); 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)); @@ -2735,38 +2882,18 @@ mono_jinfo_get_epilog_size (MonoJitInfo *ji) * LLVM/Bitcode exception handling. */ -#ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE - -#if 0 -static gboolean show_native_addresses = TRUE; -#else -static gboolean show_native_addresses = FALSE; -#endif - -static _Unwind_Reason_Code -build_stack_trace (struct _Unwind_Context *frame_ctx, void *state) -{ - MonoDomain *domain = mono_domain_get (); - uintptr_t ip = _Unwind_GetIP (frame_ctx); - - if (show_native_addresses || mono_jit_info_table_find (domain, (char*)ip)) { - GList **trace_ips = (GList **)state; - *trace_ips = g_list_prepend (*trace_ips, (gpointer)ip); - } - - return _URC_NO_REASON; -} - -#endif - static void throw_exception (MonoObject *ex, gboolean rethrow) { + MonoError error; MonoJitTlsData *jit_tls = mono_get_jit_tls (); MonoException *mono_ex; - if (!mono_object_isinst (ex, mono_defaults.exception_class)) - mono_ex = mono_get_exception_runtime_wrapped (ex); + if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) { + mono_error_assert_ok (&error); + mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error); + mono_error_assert_ok (&error); + } else mono_ex = (MonoException*)ex; @@ -2903,6 +3030,7 @@ mono_llvm_clear_exception (void) gint32 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj) { + MonoError error; MonoJitTlsData *jit_tls = mono_get_jit_tls (); MonoObject *exc; gint32 index = -1; @@ -2923,16 +3051,21 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg g_assert (rgctx || this_obj); context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable); - inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context); + inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + catch_class = mono_class_from_mono_type (inflated_type); mono_metadata_free_type (inflated_type); } // FIXME: Handle edge cases handled in get_exception_catch_class - if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, catch_class)) { + if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) { index = ei->clause_index; break; - } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { + } else + mono_error_assert_ok (&error); + + if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { g_assert_not_reached (); } }