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 guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
29 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
30 static guint64 debugger_compile_method (guint64 method_arg);
31 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
32 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
33 static guint64 debugger_create_string (guint64 dummy_argument, const gchar *string_argument);
34 static guint64 debugger_class_get_static_field_data (guint64 klass);
35 static guint64 debugger_lookup_class (guint64 image_argument, guint64 token_arg);
36 static guint64 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument);
37 static guint64 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument);
38 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
39 static guint64 debugger_get_current_thread (void);
40 static void debugger_attach (void);
41 static void debugger_detach (void);
42 static void debugger_initialize (void);
44 static void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
46 static MonoDebuggerMetadataInfo debugger_metadata_info = {
47 sizeof (MonoDebuggerMetadataInfo),
48 sizeof (MonoDefaults),
51 sizeof (MonoArrayType),
54 G_STRUCT_OFFSET (MonoThread, tid),
55 G_STRUCT_OFFSET (MonoThread, stack_ptr),
56 G_STRUCT_OFFSET (MonoThread, end_stack),
57 G_STRUCT_OFFSET (MonoClass, instance_size),
58 G_STRUCT_OFFSET (MonoClass, parent),
59 G_STRUCT_OFFSET (MonoClass, type_token),
60 G_STRUCT_OFFSET (MonoClass, fields),
61 G_STRUCT_OFFSET (MonoClass, methods),
62 G_STRUCT_OFFSET (MonoClass, method.count),
63 G_STRUCT_OFFSET (MonoClass, this_arg),
64 G_STRUCT_OFFSET (MonoClass, byval_arg),
65 G_STRUCT_OFFSET (MonoClass, generic_class),
66 G_STRUCT_OFFSET (MonoClass, generic_container),
67 sizeof (MonoClassField),
68 G_STRUCT_OFFSET (MonoDefaults, corlib),
69 G_STRUCT_OFFSET (MonoDefaults, object_class),
70 G_STRUCT_OFFSET (MonoDefaults, byte_class),
71 G_STRUCT_OFFSET (MonoDefaults, void_class),
72 G_STRUCT_OFFSET (MonoDefaults, boolean_class),
73 G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
74 G_STRUCT_OFFSET (MonoDefaults, int16_class),
75 G_STRUCT_OFFSET (MonoDefaults, uint16_class),
76 G_STRUCT_OFFSET (MonoDefaults, int32_class),
77 G_STRUCT_OFFSET (MonoDefaults, uint32_class),
78 G_STRUCT_OFFSET (MonoDefaults, int_class),
79 G_STRUCT_OFFSET (MonoDefaults, uint_class),
80 G_STRUCT_OFFSET (MonoDefaults, int64_class),
81 G_STRUCT_OFFSET (MonoDefaults, uint64_class),
82 G_STRUCT_OFFSET (MonoDefaults, single_class),
83 G_STRUCT_OFFSET (MonoDefaults, double_class),
84 G_STRUCT_OFFSET (MonoDefaults, char_class),
85 G_STRUCT_OFFSET (MonoDefaults, string_class),
86 G_STRUCT_OFFSET (MonoDefaults, enum_class),
87 G_STRUCT_OFFSET (MonoDefaults, array_class),
88 G_STRUCT_OFFSET (MonoDefaults, delegate_class),
89 G_STRUCT_OFFSET (MonoDefaults, exception_class)
93 * This is a global data symbol which is read by the debugger.
95 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
97 MONO_DEBUGGER_VERSION,
98 sizeof (MonoDebuggerInfo),
99 sizeof (MonoSymbolTable),
101 &mono_debugger_notification_function,
102 mono_trampoline_code,
104 &debugger_metadata_info,
105 &debugger_compile_method,
106 &debugger_get_virtual_method,
107 &debugger_get_boxed_object,
108 &debugger_insert_breakpoint,
109 &debugger_remove_breakpoint,
110 &mono_debugger_runtime_invoke,
111 &debugger_create_string,
112 &debugger_class_get_static_field_data,
113 &debugger_lookup_class,
114 &debugger_lookup_type,
115 &debugger_lookup_assembly,
116 &debugger_run_finally,
117 &debugger_get_current_thread,
120 &debugger_initialize,
121 (void*)&mono_get_lmf_addr
125 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
127 MonoMethodDesc *desc;
129 desc = mono_method_desc_new (string_argument, TRUE);
133 return (guint64) mono_debugger_insert_breakpoint_full (desc);
137 debugger_remove_breakpoint (guint64 breakpoint)
139 return mono_debugger_remove_breakpoint (breakpoint);
143 debugger_compile_method_cb (MonoMethod *method)
147 mono_debugger_lock ();
148 retval = mono_compile_method (method);
149 mono_debugger_unlock ();
151 mono_debugger_notification_function (
152 MONO_DEBUGGER_EVENT_METHOD_COMPILED, (guint64) (gsize) retval, 0);
158 debugger_compile_method (guint64 method_arg)
160 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
162 return (guint64) (gsize) debugger_compile_method_cb (method);
166 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
168 MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
169 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
171 if (mono_class_is_valuetype (mono_method_get_class (method)))
174 return (guint64) (gsize) mono_object_get_virtual_method (object, method);
178 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
180 static MonoObject *last_boxed_object = NULL;
181 MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
182 gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
185 if (!mono_class_is_valuetype (klass))
188 boxed = mono_value_box (mono_domain_get (), klass, val);
189 last_boxed_object = boxed; // Protect the object from being garbage collected
191 return (guint64) (gsize) boxed;
195 debugger_create_string (guint64 dummy_argument, const gchar *string_argument)
197 return (guint64) (gsize) mono_string_new_wrapper (string_argument);
201 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument)
205 mono_debugger_lock ();
206 // retval = mono_debugger_lookup_type (string_argument);
208 mono_debugger_unlock ();
213 debugger_lookup_class (guint64 image_argument, guint64 token_argument)
215 MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
216 guint32 token = (guint32) token_argument;
219 klass = mono_class_get (image, token);
221 mono_class_init (klass);
223 return (guint64) (gsize) klass;
227 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument)
231 mono_debugger_lock ();
232 retval = mono_debugger_lookup_assembly (string_argument);
233 mono_debugger_unlock ();
238 debugger_run_finally (guint64 context_argument, guint64 dummy)
240 mono_debugger_run_finally (GUINT_TO_POINTER ((gsize)context_argument));
245 debugger_class_get_static_field_data (guint64 value)
247 MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
248 MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
249 return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
253 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
255 mono_debugger_notification_function (event, data, arg);
259 debugger_get_current_thread (void)
261 return (guint64) (gsize) mono_thread_current ();
265 debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
267 mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_CREATED,
268 (guint64) (gsize) stack_ptr, thread);
272 debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
274 mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_EXITED,
275 (guint64) (gsize) stack_ptr, thread);
279 debugger_gc_stop_world (void)
281 mono_debugger_event (
282 MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
286 debugger_gc_start_world (void)
288 mono_debugger_event (
289 MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
292 static GCThreadFunctions debugger_thread_vtable = {
295 debugger_gc_thread_created,
296 debugger_gc_thread_exited,
298 debugger_gc_stop_world,
299 debugger_gc_start_world
303 debugger_init_threads (void)
305 gc_thread_vtable = &debugger_thread_vtable;
309 debugger_finalize_threads (void)
311 gc_thread_vtable = NULL;
315 debugger_attach (void)
317 mono_debugger_init ();
319 mono_debugger_event_handler = debugger_event_handler;
320 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
322 debugger_init_threads ();
323 GC_mono_debugger_add_all_threads ();
327 debugger_detach (void)
329 mono_debugger_event_handler = NULL;
330 mono_debugger_notification_function = NULL;
331 debugger_finalize_threads ();
334 extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
337 debugger_initialize (void)
342 mono_debugger_init (void)
344 mono_debugger_notification_function = mono_debugger_create_notification_function ();
345 mono_debugger_event_handler = debugger_event_handler;
348 * Use an indirect call so gcc can't optimize it away.
350 MONO_DEBUGGER__debugger_info.initialize ();
352 debugger_init_threads ();
355 * Initialize the thread manager.
358 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
359 GetCurrentThreadId (), 0);
366 } DebuggerThreadArgs;
377 main_thread_handler (gpointer user_data)
379 MainThreadArgs *main_args = (MainThreadArgs *) user_data;
382 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_REACHED_MAIN,
383 (guint64) (gsize) main_args->method, 0);
385 retval = mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
388 * This will never return.
390 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0,
391 (guint64) (gsize) retval);
397 mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
399 MainThreadArgs main_args;
401 MonoMethod *main_method;
404 * Get and compile the main function.
407 image = mono_assembly_get_image (assembly);
408 main_method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
411 * Reload symbol tables.
413 * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
414 * linker from removing the .mdb_debug_info section.
416 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE,
417 (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
418 mono_debugger_unlock ();
421 * Start the main thread and wait until it's ready.
424 main_args.domain = domain;
425 main_args.method = main_method;
426 main_args.argc = argc;
427 main_args.argv = argv;
430 mono_thread_create (domain, main_thread_handler, &main_args);
432 main_thread_handler (&main_args);
435 mono_thread_manage ();
438 * This will never return.
440 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);