2007-09-30 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mono / mini / debug-debugger.c
index 8c887fc5c85f71845135ff1f89a890a32625d7bc..adcbddf3fb0016f38dfe53c6ab1aa855d73e2a6d 100644 (file)
-#if defined(__i386__) || defined(__x86_64__)
+#include <config.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/mono-debug.h>
+#include <mono/metadata/mono-config.h>
 #define _IN_THE_MONO_DEBUGGER
-#include <mono/metadata/mono-debug-debugger.h>
+#include "debug-debugger.h"
+#include "debug-mini.h"
 #include <libgc/include/libgc-mono-debugger.h>
 #include "mini.h"
 #include <unistd.h>
 #include <locale.h>
 #include <string.h>
 
-#define IO_LAYER(func) (* mono_debugger_io_layer.func)
-
-static GPtrArray *thread_array = NULL;
-
-static gpointer main_started_cond;
-static gpointer main_ready_cond;
+/*
+ * This file is only compiled on platforms where the debugger is supported - see the conditional
+ * definition of `debugger_sources' in Makefile.am.
+ *
+ * configure.in checks whether we're using the included libgc and disables the debugger if not.
+ */
 
-static MonoMethod *debugger_main_method;
+#if !defined(MONO_DEBUGGER_SUPPORTED)
+#error "Some clown tried to compile debug-debugger.c on an unsupported platform - fix Makefile.am!"
+#elif !defined(USE_INCLUDED_LIBGC)
+#error "Some clown #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
+#endif
 
-static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
-static guint64 debugger_remove_breakpoint (guint64 breakpoint);
 static guint64 debugger_compile_method (guint64 method_arg);
 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
-static guint64 debugger_create_string (guint64 dummy_argument, const gchar *string_argument);
 static guint64 debugger_class_get_static_field_data (guint64 klass);
-static guint64 debugger_lookup_class (guint64 image_argument, guint64 token_arg);
-static guint64 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument);
-static guint64 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument);
-static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
 
