[runtime] Centralize the processing of MonoTrampInfo structures into the mono_tramp_i...
[mono.git] / mono / mini / debug-debugger.c
index df84401d997dcaba813e16d4e64354c801aad9b1..a103595c0bf72426da06cef43e283fb219b22e1a 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * debug-debugger.c: Hard debugger support (mdb)
+ *
+ * Author:
+ *
+ * Copyright 2006-2010 Novell, Inc.
+ */
+#if MONO_DEBUGGER_SUPPORTED
+
 #include <config.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/metadata/threads.h>
  * configure.in checks whether we're using the included libgc and disables the debugger if not.
  */
 
-#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!"
+#if !defined(USE_INCLUDED_LIBGC)
+#error "Inconsistency detected: #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
 #endif
 
 static guint64 debugger_compile_method (guint64 method_arg);
@@ -32,11 +39,11 @@ static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
 static guint64 debugger_class_get_static_field_data (guint64 klass);
 
 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_init_code_buffer (void);
 
+static void debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg);
+
 static guint64 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
                                       G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument);
 static gint64 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
@@ -50,20 +57,26 @@ static guint64 debugger_register_class_init_callback (guint64 image_argument, gu
 static void debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy);
 static guint64 debugger_get_method_signature (guint64 argument1, G_GNUC_UNUSED guint64 argument2);
 
+static guint64 debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2);
+
 #define EXECUTABLE_CODE_BUFFER_SIZE 4096
 static guint8 *debugger_executable_code_buffer = NULL;
 
+static GCThreadFunctions debugger_thread_vtable;
+
+static guint32 debugger_thread_abort_signal = 0;
+
 static MonoDebuggerMetadataInfo debugger_metadata_info = {
        sizeof (MonoDebuggerMetadataInfo),
        sizeof (MonoDefaults),
        &mono_defaults,
-       sizeof (MonoType),
+       MONO_SIZEOF_TYPE,
        sizeof (MonoArrayType),
        sizeof (MonoClass),
-       sizeof (MonoThread),
-       G_STRUCT_OFFSET (MonoThread, tid),
-       G_STRUCT_OFFSET (MonoThread, stack_ptr),
-       G_STRUCT_OFFSET (MonoThread, end_stack),
+       sizeof (MonoInternalThread),
+       G_STRUCT_OFFSET (MonoInternalThread, tid),
+       G_STRUCT_OFFSET (MonoInternalThread, stack_ptr),
+       G_STRUCT_OFFSET (MonoInternalThread, end_stack),
        G_STRUCT_OFFSET (MonoClass, image),
        G_STRUCT_OFFSET (MonoClass, instance_size),
        G_STRUCT_OFFSET (MonoClass, parent),
@@ -111,24 +124,19 @@ static MonoDebuggerMetadataInfo debugger_metadata_info = {
 
 extern void MONO_DEBUGGER__notification_function (guint64 command, guint64 data, guint64 data2);
 
-/*
- * Backwards compatibility:
- * The debugger expects a pointer to the function in `MONO_DEBUGGER__debugger_info'.
- */
-static void (*__obsolete_notification_func_ptr) (guint64 command, guint64 data, guint64 data2) =
-       &MONO_DEBUGGER__notification_function;
-
 /*
  * This is a global data symbol which is read by the debugger.
  */
 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
        MONO_DEBUGGER_MAGIC,
-       MONO_DEBUGGER_VERSION,
+       MONO_DEBUGGER_MAJOR_VERSION,
+       MONO_DEBUGGER_MINOR_VERSION,
+       0, /* runtime_flags */
        sizeof (MonoDebuggerInfo),
        sizeof (MonoSymbolTable),
        MONO_TRAMPOLINE_NUM,
        mono_trampoline_code,
-       &__obsolete_notification_func_ptr,
+       &MONO_DEBUGGER__notification_function,
        &mono_symbol_table,
        &debugger_metadata_info,
        &mono_debug_debugger_version,
@@ -139,10 +147,7 @@ MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
        &mono_debugger_runtime_invoke,
        &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,
@@ -164,9 +169,28 @@ MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
        MONO_BREAKPOINT_ARRAY_SIZE,
 
        debugger_get_method_signature,
-       debugger_init_code_buffer
+       debugger_init_code_buffer,
+
+       &gc_thread_vtable,
+       &debugger_thread_vtable,
+
+       &mono_debugger_event_handler,
+       debugger_event_handler,
+
+       &_mono_debug_using_mono_debugger,
+       (gint32*)&_mono_debugger_interruption_request,
+
+       &debugger_abort_runtime_invoke,
+
+       &debugger_thread_abort_signal
 };
 
+static guint64
+debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2)
+{
+       return mono_debugger_abort_runtime_invoke ();
+}
+
 static guint64
 debugger_compile_method (guint64 method_arg)
 {
@@ -239,6 +263,7 @@ debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
                return -1;
 
        mono_class_init (klass);
+       mono_class_setup_methods (klass);
        return (gint64) (gssize) klass;
 }
 
