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 "debug-mini.h"
10 #include <libgc/include/libgc-mono-debugger.h>
17 * This file is only compiled on platforms where the debugger is supported - see the conditional
18 * definition of `debugger_sources' in Makefile.am.
20 * configure.in checks whether we're using the included libgc and disables the debugger if not.
23 #if !defined(MONO_DEBUGGER_SUPPORTED)
24 #error "Some clown tried to compile debug-debugger.c on an unsupported platform - fix Makefile.am!"
25 #elif !defined(USE_INCLUDED_LIBGC)
26 #error "Some clown #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
29 static guint64 debugger_compile_method (guint64 method_arg);
30 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
31 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
32 static guint64 debugger_class_get_static_field_data (guint64 klass);
34 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
35 static void debugger_initialize (void);
36 static guint64 debugger_init_code_buffer (void);
38 static void debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg);
40 static guint64 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
41 G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument);
42 static gint64 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
43 G_GNUC_UNUSED guint64 dummy2, gchar *full_name);
44 static guint64 debugger_insert_method_breakpoint (guint64 method_argument, guint64 index);
45 static guint64 debugger_insert_source_breakpoint (guint64 image_argument, guint64 token,
46 guint64 index, const gchar *class_name);
47 static void debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy);
48 static guint64 debugger_register_class_init_callback (guint64 image_argument, guint64 token,
49 guint64 index, const gchar *class_name);
50 static void debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy);
51 static guint64 debugger_get_method_signature (guint64 argument1, G_GNUC_UNUSED guint64 argument2);
53 #define EXECUTABLE_CODE_BUFFER_SIZE 4096
54 static guint8 *debugger_executable_code_buffer = NULL;
56 static GCThreadFunctions debugger_thread_vtable;
58 static MonoDebuggerMetadataInfo debugger_metadata_info = {
59 sizeof (MonoDebuggerMetadataInfo),
60 sizeof (MonoDefaults),
63 sizeof (MonoArrayType),
66 G_STRUCT_OFFSET (MonoThread, tid),
67 G_STRUCT_OFFSET (MonoThread, stack_ptr),
68 G_STRUCT_OFFSET (MonoThread, end_stack),
69 G_STRUCT_OFFSET (MonoClass, image),
70 G_STRUCT_OFFSET (MonoClass, instance_size),
71 G_STRUCT_OFFSET (MonoClass, parent),
72 G_STRUCT_OFFSET (MonoClass, type_token),
73 G_STRUCT_OFFSET (MonoClass, fields),
74 G_STRUCT_OFFSET (MonoClass, methods),
75 G_STRUCT_OFFSET (MonoClass, method.count),
76 G_STRUCT_OFFSET (MonoClass, this_arg),
77 G_STRUCT_OFFSET (MonoClass, byval_arg),
78 G_STRUCT_OFFSET (MonoClass, generic_class),
79 G_STRUCT_OFFSET (MonoClass, generic_container),
80 G_STRUCT_OFFSET (MonoClass, vtable),
81 sizeof (MonoClassField),
82 G_STRUCT_OFFSET (MonoClassField, type),
83 G_STRUCT_OFFSET (MonoClassField, offset),
84 G_STRUCT_OFFSET (MonoDefaults, corlib),
85 G_STRUCT_OFFSET (MonoDefaults, object_class),
86 G_STRUCT_OFFSET (MonoDefaults, byte_class),
87 G_STRUCT_OFFSET (MonoDefaults, void_class),
88 G_STRUCT_OFFSET (MonoDefaults, boolean_class),
89 G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
90 G_STRUCT_OFFSET (MonoDefaults, int16_class),
91 G_STRUCT_OFFSET (MonoDefaults, uint16_class),
92 G_STRUCT_OFFSET (MonoDefaults, int32_class),
93 G_STRUCT_OFFSET (MonoDefaults, uint32_class),
94 G_STRUCT_OFFSET (MonoDefaults, int_class),
95 G_STRUCT_OFFSET (MonoDefaults, uint_class),
96 G_STRUCT_OFFSET (MonoDefaults, int64_class),
97 G_STRUCT_OFFSET (MonoDefaults, uint64_class),
98 G_STRUCT_OFFSET (MonoDefaults, single_class),
99 G_STRUCT_OFFSET (MonoDefaults, double_class),
100 G_STRUCT_OFFSET (MonoDefaults, char_class),
101 G_STRUCT_OFFSET (MonoDefaults, string_class),
102 G_STRUCT_OFFSET (MonoDefaults, enum_class),
103 G_STRUCT_OFFSET (MonoDefaults, array_class),
104 G_STRUCT_OFFSET (MonoDefaults, delegate_class),
105 G_STRUCT_OFFSET (MonoDefaults, exception_class),
106 G_STRUCT_OFFSET (MonoMethod, klass),
107 G_STRUCT_OFFSET (MonoMethod, token),
108 G_STRUCT_OFFSET (MonoMethod, name) + sizeof (void *),
109 G_STRUCT_OFFSET (MonoMethodInflated, declaring),
110 G_STRUCT_OFFSET (MonoVTable, klass),
111 G_STRUCT_OFFSET (MonoVTable, vtable)
114 extern void MONO_DEBUGGER__notification_function (guint64 command, guint64 data, guint64 data2);
117 * This is a global data symbol which is read by the debugger.
119 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
121 MONO_DEBUGGER_MAJOR_VERSION,
122 MONO_DEBUGGER_MINOR_VERSION,
124 sizeof (MonoDebuggerInfo),
125 sizeof (MonoSymbolTable),
127 mono_trampoline_code,
128 &MONO_DEBUGGER__notification_function,
130 &debugger_metadata_info,
131 &mono_debug_debugger_version,
133 &debugger_compile_method,
134 &debugger_get_virtual_method,
135 &debugger_get_boxed_object,
136 &mono_debugger_runtime_invoke,
137 &debugger_class_get_static_field_data,
138 &debugger_run_finally,
139 &debugger_initialize,
141 &debugger_create_string,
142 &debugger_lookup_class,
144 &debugger_insert_method_breakpoint,
145 &debugger_insert_source_breakpoint,
146 &debugger_remove_breakpoint,
148 &debugger_register_class_init_callback,
149 &debugger_remove_class_init_callback,
151 &mono_debugger_thread_table,
153 &debugger_executable_code_buffer,
154 mono_breakpoint_info,
155 mono_breakpoint_info_index,
157 EXECUTABLE_CODE_BUFFER_SIZE,
158 MONO_BREAKPOINT_ARRAY_SIZE,
160 debugger_get_method_signature,
161 debugger_init_code_buffer,
164 &debugger_thread_vtable,
166 &mono_debugger_event_handler,
167 debugger_event_handler,
169 &_mono_debug_using_mono_debugger,
170 (gint32*)&_mono_debugger_interruption_request
174 debugger_compile_method (guint64 method_arg)
176 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
179 mono_debugger_lock ();
180 addr = mono_compile_method (method);
181 mono_debugger_unlock ();
183 return (guint64) (gsize) addr;
187 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
189 MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
190 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
192 if (mono_class_is_valuetype (mono_method_get_class (method)))
195 return (guint64) (gsize) mono_object_get_virtual_method (object, method);
199 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
201 static MonoObject *last_boxed_object = NULL;
202 MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
203 gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
206 if (!mono_class_is_valuetype (klass))
209 boxed = mono_value_box (mono_domain_get (), klass, val);
210 last_boxed_object = boxed; // Protect the object from being garbage collected
212 return (guint64) (gsize) boxed;
216 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
217 G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument)
219 return (guint64) (gsize) mono_string_new_wrapper (string_argument);
223 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
224 G_GNUC_UNUSED guint64 dummy2, gchar *full_name)
226 MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
227 gchar *name_space, *name, *pos;
230 pos = strrchr (full_name, '.');
232 name_space = full_name;
240 klass = mono_class_from_name (image, name_space ? name_space : "", name);
244 mono_class_init (klass);
245 mono_class_setup_methods (klass);
246 return (gint64) (gssize) klass;
250 debugger_run_finally (guint64 context_argument, G_GNUC_UNUSED guint64 dummy)
252 mono_debugger_run_finally (GUINT_TO_POINTER ((gsize)context_argument));
257 debugger_class_get_static_field_data (guint64 value)
259 MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
260 MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
261 return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
265 debugger_insert_method_breakpoint (guint64 method_argument, guint64 index)
267 MonoMethod *method = GUINT_TO_POINTER ((gsize) method_argument);
268 MonoDebugMethodAddressList *info;
270 mono_debugger_lock ();
272 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
273 const char *name = method->name;
274 MonoMethod *nm = NULL;
276 if (method->klass->parent == mono_defaults.multicastdelegate_class) {
277 if (*name == 'I' && (strcmp (name, "Invoke") == 0))
278 nm = mono_marshal_get_delegate_invoke (method, NULL);
279 else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
280 nm = mono_marshal_get_delegate_begin_invoke (method);
281 else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
282 nm = mono_marshal_get_delegate_end_invoke (method);
286 mono_debugger_unlock ();
293 info = mono_debugger_insert_method_breakpoint (method, index);
295 mono_debugger_unlock ();
296 return (guint64) (gsize) info;
300 debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint64 index,
301 const gchar *class_name)
303 MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
304 MonoDebugMethodAddressList *info;
308 mono_debugger_lock ();
310 klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
311 if (!klass || !klass->inited || !klass->methods) {
312 mono_debugger_unlock ();
316 for (i = 0; i < klass->method.count; i++) {
317 MonoMethod *method = klass->methods [i];
319 if (method->token != token)
322 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
323 const char *name = method->name;
324 MonoMethod *nm = NULL;
326 if (method->klass->parent == mono_defaults.multicastdelegate_class) {
327 if (*name == 'I' && (strcmp (name, "Invoke") == 0))
328 nm = mono_marshal_get_delegate_invoke (method, NULL);
329 else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
330 nm = mono_marshal_get_delegate_begin_invoke (method);
331 else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
332 nm = mono_marshal_get_delegate_end_invoke (method);
336 mono_debugger_unlock ();
343 info = mono_debugger_insert_method_breakpoint (method, index);
344 mono_debugger_unlock ();
345 return (guint64) (gsize) info;
348 mono_debugger_unlock ();
353 debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy)
355 mono_debugger_lock ();
356 mono_debugger_remove_method_breakpoint (index);
357 mono_debugger_remove_class_init_callback (index);
358 mono_debugger_unlock ();
362 debugger_register_class_init_callback (guint64 image_argument, guint64 token, guint64 index,
363 const gchar *class_name)
365 MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
368 mono_debugger_lock ();
369 klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
370 mono_debugger_unlock ();
371 return (guint64) (gsize) klass;
375 debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy)
377 mono_debugger_lock ();
378 mono_debugger_remove_class_init_callback (index);
379 mono_debugger_unlock ();
383 debugger_get_method_signature (guint64 method_arg, G_GNUC_UNUSED guint64 dummy)
385 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
386 MonoMethodSignature *sig;
388 sig = mono_method_signature (method);
389 return (guint64) (gsize) sig;
393 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
395 MONO_DEBUGGER__notification_function (event, data, arg);
399 debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
401 mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_CREATED,
402 (guint64) (gsize) stack_ptr, thread);
406 debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
408 mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_EXITED,
409 (guint64) (gsize) stack_ptr, thread);
413 debugger_gc_stop_world (void)
415 mono_debugger_event (MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
419 debugger_gc_start_world (void)
421 mono_debugger_event (MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
424 static GCThreadFunctions debugger_thread_vtable = {
427 debugger_gc_thread_created,
428 debugger_gc_thread_exited,
430 debugger_gc_stop_world,
431 debugger_gc_start_world
435 debugger_init_threads (void)
437 gc_thread_vtable = &debugger_thread_vtable;
443 debugger_finalize_threads (void)
445 gc_thread_vtable = NULL;
451 debugger_init_code_buffer (void)
453 if (!debugger_executable_code_buffer)
454 debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
455 return (guint64) (gsize) debugger_executable_code_buffer;
458 extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
461 debugger_initialize (void)
466 mono_debugger_init (void)
468 debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
469 mono_debugger_event_handler = debugger_event_handler;
472 * Use an indirect call so gcc can't optimize it away.
474 MONO_DEBUGGER__debugger_info.initialize ();
476 debugger_init_threads ();
479 * Initialize the thread manager.
481 * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
482 * linker from removing the .mdb_debug_info section.
485 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
486 (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
493 } DebuggerThreadArgs;
504 main_thread_handler (gpointer user_data)
506 MainThreadArgs *main_args = (MainThreadArgs *) user_data;
508 return mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
512 mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
514 MainThreadArgs main_args;
516 MonoMethod *main_method;
519 * Get and compile the main function.
522 image = mono_assembly_get_image (assembly);
523 main_method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
526 * Initialize managed code.
528 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE,
529 (guint64) (gssize) main_method, 0);
532 * Start the main thread and wait until it's ready.
535 main_args.domain = domain;
536 main_args.method = main_method;
537 main_args.argc = argc;
538 main_args.argv = argv;
541 mono_thread_create (domain, main_thread_handler, &main_args);
543 main_thread_handler (&main_args);
546 mono_thread_manage ();
549 * This will never return.
551 mono_debugger_event (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);