-void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
+static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
+static void debugger_attach (void);
+static void debugger_detach (void);
+static void debugger_initialize (void);
+
+static guint64 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
+                                      const gchar *string_argument);
+static gint64 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
+                                    gchar *full_name);
+static guint64 debugger_insert_method_breakpoint (guint64 method_argument, guint64 index);
+static void debugger_remove_method_breakpoint (G_GNUC_UNUSED guint64 dummy, guint64 index);
+static void debugger_runtime_class_init (guint64 klass_arg);
+
+static void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
+
+static MonoDebuggerMetadataInfo debugger_metadata_info = {
+       sizeof (MonoDebuggerMetadataInfo),
+       sizeof (MonoDefaults),
+       &mono_defaults,
+       sizeof (MonoType),
+       sizeof (MonoArrayType),
+       sizeof (MonoClass),
+       sizeof (MonoThread),
+       G_STRUCT_OFFSET (MonoThread, tid),
+       G_STRUCT_OFFSET (MonoThread, stack_ptr),
+       G_STRUCT_OFFSET (MonoThread, end_stack),
+       G_STRUCT_OFFSET (MonoClass, image),
+       G_STRUCT_OFFSET (MonoClass, instance_size),
+       G_STRUCT_OFFSET (MonoClass, parent),
+       G_STRUCT_OFFSET (MonoClass, type_token),
+       G_STRUCT_OFFSET (MonoClass, fields),
+       G_STRUCT_OFFSET (MonoClass, methods),
+       G_STRUCT_OFFSET (MonoClass, method.count),
+       G_STRUCT_OFFSET (MonoClass, this_arg),
+       G_STRUCT_OFFSET (MonoClass, byval_arg),
+       G_STRUCT_OFFSET (MonoClass, generic_class),
+       G_STRUCT_OFFSET (MonoClass, generic_container),
+       sizeof (MonoClassField),
+       G_STRUCT_OFFSET (MonoDefaults, corlib),
+       G_STRUCT_OFFSET (MonoDefaults, object_class),
+       G_STRUCT_OFFSET (MonoDefaults, byte_class),
+       G_STRUCT_OFFSET (MonoDefaults, void_class),
+       G_STRUCT_OFFSET (MonoDefaults, boolean_class),
+       G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
+       G_STRUCT_OFFSET (MonoDefaults, int16_class),
+       G_STRUCT_OFFSET (MonoDefaults, uint16_class),
+       G_STRUCT_OFFSET (MonoDefaults, int32_class),
+       G_STRUCT_OFFSET (MonoDefaults, uint32_class),
+       G_STRUCT_OFFSET (MonoDefaults, int_class),
+       G_STRUCT_OFFSET (MonoDefaults, uint_class),
+       G_STRUCT_OFFSET (MonoDefaults, int64_class),
+       G_STRUCT_OFFSET (MonoDefaults, uint64_class),
+       G_STRUCT_OFFSET (MonoDefaults, single_class),
+       G_STRUCT_OFFSET (MonoDefaults, double_class),
+       G_STRUCT_OFFSET (MonoDefaults, char_class),
+       G_STRUCT_OFFSET (MonoDefaults, string_class),
+       G_STRUCT_OFFSET (MonoDefaults, enum_class),
+       G_STRUCT_OFFSET (MonoDefaults, array_class),
+       G_STRUCT_OFFSET (MonoDefaults, delegate_class),
+       G_STRUCT_OFFSET (MonoDefaults, exception_class),
+       G_STRUCT_OFFSET (MonoMethod, klass),
+       G_STRUCT_OFFSET (MonoMethod, token),
+       G_STRUCT_OFFSET (MonoMethod, name) + sizeof (void *),
+       G_STRUCT_OFFSET (MonoMethodInflated, declaring)
+};
 
 /*
  * This is a global data symbol which is read by the debugger.
@@ -43,86 +106,62 @@ MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
        sizeof (MonoDebuggerInfo),
        sizeof (MonoSymbolTable),
        0,
+       &mono_debugger_notification_function,
        mono_trampoline_code,
        &mono_symbol_table,
+       &debugger_metadata_info,
        &debugger_compile_method,
        &debugger_get_virtual_method,
        &debugger_get_boxed_object,
-       &debugger_insert_breakpoint,
-       &debugger_remove_breakpoint,
        &mono_debugger_runtime_invoke,
-       &debugger_create_string,
        &debugger_class_get_static_field_data,
+       &debugger_run_finally,
+       &debugger_attach,
+       &debugger_detach,
+       &debugger_initialize,
+       (void*)&mono_get_lmf_addr,
+
+       &debugger_create_string,
        &debugger_lookup_class,
-       &debugger_lookup_type,
-       &debugger_lookup_assembly,
-       &debugger_run_finally
-};
+       &debugger_insert_method_breakpoint,
+       &debugger_remove_method_breakpoint,
+       &debugger_runtime_class_init,
 
-MonoDebuggerManager MONO_DEBUGGER__manager = {
-       sizeof (MonoDebuggerManager),
-       sizeof (MonoDebuggerThread),
-       NULL, NULL, NULL, 0
+       &mono_debug_debugger_version,
+       &mono_debugger_thread_table
 };
 
 static guint64
-debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
-{
-       MonoMethodDesc *desc;
-
-       desc = mono_method_desc_new (string_argument, TRUE);
-       if (!desc)
-               return 0;
-
-       return (guint64) mono_debugger_insert_breakpoint_full (desc);
-}
-
-static guint64
-debugger_remove_breakpoint (guint64 breakpoint)
-{
-       return mono_debugger_remove_breakpoint (breakpoint);
-}
-
-static gpointer
-debugger_compile_method_cb (MonoMethod *method)
+debugger_compile_method (guint64 method_arg)
 {
-       gpointer retval;
+       MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
+       gpointer addr;
 
        mono_debugger_lock ();
-       retval = mono_compile_method (method);
+       addr = mono_compile_method (method);
        mono_debugger_unlock ();
 
-       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_METHOD_COMPILED, GPOINTER_TO_UINT (retval), 0);
-
-       return retval;
-}
-
-static guint64
-debugger_compile_method (guint64 method_arg)
-{
-       MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
-
-       return GPOINTER_TO_UINT (debugger_compile_method_cb (method));
+       return (guint64) (gsize) addr;
 }
 
 static guint64
 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
 {
-       MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gssize) object_arg);
-       MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
+       MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
+       MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
 
        if (mono_class_is_valuetype (mono_method_get_class (method)))
                return method_arg;
 
-       return GPOINTER_TO_UINT (mono_object_get_virtual_method (object, method));
+       return (guint64) (gsize) mono_object_get_virtual_method (object, method);
 }
 
 static guint64
 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
 {
        static MonoObject *last_boxed_object = NULL;
-       MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gssize) klass_arg);
-       gpointer val = (gpointer) GUINT_TO_POINTER ((gssize) val_arg);
+       MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
+       gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
        MonoObject *boxed;
 
        if (!mono_class_is_valuetype (klass))
@@ -131,65 +170,105 @@ debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
        boxed = mono_value_box (mono_domain_get (), klass, val);
        last_boxed_object = boxed; // Protect the object from being garbage collected
 
-       return GPOINTER_TO_UINT (boxed);
+       return (guint64) (gsize) boxed;
 }
 
 static guint64
-debugger_create_string (guint64 dummy_argument, const gchar *string_argument)
+debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
+                       const gchar *string_argument)
 {
-       return GPOINTER_TO_UINT (mono_string_new_wrapper (string_argument));
+       return (guint64) (gsize) mono_string_new_wrapper (string_argument);
 }
 
-static guint64
-debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument)
+static gint64
+debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
+                      gchar *full_name)
 {
-       guint64 retval;
+       MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
+       gchar *name_space, *name, *pos;
+       MonoClass *klass;
 
-       mono_debugger_lock ();
-       // retval = mono_debugger_lookup_type (string_argument);
-       retval = -1;
-       mono_debugger_unlock ();
-       return retval;
+       pos = strrchr (full_name, '.');
+       if (pos) {
+               name_space = full_name;
+               *pos = 0;
+               name = pos + 1;
+       } else {
+               name = full_name;
+               name_space = NULL;
+       }
+
+       klass = mono_class_from_name (image, name_space ? name_space : "", name);
+       if (!klass)
+               return -1;
+
+       mono_class_init (klass);
+       return (gint64) (gssize) klass;
 }
 
 static guint64
-debugger_lookup_class (guint64 image_argument, guint64 token_argument)
+debugger_run_finally (guint64 context_argument, G_GNUC_UNUSED guint64 dummy)
 {
-       MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gssize) image_argument);
-       guint32 token = (guint32) token_argument;
-       MonoClass *klass;
-
-       klass = mono_class_get (image, token);
-       if (klass)
-               mono_class_init (klass);
+       mono_debugger_run_finally (GUINT_TO_POINTER ((gsize)context_argument));
+       return 0;
+}
 
-       return GPOINTER_TO_UINT (klass);
+static guint64
+debugger_class_get_static_field_data (guint64 value)
+{
+       MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
+       MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
+       return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
 }
 
 static guint64
-debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument)
+debugger_insert_method_breakpoint (guint64 method_argument, guint64 index)
 {
-       gint64 retval;
+       MonoMethod *method = GUINT_TO_POINTER ((gsize) method_argument);
+       MonoDebugMethodAddressList *info;
 
        mono_debugger_lock ();
-       retval = mono_debugger_lookup_assembly (string_argument);
+
+       if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
+               const char *name = method->name;
+               MonoMethod *nm = NULL;
+
+               if (method->klass->parent == mono_defaults.multicastdelegate_class) {
+                       if (*name == 'I' && (strcmp (name, "Invoke") == 0))
+                               nm = mono_marshal_get_delegate_invoke (method);
+                       else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
+                               nm = mono_marshal_get_delegate_begin_invoke (method);
+                       else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
+                               nm = mono_marshal_get_delegate_end_invoke (method);
+               }
+
+               if (!nm) {
+                       mono_debugger_unlock ();
+                       return 0;
+               }
+
+               method = nm;
+       }
+
+       info = mono_debugger_insert_method_breakpoint (method, index);
+
        mono_debugger_unlock ();
-       return retval;
+       return (guint64) (gsize) info;
 }
 
-static guint64
-debugger_run_finally (guint64 context_argument, guint64 dummy)
+static void
+debugger_remove_method_breakpoint (G_GNUC_UNUSED guint64 dummy, guint64 index)
 {
-       mono_debugger_run_finally (GUINT_TO_POINTER (context_argument));
-       return 0;
+       mono_debugger_lock ();
+       mono_debugger_remove_method_breakpoint (index);
+       mono_debugger_unlock ();
 }
 
-static guint64
-debugger_class_get_static_field_data (guint64 value)
+static void
+debugger_runtime_class_init (guint64 klass_arg)
 {
-       MonoClass *klass = GUINT_TO_POINTER ((gssize) value);
-       MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
-       return GPOINTER_TO_UINT (mono_vtable_get_static_field_data (vtable));
+       MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
+       mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
 }
 
 static void
@@ -199,121 +278,101 @@ debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
 }
 
 static void
-debugger_thread_manager_thread_created (MonoDebuggerThread *thread)
+debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
 {
-       if (!thread_array)
-               thread_array = g_ptr_array_new ();
-
-       g_ptr_array_add (thread_array, thread);
+       mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_CREATED,
+                            (guint64) (gsize) stack_ptr, thread);
 }
 
 static void
-debugger_thread_manager_add_thread (gsize tid, gpointer start_stack, gpointer func)
+debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
 {
-       MonoDebuggerThread *thread = g_new0 (MonoDebuggerThread, 1);
-
-       thread->tid = tid;
-       thread->func = func;
-       thread->start_stack = start_stack;
-
-       mono_debugger_notification_function (
-               MONO_DEBUGGER_EVENT_THREAD_CREATED, GPOINTER_TO_UINT (thread), tid);
-
-       debugger_thread_manager_thread_created (thread);
+       mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_EXITED,
+                            (guint64) (gsize) stack_ptr, thread);
 }
 
 static void
-debugger_thread_manager_start_resume (gsize tid)
+debugger_gc_stop_world (void)
 {
+       mono_debugger_event (
+               MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
 }
 
 static void
-debugger_thread_manager_end_resume (gsize tid)
+debugger_gc_start_world (void)
 {
+       mono_debugger_event (
+               MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
 }
 
-static void
-debugger_thread_manager_acquire_global_thread_lock (void)
-{
-       int tid = IO_LAYER (GetCurrentThreadId) ();
+static GCThreadFunctions debugger_thread_vtable = {
+       NULL,
 
-       mono_debugger_notification_function (
-               MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, tid);
-}
+       debugger_gc_thread_created,
+       debugger_gc_thread_exited,
+
+       debugger_gc_stop_world,
+       debugger_gc_start_world
+};
 
 static void
-debugger_thread_manager_release_global_thread_lock (void)
+debugger_init_threads (void)
 {
-       int tid = IO_LAYER (GetCurrentThreadId) ();
-
-       mono_debugger_notification_function (
-               MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, tid);
+       gc_thread_vtable = &debugger_thread_vtable;
 }
 
-extern void GC_push_all_stack (gpointer b, gpointer t);
-
 static void
-debugger_gc_stop_world (void)
+debugger_finalize_threads (void)
 {
-       debugger_thread_manager_acquire_global_thread_lock ();
+       gc_thread_vtable = NULL;
 }
 
 static void
-debugger_gc_start_world (void)
+debugger_attach (void)
 {
-       debugger_thread_manager_release_global_thread_lock ();
+       mono_debugger_init ();
+
+       mono_debugger_event_handler = debugger_event_handler;
+       debugger_init_threads ();
 }
 
 static void
-debugger_gc_push_all_stacks (void)
+debugger_detach (void)
 {
-       int i, tid;
-
-       tid = IO_LAYER (GetCurrentThreadId) ();
-
-       if (!thread_array)
-               return;
-
-       for (i = 0; i < thread_array->len; i++) {
-               MonoDebuggerThread *thread = g_ptr_array_index (thread_array, i);
-               gpointer end_stack = (thread->tid == tid) ? &i : thread->end_stack;
-
-               GC_push_all_stack (end_stack, thread->start_stack);
-       }
+       mono_debugger_event_handler = NULL;
+       mono_debugger_notification_function = NULL;
+       debugger_finalize_threads ();
 }
 
-static GCThreadFunctions debugger_thread_vtable = {
-       NULL,
-
-       debugger_gc_stop_world,
-       debugger_gc_push_all_stacks,
-       debugger_gc_start_world
-};
+extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
 
 static void
-debugger_thread_manager_init (void)
+debugger_initialize (void)
 {
-       if (!thread_array)
-               thread_array = g_ptr_array_new ();
-
-       gc_thread_vtable = &debugger_thread_vtable;
 }
 
-static MonoThreadCallbacks thread_callbacks = {
-       &debugger_compile_method_cb,
-       &debugger_thread_manager_add_thread,
-       &debugger_thread_manager_start_resume,
-       &debugger_thread_manager_end_resume
-};
-
 void
 mono_debugger_init (void)
 {
-       main_started_cond = IO_LAYER (CreateSemaphore) (NULL, 0, 1, NULL);
-       main_ready_cond = IO_LAYER (CreateSemaphore) (NULL, 0, 1, NULL);
+       mono_debugger_notification_function = mono_debugger_create_notification_function ();
+       mono_debugger_event_handler = debugger_event_handler;
+
+       /*
+        * Use an indirect call so gcc can't optimize it away.
+        */
+       MONO_DEBUGGER__debugger_info.initialize ();
+
+       debugger_init_threads ();
 