@@ -304,7 +329,7 @@ debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint6
        mono_debugger_lock ();
 
        klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
-       if (!klass) {
+       if (!klass || !klass->inited || !klass->methods) {
                mono_debugger_unlock ();
                return 0;
        }
@@ -336,7 +361,7 @@ debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint6
                        method = nm;
                }
 
-               info = mono_debugger_insert_method_breakpoint (method, index);
+               info = mono_debug_lookup_method_addresses (method);
                mono_debugger_unlock ();
                return (guint64) (gsize) info;
        }
@@ -350,6 +375,7 @@ debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy)
 {
        mono_debugger_lock ();
        mono_debugger_remove_method_breakpoint (index);
+       mono_debugger_remove_class_init_callback (index);
        mono_debugger_unlock ();
 }
 
@@ -432,28 +458,15 @@ debugger_init_threads (void)
        gc_thread_vtable = &debugger_thread_vtable;
 }
 
+#if 0
+
 static void
 debugger_finalize_threads (void)
 {
        gc_thread_vtable = NULL;
 }
 
-static void
-debugger_attach (void)
-{
-       mono_debugger_init ();
-
-       mono_debugger_event_handler = debugger_event_handler;
-       debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
-       debugger_init_threads ();
-}
-
-static void
-debugger_detach (void)
-{
-       mono_debugger_event_handler = NULL;
-       debugger_finalize_threads ();
-}
+#endif
 
 static guint64
 debugger_init_code_buffer (void)
@@ -464,18 +477,49 @@ debugger_init_code_buffer (void)
 }
 
 extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
+extern long MONO_DEBUGGER__using_debugger;
 
 static void
 debugger_initialize (void)
 {
 }
 
+/**
+ * Check whether we're running inside the debugger.
+ *
+ * There seems to be a bug in some versions of glibc which causes _dl_debug_state() being called with
+ * RT_CONSISTENT before relocations are done.
+ *
+ * If that happens, the debugger cannot read the `MONO_DEBUGGER__debugger_info' structure at the time
+ * the `libmono.so' library is loaded.
+ *
+ * As a workaround, the `mdb_debug_info' now also contains a global variable called
+ * `MONO_DEBUGGER__using_debugger' which may we set to 1 by the debugger to tell us that we're running
+ * inside the debugger.
+ *
+ * mini_init() checks this and calls mini_debugger_init() if necessary.
+ *
+ */
+
+gboolean
+mini_debug_running_inside_mdb (void)
+{
+       return MONO_DEBUGGER__using_debugger || mono_debug_using_mono_debugger ();
+}
+
 void
-mono_debugger_init (void)
+mini_debugger_init (void)
 {
+       if (mono_debugger_event_handler) {
+               g_warning (G_STRLOC ": duplicate call to mono_debugger_init()!");
+               return;
+       }
+
        debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
        mono_debugger_event_handler = debugger_event_handler;
 
+       debugger_thread_abort_signal = mono_thread_get_abort_signal ();
+
        /*
         * Use an indirect call so gcc can't optimize it away.
         */
@@ -494,6 +538,13 @@ mono_debugger_init (void)
                             (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
 }
 
+void
+mini_debugger_set_attach_ok (void)
+{
+       debugger_thread_abort_signal = mono_thread_get_abort_signal ();
+       MONO_DEBUGGER__debugger_info.runtime_flags |= DEBUGGER_RUNTIME_FLAGS_ATTACH_OK;
+}
+
 typedef struct 
 {
        MonoDomain *domain;
@@ -517,7 +568,7 @@ main_thread_handler (gpointer user_data)
 }
 
 int
-mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
+mini_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
 {
        MainThreadArgs main_args;
        MonoImage *image;
@@ -560,3 +611,4 @@ mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char *
 
        return 0;
 }
+#endif /* MONO_DEBUGGER_SUPPORTED */