2003-01-07 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / jit / debug.c
index 1edeae0fc3990f0d06cd429a4a113f3481dd6926..b1eb7a07699b6b7b0739c16fe4c3976c6b8e176b 100644 (file)
@@ -35,15 +35,23 @@ static void initialize_debugger_support (void);
 
 static MonoDebugHandle *mono_debug_handle = NULL;
 static gconstpointer debugger_notification_address = NULL;
+#ifndef PLATFORM_WIN32
 static pthread_cond_t debugger_thread_cond = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t debugger_thread_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_cond_t debugger_finished_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t debugger_finished_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 static pthread_cond_t debugger_start_cond = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t debugger_start_mutex = PTHREAD_MUTEX_INITIALIZER;
+static gboolean debugger_signalled = FALSE;
+#endif
+static gboolean must_send_finished = FALSE;
 
+extern void (*mono_debugger_class_init_func) (MonoClass *klass);
 
 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
 static int debugger_update_symbol_file_table (void);
+static gpointer debugger_compile_method (MonoMethod *method);
 
 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
 static void mono_debug_close_assembly (AssemblyDebugInfo* info);
@@ -59,9 +67,10 @@ MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
        &mono_generic_trampoline_code,
        &mono_breakpoint_trampoline_code,
        &debugger_symbol_file_table_generation,
+       &debugger_symbol_file_table_modified,
        &debugger_notification_address,
        &debugger_symbol_file_table,
-       &mono_compile_method,
+       &debugger_compile_method,
        &debugger_insert_breakpoint,
        &debugger_remove_breakpoint,
        &mono_runtime_invoke
@@ -70,24 +79,38 @@ MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
 static void
 mono_debugger_lock (void)
 {
+#ifndef PLATFORM_WIN32
        pthread_mutex_lock (&debugger_thread_mutex);
+#endif
 }
 
 static void
 mono_debugger_unlock (void)
 {
+#ifndef PLATFORM_WIN32
        pthread_mutex_unlock (&debugger_thread_mutex);
+#endif
 }
 
 static void
-mono_debugger_signal (void)
+mono_debugger_signal (gboolean modified)
 {
-       mono_debugger_lock ();
-       if (!debugger_symbol_file_table_modified) {
+#ifndef PLATFORM_WIN32
+       if (modified)
                debugger_symbol_file_table_modified = TRUE;
+       if (!debugger_signalled) {
+               debugger_signalled = TRUE;
                pthread_cond_signal (&debugger_thread_cond);
        }
-       mono_debugger_unlock ();
+#endif
+}
+
+static void
+mono_debugger_wait (void)
+{
+#ifndef PLATFORM_WIN32
+       pthread_cond_wait (&debugger_finished_cond, &debugger_finished_mutex);
+#endif
 }
 
 static void
@@ -176,6 +199,7 @@ mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **ar
                        }
                        break;
                case MONO_DEBUG_FORMAT_MONO:
+               case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
                        debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
                                MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
                        break;
@@ -183,7 +207,8 @@ mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **ar
                        break;
                }
 
-               if (debug->format != MONO_DEBUG_FORMAT_MONO) {
+               if ((debug->format != MONO_DEBUG_FORMAT_MONO) &&
+                   (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER)) {
                        if (!strcmp (arg, "dont_assemble")) {
                                debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
                                continue;
@@ -200,12 +225,6 @@ mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **ar
                                debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
                                continue;
                        }
-               } else {
-                       if (!strcmp (arg, "internal_mono_debugger")) {
-                               debug->flags |= MONO_DEBUG_FLAGS_MONO_DEBUGGER;
-                               initialize_debugger_support ();
-                               continue;
-                       }
                }
 
                message = g_strdup_printf ("Unknown argument `%s'.", arg);
@@ -227,6 +246,11 @@ mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **ar
                        debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
                break;
        case MONO_DEBUG_FORMAT_MONO:
+               mono_debugger_class_init_func = mono_debug_add_type;
+               break;
+       case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
+               mono_debugger_class_init_func = mono_debug_add_type;
+               initialize_debugger_support ();
                break;
        default:
                g_assert_not_reached ();
@@ -285,7 +309,8 @@ mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **ar
        mono_debug_add_type (mono_defaults.serializationinfo_class);
        mono_debug_add_type (mono_defaults.streamingcontext_class);
 
-       g_message (G_STRLOC);
+       debugger_update_symbol_file_table ();
+
        mono_debugger_unlock ();
 
        return debug;
@@ -739,10 +764,11 @@ mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
                        info->ilfile = g_strdup_printf ("%s.il", info->name);
                break;
        case MONO_DEBUG_FORMAT_MONO:
+       case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
                info->filename = replace_suffix (image->name, "dbg");
                if (g_file_test (info->filename, G_FILE_TEST_EXISTS))
                        info->symfile = mono_debug_open_mono_symbol_file (info->image, info->filename, TRUE);
-               else if (debug->flags & MONO_DEBUG_FLAGS_MONO_DEBUGGER)
+               else if (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER)
                        info->symfile = mono_debug_create_mono_symbol_file (info->image);
                debugger_symbol_file_table_generation++;
                break;
@@ -751,7 +777,7 @@ mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
                break;
        }
 