-       mono_debugger_notification_function = mono_debugger_create_notification_function
-               (&MONO_DEBUGGER__manager.notification_address);
+       /*
+        * Initialize the thread manager.
+        *
+        * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
+        * linker from removing the .mdb_debug_info section.
+        */
+
+       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
+                                            (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
 }
 
 typedef struct 
@@ -336,25 +395,16 @@ main_thread_handler (gpointer user_data)
        MainThreadArgs *main_args = (MainThreadArgs *) user_data;
        int retval;
 
-       MONO_DEBUGGER__manager.main_tid = IO_LAYER (GetCurrentThreadId) ();
-       MONO_DEBUGGER__manager.main_thread = g_new0 (MonoDebuggerThread, 1);
-       MONO_DEBUGGER__manager.main_thread->tid = IO_LAYER (GetCurrentThreadId) ();
-       MONO_DEBUGGER__manager.main_thread->start_stack = &main_args;
-
-       debugger_thread_manager_thread_created (MONO_DEBUGGER__manager.main_thread);
-
-       IO_LAYER (ReleaseSemaphore) (main_started_cond, 1, NULL);
-
-       /*
-        * Wait until everything is ready.
-        */
-       IO_LAYER (WaitForSingleObject) (main_ready_cond, INFINITE, FALSE);
+       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_REACHED_MAIN,
+                                            (guint64) (gsize) main_args->method, 0);
 
        retval = mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
