X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-exceptions.c;h=18ff15488d3075b112c00295f04bc36dc97356b3;hb=94f79d6fcb3a15085bc09f6f12fed9108f3e9a77;hp=d3ad78032c93fe7c7963ef84be277b3f632f458d;hpb=a2a78adb54383f1ee8ef62118982c7c6fd87bfec;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index d3ad78032c9..18ff15488d3 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -25,6 +25,7 @@ #include #include "mini.h" +#include "trace.h" #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK #include @@ -50,8 +51,8 @@ */ 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) + MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, + gboolean *managed) { gboolean managed2; gpointer ip = MONO_CONTEXT_GET_IP (ctx); @@ -72,14 +73,20 @@ mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *re return ji; if (managed2 || ji->method->wrapper_type) { - char *source_location, *tmpaddr, *fname; - gint32 offset, iloffset; + const char *real_ip, *start; + gint32 offset; + start = (const char *)ji->code_start; if (!managed2) /* ctx->ip points into native code */ - offset = (char*)MONO_CONTEXT_GET_IP (new_ctx) - (char*)ji->code_start; + real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx); else - offset = (char *)ip - (char *)ji->code_start; + real_ip = (const char*)ip; + + if ((real_ip >= start) && (real_ip <= start + ji->code_size)) + offset = real_ip - start; + else + offset = -1; if (native_offset) *native_offset = offset; @@ -88,28 +95,9 @@ mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *re if (!ji->method->wrapper_type) *managed = TRUE; - if (trace) { - source_location = mono_debug_source_location_from_address (ji->method, offset, NULL, domain); - iloffset = mono_debug_il_offset_from_address (ji->method, offset, domain); - - if (iloffset < 0) - tmpaddr = g_strdup_printf ("<0x%05x>", offset); - 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) + *trace = mono_debug_print_stack_frame (ji->method, offset, domain); + } else { if (trace) { char *fname = mono_method_full_name (res->method, TRUE); *trace = g_strdup_printf ("in (unmanaged) %s", fname); @@ -130,7 +118,6 @@ ves_icall_System_Exception_get_trace (MonoException *ex) MonoArray *ta = ex->trace_ips; int i, len; GString *trace_str; - char tmpaddr [256]; if (ta == NULL) /* Exception is not thrown yet */ @@ -147,28 +134,15 @@ ves_icall_System_Exception_get_trace (MonoException *ex) /* Unmanaged frame */ g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip); } else { - char *source_location, *fname; - gint32 address, iloffset; + gchar *location; + gint32 address; address = (char *)ip - (char *)ji->code_start; + location = mono_debug_print_stack_frame ( + ji->method, address, ex->object.vtable->domain); - source_location = mono_debug_source_location_from_address (ji->method, address, NULL, ex->object.vtable->domain); - iloffset = mono_debug_il_offset_from_address (ji->method, address, ex->object.vtable->domain); - - if (iloffset < 0) - sprintf (tmpaddr, "<0x%05x>", address); - else - sprintf (tmpaddr, "[0x%05x]", iloffset); - - fname = mono_method_full_name (ji->method, TRUE); - - if (source_location) - g_string_append_printf (trace_str, "in %s (at %s) %s\n", tmpaddr, source_location, fname); - else - g_string_append_printf (trace_str, "in %s %s\n", tmpaddr, fname); - - g_free (fname); - g_free (source_location); + g_string_append_printf (trace_str, "%s\n", location); + g_free (location); } } @@ -184,6 +158,7 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info MonoDomain *domain = mono_domain_get (); MonoArray *res; MonoArray *ta = exc->trace_ips; + MonoDebugSourceLocation *location; int i, len; if (ta == NULL) { @@ -203,7 +178,7 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info ji = mono_jit_info_table_find (domain, ip); if (ji == NULL) { /* Unmanaged frame */ - mono_array_set (res, gpointer, i, sf); + mono_array_setref (res, i, sf); continue; } @@ -214,27 +189,37 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info sf->method = NULL; s = mono_method_full_name (ji->method, TRUE); - sf->internal_method_name = mono_string_new (domain, s); + MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s)); g_free (s); } else - sf->method = mono_method_get_object (domain, ji->method, NULL); + MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, ji->method, NULL)); sf->native_offset = (char *)ip - (char *)ji->code_start; - sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain); + /* + * mono_debug_lookup_source_location() returns both the file / line number information + * and the IL offset. Note that computing the IL offset is already an expensive + * operation, so we shouldn't call this method twice. + */ + location = mono_debug_lookup_source_location (ji->method, sf->native_offset, domain); + if (location) + sf->il_offset = location->il_offset; + else + sf->il_offset = 0; if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain); - - sf->filename = filename? mono_string_new (domain, filename): NULL; - sf->column = 0; - - g_free (filename); + if (location) { + MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file)); + sf->line = location->row; + sf->column = location->column; + } else { + sf->line = sf->column = 0; + sf->filename = NULL; + } } - mono_array_set (res, gpointer, i, sf); + mono_debug_free_source_location (location); + mono_array_setref (res, i, sf); } return res; @@ -310,14 +295,20 @@ mono_jit_walk_stack_from_ctx (MonoStackWalk func, MonoContext *start_ctx, gboole } while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) { - 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 = do_il_offset ? mono_debug_il_offset_from_address (ji->method, native_offset, domain): -1; + if (do_il_offset) { + MonoDebugSourceLocation *source; + + source = mono_debug_lookup_source_location (ji->method, native_offset, domain); + il_offset = source ? source->il_offset : -1; + mono_debug_free_source_location (source); + } else + il_offset = -1; if (func (ji->method, native_offset, il_offset, managed, user_data)) return; @@ -343,14 +334,26 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, MonoLMF *lmf = jit_tls->lmf; MonoJitInfo *ji, rji; MonoContext ctx, new_ctx; + MonoDebugSourceLocation *location; MONO_ARCH_CONTEXT_DEF; mono_arch_flush_register_windows (); +#ifdef MONO_INIT_CONTEXT_FROM_CURRENT + MONO_INIT_CONTEXT_FROM_CURRENT (&ctx); +#else MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info); +#endif + /* + * FIXME: This is needed because of the LMF stuff which doesn't exist on ia64. + * Probably the whole mono_find_jit_info () stuff needs to be fixed so this isn't + * needed even on other platforms. This is also true for s390/s390x. + */ +#if !defined(__ia64__) && !defined(__s390__) && !defined(__s390x__) skip++; +#endif do { ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL); @@ -373,19 +376,26 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, } while (skip >= 0); *method = mono_method_get_object (domain, ji->method, NULL); - *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain); - if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain); - - *file = filename? mono_string_new (domain, filename): NULL; - *column = 0; + location = mono_debug_lookup_source_location (ji->method, *native_offset, domain); + if (location) + *iloffset = location->il_offset; + else + *iloffset = 0; - g_free (filename); + if (need_file_info) { + if (location) { + *file = mono_string_new (domain, location->source_file); + *line = location->row; + *column = location->column; + } else { + *file = NULL; + *line = *column = 0; + } } + mono_debug_free_source_location (location); + return TRUE; } @@ -466,7 +476,7 @@ grow_array (MonoSecurityStack *stack) int i; for (i=0; i < stack->maximum; i++) { gpointer frame = mono_array_get (stack->stack, gpointer, i); - mono_array_set (newstack, gpointer, i, frame); + mono_array_setref (newstack, i, frame); } stack->maximum = newsize; stack->stack = newstack; @@ -494,7 +504,7 @@ callback_get_stack_frames_security_info (MonoDomain *domain, MonoContext *ctx, M if (ss->count == ss->maximum) grow_array (ss); - mono_array_set (ss->stack, gpointer, ss->count++, mono_declsec_create_frame (domain, ji)); + mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (domain, ji)); /* continue down the stack */ return FALSE; @@ -597,7 +607,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina g_assert (ctx != NULL); if (!obj) { MonoException *ex = mono_get_exception_null_reference (); - ex->message = mono_string_new (domain, "Object reference not set to an instance of an object"); + MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object")); obj = (MonoObject *)ex; } @@ -632,7 +642,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina if (!test_only) { MonoContext ctx_cp = *ctx; - if (mono_jit_trace_calls != NULL) + if (mono_trace_is_enabled ()) g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name); if (!mono_handle_exception_internal (&ctx_cp, obj, original_ip, TRUE, &first_filter_idx)) { if (mono_break_on_exc) @@ -741,10 +751,10 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina if (test_only) { if (mono_ex && !initial_trace_ips) { trace_ips = g_list_reverse (trace_ips); - mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class); + MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class)); if (has_dynamic_methods) /* These methods could go away anytime, so compute the stack trace now */ - mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex); + MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); } g_list_free (trace_ips); @@ -752,7 +762,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina mono_gc_enable (); return TRUE; } - if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) + if (mono_trace_is_enabled () && 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); @@ -765,7 +775,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && MONO_CONTEXT_GET_IP (ctx) < ei->try_end && (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) { - if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method)) + if (mono_trace_is_enabled () && 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); @@ -801,10 +811,10 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina } else { if (mono_ex && !initial_trace_ips) { trace_ips = g_list_reverse (trace_ips); - mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class); + MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class)); if (has_dynamic_methods) /* These methods could go away anytime, so compute the stack trace now */ - mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex); + MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); } g_list_free (trace_ips); return FALSE; @@ -953,20 +963,11 @@ print_stack_frame (MonoMethod *method, gint32 native_offset, gint32 il_offset, g FILE *stream = (FILE*)data; if (method) { - char *fname = mono_method_full_name (method, TRUE); - - if (il_offset != -1) { - gchar *source_location = mono_debug_source_location_from_address (method, native_offset, NULL, mono_domain_get ()); - - if (source_location) - fprintf (stream, "in %s (at %s)\n", fname, source_location); - else - fprintf (stream, "in %s [IL 0x%lx]\n", fname, (long)il_offset); - } else - fprintf (stream, "in %s <0x%lx>\n", fname, (long)native_offset); - g_free (fname); + gchar *location = mono_debug_print_stack_frame (method, native_offset, mono_domain_get ()); + fprintf (stream, " %s\n", location); + g_free (location); } else - fprintf (stream, "in <%lx>\n", (long)native_offset); + fprintf (stream, " at <0x%05x>\n", native_offset); return FALSE; } @@ -978,21 +979,27 @@ print_stack_frame (MonoMethod *method, gint32 native_offset, gint32 il_offset, g * information and aborting. */ void -mono_handle_native_sigsegv (void *ctx) +mono_handle_native_sigsegv (int signal, void *ctx) { +#ifndef PLATFORM_WIN32 + struct sigaction sa; +#endif + const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT"; + + /* * A SIGSEGV indicates something went very wrong so we can no longer depend * on anything working. So try to print out lots of diagnostics, starting - * with ones which have a greater change of working. + * with ones which have a greater chance of working. */ fprintf (stderr, "\n" "=================================================================\n" - "Got a SIGSEGV while executing native code. This usually indicates\n" + "Got a %s while executing native code. This usually indicates\n" "a fatal error in the mono runtime or one of the native libraries \n" "used by your application.\n" "=================================================================\n" - "\n"); + "\n", signal_str); fprintf (stderr, "Stacktrace:\n\n"); @@ -1019,6 +1026,17 @@ mono_handle_native_sigsegv (void *ctx) fflush (stderr); #endif +#ifndef PLATFORM_WIN32 + + /* Remove our SIGABRT handler */ + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + + g_assert (sigaction (SIGABRT, &sa, NULL) != -1); + +#endif + abort (); }