-       if (debug->format != MONO_DEBUG_FORMAT_MONO)
+       if ((debug->format != MONO_DEBUG_FORMAT_MONO) && (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
                debug_load_method_lines (info);
 
        return info;
@@ -773,6 +799,7 @@ mono_debug_write_symbols (MonoDebugHandle *debug)
                mono_debug_write_dwarf2 (debug);
                break;
        case MONO_DEBUG_FORMAT_MONO:
+       case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
                break;
        default:
                g_assert_not_reached ();
@@ -784,8 +811,6 @@ mono_debug_write_symbols (MonoDebugHandle *debug)
 void
 mono_debug_make_symbols (void)
 {
-       release_symbol_file_table ();
-
        if (!mono_debug_handle || !mono_debug_handle->dirty)
                return;
        
@@ -797,6 +822,7 @@ mono_debug_make_symbols (void)
                mono_debug_write_dwarf2 (mono_debug_handle);
                break;
        case MONO_DEBUG_FORMAT_MONO:
+       case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
                debugger_update_symbol_file_table ();
                break;
        default:
@@ -811,6 +837,7 @@ mono_debug_close_assembly (AssemblyDebugInfo* info)
 {
        switch (info->format) {
        case MONO_DEBUG_FORMAT_MONO:
+       case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
                if (info->symfile != NULL)
                        mono_debug_close_mono_symbol_file (info->symfile);
                break;
@@ -958,13 +985,14 @@ mono_debug_add_type (MonoClass *klass)
        info = mono_debug_get_image (mono_debug_handle, klass->image);
        g_assert (info);
 
-       if (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO)
+       if ((mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO) &&
+           (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
                return;
 
        if (info->symfile) {
                mono_debugger_lock ();
                mono_debug_symfile_add_type (info->symfile, klass);
-               mono_debugger_signal ();
+               mono_debugger_signal (TRUE);
                mono_debugger_unlock ();
        }
 }
@@ -1083,7 +1111,7 @@ mono_debug_add_method (MonoFlowGraph *cfg)
        }
 
        debug_generate_method_lines (info, minfo, cfg);
-       if (info->format == MONO_DEBUG_FORMAT_MONO)
+       if ((info->format == MONO_DEBUG_FORMAT_MONO) || (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER))
                debug_update_il_offsets (info, minfo, cfg);
 
        if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
@@ -1134,7 +1162,7 @@ mono_debug_add_method (MonoFlowGraph *cfg)
 
        if (info->symfile) {
                mono_debug_symfile_add_method (info->symfile, method);
-               mono_debugger_signal ();
+               mono_debugger_signal (TRUE);
        }
 
        mono_debugger_unlock ();
@@ -1214,7 +1242,9 @@ update_symbol_file_table_count_func (gpointer key, gpointer value, gpointer user
 {
        AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
 
-       if (!info->symfile || (info->format != MONO_DEBUG_FORMAT_MONO))
+       if (!info->symfile)
+               return;
+       if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
                return;
 
        ++ (* (int *) user_data);
@@ -1232,7 +1262,9 @@ update_symbol_file_table_func (gpointer key, gpointer value, gpointer user_data)
        AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
        struct SymfileTableData *data = (struct SymfileTableData *) user_data;
 
-       if (!info->symfile || (info->format != MONO_DEBUG_FORMAT_MONO))
+       if (!info->symfile)
+               return;
+       if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
                return;
 
        data->symfile_table->symfiles [data->index++] = info->symfile;
@@ -1262,6 +1294,7 @@ debugger_update_symbol_file_table (void)
        symfile_table->total_size = size;
        symfile_table->count = count;
        symfile_table->generation = debugger_symbol_file_table_generation;
+       symfile_table->global_symfile = mono_debugger_global_symbol_file;
 
        data.symfile_table = symfile_table;
        data.index = 0;
@@ -1275,10 +1308,9 @@ debugger_update_symbol_file_table (void)
        return TRUE;
 }
 
-extern void (*mono_debugger_class_init_func) (MonoClass *klass);
-
 static gboolean has_mono_debugger_support = FALSE;
 
+#ifndef PLATFORM_WIN32
 /*
  * NOTE: We must not call any functions here which we ever may want to debug !
  */
@@ -1308,9 +1340,6 @@ debugger_thread_func (gpointer ptr)
                /* Wait for an event. */
                pthread_cond_wait (&debugger_thread_cond, &debugger_thread_mutex);
 
-               if (!debugger_symbol_file_table_modified)
-                       continue;
-
                /* Reload the symbol file table if necessary. */
                if (debugger_symbol_file_table_generation > last_generation) {
                        debugger_update_symbol_file_table ();
@@ -1325,33 +1354,49 @@ debugger_thread_func (gpointer ptr)
                 */
                notification_code ();
 
-               /* Clear modified flag. */
+               /* Clear modified and signalled flag. */
                debugger_symbol_file_table_modified = FALSE;
+               debugger_signalled = FALSE;
+
+               if (must_send_finished) {
+                       pthread_mutex_lock (&debugger_finished_mutex);
+                       pthread_cond_signal (&debugger_finished_cond);
+                       must_send_finished = FALSE;
+                       pthread_mutex_unlock (&debugger_finished_mutex);
+               }
        }
 
        return NULL;
 }
+#endif
 
 static void
 initialize_debugger_support ()
 {
        guint8 *buf, *ptr;
+#ifndef PLATFORM_WIN32
        pthread_t thread;
        int ret;
+#endif
 
        if (has_mono_debugger_support)
                return;
        has_mono_debugger_support = TRUE;
 
-       mono_debugger_class_init_func = mono_debug_add_type;
-
        ptr = buf = g_malloc0 (16);
        x86_breakpoint (buf);
        debugger_notification_address = buf;
        x86_ret (buf);
 
+#ifndef PLATFORM_WIN32
        pthread_mutex_lock (&debugger_start_mutex);
 
+       /*
+        * This mutex is only unlocked by the pthread_cond_wait() in
+        * mono_debugger_wait().
+        */
+       pthread_mutex_lock (&debugger_finished_mutex);
+
        ret = pthread_create (&thread, NULL, debugger_thread_func, ptr);
        g_assert (ret == 0);
 
@@ -1360,6 +1405,12 @@ initialize_debugger_support ()
         * debugger attached to it.
         */
        pthread_cond_wait (&debugger_start_cond, &debugger_start_mutex);
+
+       /*
+        * We keep this mutex until mono_debugger_jit_exec().
+        */
+       pthread_mutex_lock (&debugger_thread_mutex);
+#endif
 }
 
 static GPtrArray *breakpoints = NULL;
@@ -1418,6 +1469,18 @@ debugger_remove_breakpoint (guint64 breakpoint)
        return 0;
 }
 
+static gpointer
+debugger_compile_method (MonoMethod *method)
+{
+       gpointer retval;
+
+       mono_debugger_lock ();
+       retval = mono_compile_method (method);
+       mono_debugger_signal (FALSE);
+       mono_debugger_unlock ();
+       return retval;
+}
+
 int
 mono_remove_breakpoint (int breakpoint_id)
 {
@@ -1458,3 +1521,45 @@ mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
 
        return 0;
 }
+
+void
+mono_debugger_trampoline_breakpoint_callback (void)
+{
+       mono_debugger_lock ();
+       must_send_finished = TRUE;
+       mono_debugger_signal (FALSE);
+       mono_debugger_unlock ();
+
+       mono_debugger_wait ();
+}
+
+/*
+ * This is a custom version of mono_jit_exec() which is used when we're being run inside
+ * the Mono Debugger.
+ */
+int 
+mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
+{
+       MonoImage *image = assembly->image;
+       MonoMethod *method;
+       gpointer addr;
+
+       method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
+
+       addr = mono_compile_method (method);
+
+       /*
+        * The mutex has been locked in initialize_debugger_support(); we keep it locked
+        * until we compiled the main method and signalled the debugger.
+        */
+       must_send_finished = TRUE;
+       mono_debugger_signal (TRUE);
+       mono_debugger_unlock ();
+
+       /*
+        * Wait until the debugger has loaded the initial symbol tables.
+        */
+       mono_debugger_wait ();
+
+       return mono_runtime_run_main (method, argc, argv, NULL);
+}