+
        /*
         * This will never return.
         */
-       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0, GPOINTER_TO_UINT (retval));
+       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0,
+                                            (guint64) (gsize) retval);
 
        return retval;
 }
@@ -364,48 +414,37 @@ mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char *
 {
        MainThreadArgs main_args;
        MonoImage *image;
+       MonoMethod *main_method;
 
        /*
         * Get and compile the main function.
         */
 
        image = mono_assembly_get_image (assembly);
-       debugger_main_method = mono_get_method (
-               image, mono_image_get_entry_point (image), NULL);
-       MONO_DEBUGGER__manager.main_function = mono_compile_method (debugger_main_method);
+       main_method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
 
        /*
-        * Start the main thread and wait until it's ready.
+        * Initialize managed code.
         */
-
-       main_args.domain = domain;
-       main_args.method = debugger_main_method;
-       main_args.argc = argc - 2;
-       main_args.argv = argv + 2;
-
-       mono_thread_create (domain, main_thread_handler, &main_args);
-       IO_LAYER (WaitForSingleObject) (main_started_cond, INFINITE, FALSE);
+       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE,
+                                            (guint64) (gssize) main_method, 0);
 
        /*
-        * Initialize the thread manager.
+        * Start the main thread and wait until it's ready.
         */
 
-       mono_debugger_event_handler = debugger_event_handler;
-       mono_install_thread_callbacks (&thread_callbacks);
-       debugger_thread_manager_init ();
-
-       /*
-        * Reload symbol tables.
-        */
-       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
-       mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER, 0, 0);
+       main_args.domain = domain;
+       main_args.method = main_method;
+       main_args.argc = argc;
+       main_args.argv = argv;
 
-       mono_debugger_unlock ();
+#if RUN_IN_SUBTHREAD
+       mono_thread_create (domain, main_thread_handler, &main_args);
+#else
+       main_thread_handler (&main_args);
+#endif
 
-       /*
-        * Signal the main thread that it can execute the managed Main().
-        */
-       IO_LAYER (ReleaseSemaphore) (main_ready_cond, 1, NULL);
+       mono_thread_manage ();
 
        /*
         * This will never return.
@@ -414,28 +453,3 @@ mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char *
 
        return 0;
 }
-
-#else /* defined(__x86__) || defined(__x86_64__) */
-/*
- * We're on an unsupported platform for the debugger.
- */
-#include "mini.h"
-
-void
-mono_debugger_init (void)
-{
-       /*
-        * This method is only called when we're running inside the Mono Debugger, but
-        * since the debugger doesn't work on this platform, this line should never be reached.
-        */
-       g_error ("The Mono Debugger is not supported on this platform.");
-}
-
-int
-mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
-{
-       g_assert_not_reached ();
-       return 0;
-}
-
-#endif