X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Fmini-exceptions.c;h=26c9451330e2e6786e57841f94baed3ce723afc8;hb=a595d489fa64d8e213c74470f23c576296e2d548;hp=d5323d2a3bae65565e1b0dba00affd7927980fc9;hpb=bb4e6d08efedf1582f5b1b8df9f352cbf08db8cd;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index d5323d2a3ba..26c9451330e 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -42,24 +42,36 @@ #include #endif +#ifdef HAVE_UNWIND_H +#include +#endif + #include #include #include #include #include #include -#include +#include +#include #include #include #include #include +#include #include -#include +#include #include "mini.h" #include "trace.h" #include "debugger-agent.h" #include "seq-points.h" +#include "llvm-runtime.h" +#include "mini-llvm.h" + +#ifdef ENABLE_LLVM +#include "mini-llvm-cpp.h" +#endif #ifdef ENABLE_EXTENSION_MODULE #include "../../../mono-extensions/mono/mini/mini-exceptions.c" @@ -98,17 +110,19 @@ 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); - restore_stack_protection_tramp = mono_create_specific_trampoline (restore_stack_protection, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL); + if (!mono_llvm_only) { + try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL); + restore_stack_protection_tramp = mono_create_specific_trampoline (restore_stack_protection, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL); + } #endif #ifdef MONO_ARCH_HAVE_EXCEPTIONS_INIT @@ -116,7 +130,11 @@ mono_exceptions_init (void) #endif cbs.mono_walk_stack_with_ctx = mono_runtime_walk_stack_with_ctx; cbs.mono_walk_stack_with_state = mono_walk_stack_with_state; - cbs.mono_raise_exception = mono_get_throw_exception (); + + if (mono_llvm_only) + cbs.mono_raise_exception = mono_llvm_raise_exception; + else + cbs.mono_raise_exception = mono_get_throw_exception (); cbs.mono_raise_exception_with_ctx = mono_raise_exception_with_ctx; cbs.mono_exception_walk_trace = mono_exception_walk_trace; cbs.mono_install_handler_block_guard = mono_install_handler_block_guard; @@ -165,7 +183,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 (); @@ -243,6 +261,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; @@ -301,10 +321,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; @@ -397,7 +417,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) { @@ -451,6 +471,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) { @@ -511,7 +534,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); @@ -521,15 +544,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); @@ -539,18 +562,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; } @@ -615,50 +638,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) { @@ -808,6 +787,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], @@ -870,7 +853,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); @@ -889,7 +872,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; @@ -944,7 +927,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; @@ -983,25 +968,6 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, return TRUE; } -static MonoArray * -glist_to_array (GList *list, MonoClass *eclass) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - int len, i; - - if (!list) - return NULL; - - len = g_list_length (list); - res = mono_array_new (domain, eclass, len); - - for (i = 0; list; list = list->next, i++) - mono_array_set (res, gpointer, i, list->data); - - return res; -} - static MonoClass* get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx) { @@ -1085,7 +1051,7 @@ 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, FALSE, out_domain); + return mini_jit_info_table_find_ext (domain, addr, TRUE, out_domain); } /* @@ -1183,18 +1149,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, mono_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: * @@ -1212,12 +1202,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; @@ -1265,7 +1255,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; } @@ -1274,7 +1266,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; } @@ -1302,7 +1295,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) @@ -1349,7 +1342,7 @@ 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); #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG if (ji->from_llvm) @@ -1385,7 +1378,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; @@ -1393,7 +1387,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; @@ -1531,7 +1526,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, if (msg == NULL) { msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)"); } - g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg); + g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)mono_native_thread_id_get (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg); g_free (msg); if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex))) mono_print_thread_dump_from_ctx (ctx); @@ -1602,7 +1597,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; } @@ -1731,8 +1728,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; @@ -1740,8 +1736,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; @@ -1984,6 +1979,9 @@ mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, g gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr) { + if (mono_llvm_only) + return FALSE; + /* we got a stack overflow in the soft-guard pages * There are two cases: * 1) managed code caused the overflow: we unprotect the soft-guard page @@ -2044,7 +2042,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) { @@ -2097,7 +2095,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 ."); @@ -2111,7 +2109,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) { @@ -2130,7 +2128,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) { @@ -2526,20 +2524,16 @@ 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 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->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; @@ -2552,6 +2546,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) { @@ -2699,3 +2713,212 @@ mono_jinfo_get_epilog_size (MonoJitInfo *ji) return info->epilog_size; } + +/* + * 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) +{ + 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); + else + mono_ex = (MonoException*)ex; + + // Note: Not pinned + jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE); + + if (!rethrow) { +#ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE + GList *l, *ips = NULL; + GList *trace; + + _Unwind_Backtrace (build_stack_trace, &ips); + /* The list contains gshared info-ip pairs */ + trace = NULL; + ips = g_list_reverse (ips); + for (l = ips; l; l = l->next) { + // FIXME: + trace = g_list_append (trace, l->data); + trace = g_list_append (trace, NULL); + } + MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_glist_to_array (trace, mono_defaults.int_class)); + g_list_free (l); + g_list_free (trace); +#endif + } + + mono_llvm_cpp_throw_exception (); +} + +void +mono_llvm_throw_exception (MonoObject *ex) +{ + throw_exception (ex, FALSE); +} + +void +mono_llvm_rethrow_exception (MonoObject *ex) +{ + throw_exception (ex, TRUE); +} + +void +mono_llvm_raise_exception (MonoException *e) +{ + mono_llvm_throw_exception ((MonoObject*)e); +} + +void +mono_llvm_throw_corlib_exception (guint32 ex_token_index) +{ + guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index; + MonoException *ex; + + ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token); + + mono_llvm_throw_exception ((MonoObject*)ex); +} + +/* + * mono_llvm_resume_exception: + * + * Resume exception propagation. + */ +void +mono_llvm_resume_exception (void) +{ + mono_llvm_cpp_throw_exception (); +} + +/* + * mono_llvm_load_exception: + * + * Return the currently thrown exception. + */ +MonoObject * +mono_llvm_load_exception (void) +{ + MonoJitTlsData *jit_tls = mono_get_jit_tls (); + + MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc); + g_assert (mono_ex->trace_ips); + + GList *trace_ips = NULL; + gpointer ip = __builtin_return_address (0); + + size_t upper = mono_array_length (mono_ex->trace_ips); + + for (int i = 0; i < upper; i++) { + gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i); + trace_ips = g_list_prepend (trace_ips, curr_ip); + + if (ip == curr_ip) + break; + } + + // FIXME: Does this work correctly for rethrows? + // We may be discarding useful information + // when this gets GC'ed + MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_glist_to_array (trace_ips, mono_defaults.int_class)); + g_list_free (trace_ips); + + // FIXME: + //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); + + return &mono_ex->object; +} + +/* + * mono_llvm_clear_exception: + * + * Mark the currently thrown exception as handled. + */ +void +mono_llvm_clear_exception (void) +{ + MonoJitTlsData *jit_tls = mono_get_jit_tls (); + mono_gchandle_free (jit_tls->thrown_exc); + jit_tls->thrown_exc = 0; + + mono_memory_barrier (); +} + +/* + * mono_llvm_match_exception: + * + * Return the innermost clause containing REGION_START-REGION_END which can handle + * the current exception. + */ +gint32 +mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end) +{ + MonoJitTlsData *jit_tls = mono_get_jit_tls (); + MonoObject *exc; + gint32 index = -1; + + g_assert (jit_tls->thrown_exc); + exc = mono_gchandle_get_target (jit_tls->thrown_exc); + for (int i = 0; i < jinfo->num_clauses; i++) { + MonoJitExceptionInfo *ei = &jinfo->clauses [i]; + + if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) ) + continue; + + // FIXME: Handle edge cases handled in get_exception_catch_class + if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, ei->data.catch_class)) { + index = ei->clause_index; + break; + } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { + g_assert_not_reached (); + } + } + + return index; +} + +#ifdef ENABLE_LLVM +_Unwind_Reason_Code +mono_debug_personality (int a, _Unwind_Action b, +uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e) +{ + g_assert_not_reached (); +} +#else +void +mono_debug_personality (void); + +void +mono_debug_personality (void) +{ + g_assert_not_reached (); +} +#endif