2009-10-24 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-exceptions.c
index b1dec707197a2a036b46a61465c24eacef42260f..3f6f884fbabb9c2f77a0bdee800a78be5d0032ef 100644 (file)
@@ -219,7 +219,7 @@ mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *re
        if (ji == (gpointer)-1)
                return ji;
 
-       if (managed2 || ji->method->wrapper_type) {
+       if (managed2 || (ji && ji->method->wrapper_type)) {
                const char *real_ip, *start;
                gint32 offset;
 
@@ -307,15 +307,21 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
                class = generic_info;
        }
 
-       if (class->generic_class || class->generic_container)
-               context.class_inst = mini_class_get_context (class)->class_inst;
-
        g_assert (!ji->method->klass->generic_container);
        if (ji->method->klass->generic_class)
                method_container_class = ji->method->klass->generic_class->container_class;
        else
                method_container_class = ji->method->klass;
 
+       /* class might refer to a subclass of ji->method's class */
+       while (class->generic_class && class->generic_class->container_class != method_container_class) {
+               class = class->parent;
+               g_assert (class);
+       }
+
+       if (class->generic_class || class->generic_container)
+               context.class_inst = mini_class_get_context (class)->class_inst;
+
        if (class->generic_class)
                g_assert (mono_class_has_parent_and_ignore_generics (class->generic_class->container_class, method_container_class));
        else
@@ -329,7 +335,7 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
 {
        MonoGenericContext context;
        MonoMethod *method;
-
+       
        if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
                return ji->method;
        context = get_generic_context_from_stack_frame (ji, generic_info);
@@ -620,7 +626,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
 
        actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ji_ctx));
 
-       *method = mono_method_get_object (domain, actual_method, NULL);
+       mono_gc_wbarrier_generic_store (method, (MonoObject*) mono_method_get_object (domain, actual_method, NULL));
 
        location = mono_debug_lookup_source_location (ji->method, *native_offset, domain);
        if (location)
@@ -630,7 +636,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
 
        if (need_file_info) {
                if (location) {
-                       *file = mono_string_new (domain, location->source_file);
+                       mono_gc_wbarrier_generic_store (file, (MonoObject*) mono_string_new (domain, location->source_file));
                        *line = location->row;
                        *column = location->column;
                } else {
@@ -845,6 +851,44 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex
        return catch_class;
 }
 
+/*
+ * mini_jit_info_table_find:
+ *
+ *   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)
+{
+       MonoJitInfo *ji;
+       MonoInternalThread *t = mono_thread_internal_current ();
+       GSList *l;
+
+       if (out_domain)
+               *out_domain = NULL;
+
+       ji = mono_jit_info_table_find (domain, addr);
+       if (ji) {
+               if (out_domain)
+                       *out_domain = domain;
+               return ji;
+       }
+
+       for (l = t->appdomain_refs; l; l = l->next) {
+               if (l->data != domain) {
+                       ji = mono_jit_info_table_find ((MonoDomain*)l->data, addr);
+                       if (ji) {
+                               if (out_domain)
+                                       *out_domain = (MonoDomain*)l->data;
+                               return ji;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
 /**
  * mono_handle_exception_internal:
  * @ctx: saved processor state
@@ -1082,6 +1126,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina
                                                        mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
                                                        mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), obj);
                                                        mono_perfcounters->exceptions_finallys++;
+                                                       *(mono_get_lmf_addr ()) = lmf;
                                                        call_filter (ctx, ei->handler_start);
                                                }
                                                
@@ -1520,8 +1565,6 @@ mono_handle_native_sigsegv (int signal, void *ctx)
                int res;
                int stdout_pipe [2] = { -1, -1 };
                pid_t pid;
-               const char *argv [16];
-               char buf1 [128];
                int status;
                char buffer [1024];
 
@@ -1533,7 +1576,8 @@ mono_handle_native_sigsegv (int signal, void *ctx)
                 * glibc fork acquires some locks, so if the crash happened inside malloc/free,
                 * it will deadlock. Call the syscall directly instead.
                 */
-               pid = syscall (SYS_fork);
+               pid = mono_runtime_syscall_fork ();
+
                if (pid == 0) {
                        close (stdout_pipe [0]);
                        dup2 (stdout_pipe [1], STDOUT_FILENO);
@@ -1541,23 +1585,9 @@ mono_handle_native_sigsegv (int signal, void *ctx)
                        for (i = getdtablesize () - 1; i >= 3; i--)
                                close (i);
 
-                       argv [0] = g_find_program_in_path ("gdb");
-                       if (argv [0] == NULL) {
+                       if (!mono_gdb_render_native_backtraces ())
                                close (STDOUT_FILENO);
-                               exit (1);
-                       }
 
-                       argv [1] = "-ex";
-                       sprintf (buf1, "attach %ld", (long)getpid ());
-                       argv [2] = buf1;
-                       argv [3] = "--ex";
-                       argv [4] = "info threads";
-                       argv [5] = "--ex";
-                       argv [6] = "thread apply all bt";
-                       argv [7] = "--batch";
-                       argv [8] = 0;
-
-                       execv (argv [0], (char**)argv);
                        exit (1);
                }
 
@@ -1616,7 +1646,7 @@ mono_handle_native_sigsegv (int signal, void *ctx)
 void
 mono_print_thread_dump (void *sigctx)
 {
-       MonoThread *thread = mono_thread_current ();
+       MonoInternalThread *thread = mono_thread_internal_current ();
 #if defined(__i386__) || defined(__x86_64__)
        MonoContext ctx;
 #endif
@@ -1652,7 +1682,7 @@ mono_print_thread_dump (void *sigctx)
        printf ("\t<Stack traces in thread dumps not supported on this platform>\n");
 #endif
 
-       fprintf (stdout, text->str);
+       fprintf (stdout, "%s", text->str);
        g_string_free (text, TRUE);
        fflush (stdout);
 }