2 #include <mono/io-layer/io-layer.h>
3 #include <mono/metadata/threads.h>
4 #include <mono/metadata/assembly.h>
5 #include <mono/metadata/mono-debug.h>
6 #include <mono/metadata/mono-config.h>
7 #define _IN_THE_MONO_DEBUGGER
8 #include "debug-debugger.h"
9 #include <libgc/include/libgc-mono-debugger.h>
16 * This file is only compiled on platforms where the debugger is supported - see the conditional
17 * definition of `debugger_sources' in Makefile.am.
19 * configure.in checks whether we're using the included libgc and disables the debugger if not.
22 #if !defined(MONO_DEBUGGER_SUPPORTED)
23 #error "Some clown tried to compile debug-debugger.c on an unsupported platform - fix Makefile.am!"
24 #elif !defined(USE_INCLUDED_LIBGC)
25 #error "Some clown #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
28 static MonoCodeManager *debugger_codeman = NULL;
30 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
31 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
32 static guint64 debugger_compile_method (guint64 method_arg);
33 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
34 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
35 static guint64 debugger_create_string (guint64 dummy_argument, const gchar *string_argument);
36 static guint64 debugger_class_get_static_field_data (guint64 klass);
37 static guint64 debugger_lookup_class (guint64 image_argument, guint64 token_arg);
38 static guint64 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument);
39 static guint64 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument);
40 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
41 static guint64 debugger_get_current_thread (void);
42 static void debugger_attach (void);
43 static void debugger_detach (void);
44 static void debugger_initialize (void);
46 static void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
48 static MonoDebuggerMetadataInfo debugger_metadata_info = {
49 sizeof (MonoDebuggerMetadataInfo),
50 sizeof (MonoDefaults),
53 sizeof (MonoArrayType),
56 G_STRUCT_OFFSET (MonoThread, tid),
57 G_STRUCT_OFFSET (MonoThread, stack_ptr),
58 G_STRUCT_OFFSET (MonoThread, end_stack),
59 G_STRUCT_OFFSET (MonoClass, instance_size),
60 G_STRUCT_OFFSET (MonoClass, parent),
61 G_STRUCT_OFFSET (MonoClass, type_token),
62 G_STRUCT_OFFSET (MonoClass, fields),
63 G_STRUCT_OFFSET (MonoClass, methods),
64 G_STRUCT_OFFSET (MonoClass, method.count),
65 G_STRUCT_OFFSET (MonoClass, this_arg),
66 G_STRUCT_OFFSET (MonoClass, byval_arg),
67 G_STRUCT_OFFSET (MonoClass, generic_class),
68 G_STRUCT_OFFSET (MonoClass, generic_container),
69 sizeof (MonoClassField),
70 G_STRUCT_OFFSET (MonoDefaults, corlib),
71 G_STRUCT_OFFSET (MonoDefaults, object_class),
72 G_STRUCT_OFFSET (MonoDefaults, byte_class),
73 G_STRUCT_OFFSET (MonoDefaults, void_class),
74 G_STRUCT_OFFSET (MonoDefaults, boolean_class),
75 G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
76 G_STRUCT_OFFSET (MonoDefaults, int16_class),
77 G_STRUCT_OFFSET (MonoDefaults, uint16_class),
78 G_STRUCT_OFFSET (MonoDefaults, int32_class),
79 G_STRUCT_OFFSET (MonoDefaults, uint32_class),
80 G_STRUCT_OFFSET (MonoDefaults, int_class),
81 G_STRUCT_OFFSET (MonoDefaults, uint_class),
82 G_STRUCT_OFFSET (MonoDefaults, int64_class),
83 G_STRUCT_OFFSET (MonoDefaults, uint64_class),
84 G_STRUCT_OFFSET (MonoDefaults, single_class),
85 G_STRUCT_OFFSET (MonoDefaults, double_class),
86 G_STRUCT_OFFSET (MonoDefaults, char_class),
87 G_STRUCT_OFFSET (MonoDefaults, string_class),
88 G_STRUCT_OFFSET (MonoDefaults, enum_class),
89 G_STRUCT_OFFSET (MonoDefaults, array_class),
90 G_STRUCT_OFFSET (MonoDefaults, delegate_class),
91 G_STRUCT_OFFSET (MonoDefaults, exception_class)
95 * This is a global data symbol which is read by the debugger.
97 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
99 MONO_DEBUGGER_VERSION,
100 sizeof (MonoDebuggerInfo),
101 sizeof (MonoSymbolTable),
103 &mono_debugger_notification_function,
104 mono_trampoline_code,
106 &debugger_metadata_info,
107 &debugger_compile_method,
108 &debugger_get_virtual_method,
109 &debugger_get_boxed_object,
110 &debugger_insert_breakpoint,
111 &debugger_remove_breakpoint,
112 &mono_debugger_runtime_invoke,
113 &debugger_create_string,
114 &debugger_class_get_static_field_data,
115 &debugger_lookup_class,
116 &debugger_lookup_type,
117 &debugger_lookup_assembly,
118 &debugger_run_finally,
119 &debugger_get_current_thread,
126 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
128 MonoMethodDesc *desc;
130 desc = mono_method_desc_new (string_argument, TRUE);
134 return (guint64) mono_debugger_insert_breakpoint_full (desc);
138 debugger_remove_breakpoint (guint64 breakpoint)
140 return mono_debugger_remove_breakpoint (breakpoint);
144 debugger_compile_method_cb (MonoMethod *method)
148 mono_debugger_lock ();
149 retval = mono_compile_method (method);
150 mono_debugger_unlock ();
152 mono_debugger_notification_function (
153 MONO_DEBUGGER_EVENT_METHOD_COMPILED, (guint64) (gsize) retval, 0);
159 debugger_compile_method (guint64 method_arg)
161 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
163 return (guint64) (gsize) debugger_compile_method_cb (method);
167 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
169 MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
170 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
172 if (mono_class_is_valuetype (mono_method_get_class (method)))
175 return (guint64) (gsize) mono_object_get_virtual_method (object, method);
179 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
181 static MonoObject *last_boxed_object = NULL;
182 MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
183 gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
186 if (!mono_class_is_valuetype (klass))
189 boxed = mono_value_box (mono_domain_get (), klass, val);
190 last_boxed_object = boxed; // Protect the object from being garbage collected
192 return (guint64) (gsize) boxed;
196 debugger_create_string (guint64 dummy_argument, const gchar *string_argument)
198 return (guint64) (gsize) mono_string_new_wrapper (string_argument);
202 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument)
206 mono_debugger_lock ();
207 // retval = mono_debugger_lookup_type (string_argument);
209 mono_debugger_unlock ();
214 debugger_lookup_class (guint64 image_argument, guint64 token_argument)
216 MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
217 guint32 token = (guint32) token_argument;
220 klass = mono_class_get (image, token);
222 mono_class_init (klass);
224 return (guint64) (gsize) klass;
228 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument)
232 mono_debugger_lock ();
233 retval = mono_debugger_lookup_assembly (string_argument);
234 mono_debugger_unlock ();
239 debugger_run_finally (guint64 context_argument, guint64 dummy)
241 mono_debugger_run_finally (GUINT_TO_POINTER (context_argument));
246 debugger_class_get_static_field_data (guint64 value)
248 MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
249 MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
250 return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
254 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
256 mono_debugger_notification_function (event, data, arg);
260 debugger_get_current_thread (void)
262 return (guint64) (gsize) mono_thread_current ();
266 debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
268 mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_CREATED,
269 (guint64) (gsize) stack_ptr, thread);
273 debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
275 mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_EXITED,
276 (guint64) (gsize) stack_ptr, thread);
280 debugger_gc_stop_world (void)
282 mono_debugger_event (
283 MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
287 debugger_gc_start_world (void)
289 mono_debugger_event (
290 MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
293 static GCThreadFunctions debugger_thread_vtable = {
296 debugger_gc_thread_created,
297 debugger_gc_thread_exited,
299 debugger_gc_stop_world,
300 debugger_gc_start_world
304 debugger_init_threads (void)
306 gc_thread_vtable = &debugger_thread_vtable;
310 debugger_finalize_threads (void)
312 gc_thread_vtable = NULL;
316 debugger_attach (void)
318 mono_debugger_init ();
320 mono_debugger_event_handler = debugger_event_handler;
321 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
323 debugger_init_threads ();
324 GC_mono_debugger_add_all_threads ();
328 debugger_detach (void)
330 mono_debugger_event_handler = NULL;
331 mono_debugger_notification_function = NULL;
332 debugger_finalize_threads ();
336 debugger_initialize (void)
341 mono_debugger_init (void)
344 * Use mono_code_manager_new_dynamic() to create a new malloc()-based code manager
345 * and intentionally leak the memory on exit.
347 debugger_codeman = mono_code_manager_new_dynamic ();
348 mono_debugger_notification_function = mono_debugger_create_notification_function (debugger_codeman);
349 mono_debugger_event_handler = debugger_event_handler;
352 * Use an indirect call so gcc can't optimize it away.
354 MONO_DEBUGGER__debugger_info.initialize ();
356 debugger_init_threads ();
359 * Initialize the thread manager.
362 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
363 GetCurrentThreadId (), 0);
370 } DebuggerThreadArgs;
381 main_thread_handler (gpointer user_data)
383 MainThreadArgs *main_args = (MainThreadArgs *) user_data;
387 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_REACHED_MAIN,
388 (guint64) (gsize) main_args->method, 0);
390 retval = mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
393 * This will never return.
395 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0,
396 (guint64) (gsize) retval);
402 mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
404 MainThreadArgs main_args;
409 * Get and compile the main function.
412 image = mono_assembly_get_image (assembly);
413 main = mono_get_method (image, mono_image_get_entry_point (image), NULL);
416 * Reload symbol tables.
418 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
419 mono_debugger_unlock ();
422 * Start the main thread and wait until it's ready.
425 main_args.domain = domain;
426 main_args.method = main;
427 main_args.argc = argc;
428 main_args.argv = argv;
431 mono_thread_create (domain, main_thread_handler, &main_args);
433 main_thread_handler (&main_args);
436 mono_thread_manage ();
439 * This will never return.
441 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);