#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 <libgc/include/libgc-mono-debugger.h>
#include "mini.h"
#include <unistd.h>
#include <locale.h>
#include <string.h>
-static GPtrArray *thread_array = NULL;
+/*
+ * 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 gpointer main_started_cond;
-static gpointer main_ready_cond;
+#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 MonoMethod *debugger_main_method;
+static MonoCodeManager *debugger_codeman = NULL;
static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
static guint64 debugger_remove_breakpoint (guint64 breakpoint);
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_get_current_thread (void);
+static void debugger_attach (void);
+static void debugger_detach (void);
+static void debugger_initialize (void);
+
+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, 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)
+};
/*
* This is a global data symbol which is read by the debugger.
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_lookup_class,
&debugger_lookup_type,
&debugger_lookup_assembly,
- &debugger_run_finally
-};
-
-typedef struct {
- gpointer end_stack;
- gpointer start_stack;
- gpointer func;
- guint64 tid;
-} MonoDebuggerThread;
-
-typedef struct {
- guint32 size;
- guint32 thread_size;
- gpointer main_function;
- gpointer notification_address;
- MonoDebuggerThread *main_thread;
- guint32 main_tid;
-} MonoDebuggerManager;
-
-MonoDebuggerManager MONO_DEBUGGER__manager = {
- sizeof (MonoDebuggerManager),
- sizeof (MonoDebuggerThread),
- NULL, NULL, NULL, 0
+ &debugger_run_finally,
+ &debugger_get_current_thread,
+ &debugger_attach,
+ &debugger_detach,
+ &debugger_initialize
};
static guint64
retval = mono_compile_method (method);
mono_debugger_unlock ();
- mono_debugger_notification_function (MONO_DEBUGGER_EVENT_METHOD_COMPILED, GPOINTER_TO_UINT (retval), 0);
+ mono_debugger_notification_function (
+ MONO_DEBUGGER_EVENT_METHOD_COMPILED, (guint64) (gsize) retval, 0);
return retval;
}
static guint64
debugger_compile_method (guint64 method_arg)
{
- MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
+ MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
- return GPOINTER_TO_UINT (debugger_compile_method_cb (method));
+ return (guint64) (gsize) debugger_compile_method_cb (method);
}
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))
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)
{
- return GPOINTER_TO_UINT (mono_string_new_wrapper (string_argument));
+ return (guint64) (gsize) mono_string_new_wrapper (string_argument);
}
static guint64
static guint64
debugger_lookup_class (guint64 image_argument, guint64 token_argument)
{
- MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gssize) image_argument);
+ MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
guint32 token = (guint32) token_argument;
MonoClass *klass;
if (klass)
mono_class_init (klass);
- return GPOINTER_TO_UINT (klass);
+ return (guint64) (gsize) klass;
}
static guint64
static guint64
debugger_class_get_static_field_data (guint64 value)
{
- MonoClass *klass = GUINT_TO_POINTER ((gssize) value);
+ MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
- return GPOINTER_TO_UINT (mono_vtable_get_static_field_data (vtable));
+ return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
}
static void
mono_debugger_notification_function (event, data, arg);
}
-static void
-debugger_thread_manager_thread_created (MonoDebuggerThread *thread)
-{
- if (!thread_array)
- thread_array = g_ptr_array_new ();
-
- g_ptr_array_add (thread_array, thread);
-}
-
-static void
-debugger_thread_manager_add_thread (gsize tid, gpointer start_stack, gpointer func)
+static guint64
+debugger_get_current_thread (void)
{
- 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);
+ return (guint64) (gsize) mono_thread_current ();
}
static void
-debugger_thread_manager_start_resume (gsize tid)
+debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
{
+ mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_CREATED,
+ (guint64) (gsize) stack_ptr, thread);
}
static void
-debugger_thread_manager_end_resume (gsize tid)
+debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
{
+ mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_EXITED,
+ (guint64) (gsize) stack_ptr, thread);
}
-extern void GC_push_all_stack (gpointer b, gpointer t);
-
static void
debugger_gc_stop_world (void)
{
- mono_debugger_notification_function (
+ mono_debugger_event (
MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
}
static void
debugger_gc_start_world (void)
{
- mono_debugger_notification_function (
+ mono_debugger_event (
MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
}
-static void
-debugger_gc_push_all_stacks (void)
-{
- int i, tid;
-
- tid = 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);
- }
-}
-
static GCThreadFunctions debugger_thread_vtable = {
NULL,
+ debugger_gc_thread_created,
+ debugger_gc_thread_exited,
+
debugger_gc_stop_world,
- debugger_gc_push_all_stacks,
debugger_gc_start_world
};
static void
-debugger_thread_manager_init (void)
+debugger_init_threads (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
-};
+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;
+ mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
+
+ debugger_init_threads ();
+ GC_mono_debugger_add_all_threads ();
+}
+
+static void
+debugger_detach (void)
+{
+ mono_debugger_event_handler = NULL;
+ mono_debugger_notification_function = NULL;
+ debugger_finalize_threads ();
+}
+
+static void
+debugger_initialize (void)
+{
+}
void
mono_debugger_init (void)
{
- main_started_cond = CreateSemaphore (NULL, 0, 1, NULL);
- main_ready_cond = CreateSemaphore (NULL, 0, 1, NULL);
+ /*
+ * Use mono_code_manager_new_dynamic() to create a new malloc()-based code manager
+ * and intentionally leak the memory on exit.
+ */
+ debugger_codeman = mono_code_manager_new_dynamic ();
+ mono_debugger_notification_function = mono_debugger_create_notification_function (debugger_codeman);
+ 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 ();
+
+ /*
+ * Initialize the thread manager.
+ */
- mono_debugger_notification_function = mono_debugger_create_notification_function
- (&MONO_DEBUGGER__manager.notification_address);
+ mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
+ GetCurrentThreadId (), 0);
}
typedef struct
main_thread_handler (gpointer user_data)
{
MainThreadArgs *main_args = (MainThreadArgs *) user_data;
+ gpointer function;
int retval;
- MONO_DEBUGGER__manager.main_tid = GetCurrentThreadId ();
- MONO_DEBUGGER__manager.main_thread = g_new0 (MonoDebuggerThread, 1);
- MONO_DEBUGGER__manager.main_thread->tid = GetCurrentThreadId ();
- MONO_DEBUGGER__manager.main_thread->start_stack = &main_args;
-
- debugger_thread_manager_thread_created (MONO_DEBUGGER__manager.main_thread);
-
- ReleaseSemaphore (main_started_cond, 1, NULL);
-
- /*
- * Wait until everything is ready.
- */
- WaitForSingleObject (main_ready_cond, INFINITE);
+ 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;
}
{
MainThreadArgs main_args;
MonoImage *image;
+ MonoMethod *main;
/*
* 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);
-
- /*
- * Start the main thread and wait until it's ready.
- */
-
- 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);
- WaitForSingleObject (main_started_cond, INFINITE);
-
- /*
- * Initialize the thread manager.
- */
-
- mono_debugger_event_handler = debugger_event_handler;
- mono_install_thread_callbacks (&thread_callbacks);
- debugger_thread_manager_init ();
+ main = mono_get_method (image, mono_image_get_entry_point (image), NULL);
/*
* 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);
-
mono_debugger_unlock ();
/*
- * Signal the main thread that it can execute the managed Main().
+ * Start the main thread and wait until it's ready.
*/
- ReleaseSemaphore (main_ready_cond, 1, NULL);
+
+ main_args.domain = domain;
+ main_args.method = main;
+ main_args.argc = argc;
+ main_args.argv = argv;
+
+#if RUN_IN_SUBTHREAD
+ mono_thread_create (domain, main_thread_handler, &main_args);
+#else
+ main_thread_handler (&main_args);
+#endif
+
+ mono_thread_manage ();
/*
* This will never return.