X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-exceptions.c;h=ce350f6fcd68f4b3380b04eb694b9497e6ebf585;hb=566863ff092a568451134512dd39f17600c6ea31;hp=f382d5e41b2acface36ec51bc62342a29f880388;hpb=b7c17c47e6b3c02192e64175cb5ee0ce7f7dda1b;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index f382d5e41b2..ce350f6fcd6 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -24,6 +24,83 @@ #define IS_ON_SIGALTSTACK(jit_tls) ((jit_tls) && ((guint8*)&(jit_tls) > (guint8*)(jit_tls)->signal_stack) && ((guint8*)&(jit_tls) < ((guint8*)(jit_tls)->signal_stack + (jit_tls)->signal_stack_size))) +/* mono_find_jit_info: + * + * This function is used to gather information from @ctx. It return the + * MonoJitInfo of the corresponding function, unwinds one stack frame and + * stores the resulting context into @new_ctx. It also stores a string + * describing the stack location into @trace (if not NULL), and modifies + * the @lmf if necessary. @native_offset return the IP offset from the + * start of the function or -1 if that info is not available. + */ +static MonoJitInfo * +mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, + MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, + gboolean *managed) +{ + gboolean managed2; + gpointer ip = MONO_CONTEXT_GET_IP (ctx); + MonoJitInfo *ji; + + if (trace) + *trace = NULL; + + if (native_offset) + *native_offset = -1; + + if (managed) + *managed = FALSE; + + ji = mono_arch_find_jit_info (domain, jit_tls, res, prev_ji, ctx, new_ctx, NULL, lmf, NULL, &managed2); + + if (ji == (gpointer)-1) + return ji; + + if (managed2 || ji->method->wrapper_type) { + char *source_location, *tmpaddr, *fname; + gint32 address, iloffset; + + address = (char *)ip - (char *)ji->code_start; + + if (native_offset) + *native_offset = address; + + if (managed) + if (!ji->method->wrapper_type) + *managed = TRUE; + + if (trace) { + source_location = mono_debug_source_location_from_address (ji->method, address, NULL, domain); + iloffset = mono_debug_il_offset_from_address (ji->method, address, domain); + + if (iloffset < 0) + tmpaddr = g_strdup_printf ("<0x%05x>", address); + else + tmpaddr = g_strdup_printf ("[0x%05x]", iloffset); + + fname = mono_method_full_name (ji->method, TRUE); + + if (source_location) + *trace = g_strdup_printf ("in %s (at %s) %s", tmpaddr, source_location, fname); + else + *trace = g_strdup_printf ("in %s %s", tmpaddr, fname); + + g_free (fname); + g_free (source_location); + g_free (tmpaddr); + } + } + else { + if (trace) { + char *fname = mono_method_full_name (res->method, TRUE); + *trace = g_strdup_printf ("in (unmanaged) %s", fname); + g_free (fname); + } + } + + return ji; +} + MonoArray * ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info) { @@ -78,7 +155,7 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info } void -mono_jit_walk_stack (MonoStackWalk func, gpointer user_data) { +mono_jit_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data) { MonoDomain *domain = mono_domain_get (); MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); MonoLMF *lmf = jit_tls->lmf; @@ -95,13 +172,13 @@ mono_jit_walk_stack (MonoStackWalk func, gpointer user_data) { while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) { - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed); + ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed); g_assert (ji); if (ji == (gpointer)-1) return; - il_offset = mono_debug_il_offset_from_address (ji->method, native_offset, domain); + il_offset = do_il_offset ? mono_debug_il_offset_from_address (ji->method, native_offset, domain): -1; if (func (ji->method, native_offset, il_offset, managed, user_data)) return; @@ -130,7 +207,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, skip++; do { - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL); + ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL); ctx = new_ctx; @@ -139,6 +216,8 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, /* skip all wrappers ??*/ if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE || + ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE || + ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH || ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK || ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) continue; @@ -205,7 +284,8 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo MonoContext initial_ctx; int frame_count = 0; gboolean gc_disabled = FALSE; - MonoString *initial_stack_trace; + MonoString *initial_stack_trace = NULL; + GString *trace_str = NULL; /* * This function might execute on an alternate signal stack, and Boehm GC @@ -270,7 +350,7 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo G_BREAKPOINT (); mono_unhandled_exception (obj); - if (mono_debugger_unhandled_exception (original_ip, obj)) { + if (mono_debugger_unhandled_exception (original_ip, MONO_CONTEXT_GET_SP (ctx), obj)) { /* * If this returns true, then we're running inside the * Mono Debugger and the debugger wants us to restore the @@ -294,11 +374,14 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo gboolean need_trace = FALSE; guint32 free_stack; - if (test_only && (frame_count < 1000)) + if (test_only && (frame_count < 1000)) { need_trace = TRUE; + if (!trace_str) + trace_str = g_string_new (""); + } - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx, - need_trace ? &trace : NULL, &lmf, NULL, NULL); + ji = mono_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx, + need_trace ? &trace : NULL, &lmf, NULL, NULL); if (!ji) { g_warning ("Exception inside function without unwind info"); g_assert_not_reached (); @@ -309,27 +392,16 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo //printf ("M: %s %d %d.\n", mono_method_full_name (ji->method, TRUE), frame_count, test_only); if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) { - char *tmp, *strace; - /* * Avoid overwriting the stack trace if the exception is * rethrown. Also avoid giant stack traces during a stack * overflow. */ if (!initial_stack_trace && (frame_count < 1000)) { - trace_ips = g_list_append (trace_ips, MONO_CONTEXT_GET_IP (ctx)); - - if (!mono_ex->stack_trace) - strace = g_strdup (""); - else - strace = mono_string_to_utf8 (mono_ex->stack_trace); - - tmp = g_strdup_printf ("%s%s\n", strace, trace); - g_free (strace); + trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx)); - mono_ex->stack_trace = mono_string_new (domain, tmp); - - g_free (tmp); + g_string_append (trace_str, trace); + g_string_append_c (trace_str, '\n'); } } @@ -359,31 +431,43 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo /* store the exception object int cfg->excvar */ g_assert (ji->exvar_offset); *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj; + if (!initial_stack_trace && trace_str) { + mono_ex->stack_trace = mono_string_new (domain, trace_str->str); + } } - if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) + if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { + mono_debugger_handle_exception (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), obj); filtered = call_filter (ctx, ei->data.filter); + } if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && - mono_object_isinst (obj, mono_class_get (ji->method->klass->image, ei->data.token))) || filtered) { + mono_object_isinst (obj, ei->data.catch_class)) || filtered) { if (test_only) { - if (mono_ex) + if (mono_ex) { + trace_ips = g_list_reverse (trace_ips); mono_ex->trace_ips = glist_to_array (trace_ips); + } g_list_free (trace_ips); g_free (trace); if (gc_disabled) mono_gc_enable (); + if (trace_str) + g_string_free (trace_str, TRUE); return TRUE; } if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE)); + mono_debugger_handle_exception (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), obj); MONO_CONTEXT_SET_IP (ctx, ei->handler_start); jit_tls->lmf = lmf; g_free (trace); if (gc_disabled) mono_gc_enable (); + if (trace_str) + g_string_free (trace_str, TRUE); return 0; } if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && @@ -391,6 +475,7 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) { if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE)); + mono_debugger_handle_exception (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), obj); call_filter (ctx, ei->handler_start); } @@ -422,9 +507,13 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo jit_tls->abort_func (obj); g_assert_not_reached (); } else { - if (mono_ex) + if (mono_ex) { + trace_ips = g_list_reverse (trace_ips); mono_ex->trace_ips = glist_to_array (trace_ips); + } g_list_free (trace_ips); + if (trace_str) + g_string_free (trace_str, TRUE); return FALSE; } }