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 #define _IN_THE_MONO_DEBUGGER
7 #include <mono/metadata/mono-debug-debugger.h>
8 #include <libgc/include/libgc-mono-debugger.h>
14 static GPtrArray *thread_array = NULL;
16 static gpointer main_started_cond;
17 static gpointer main_ready_cond;
19 static MonoMethod *debugger_main_method;
21 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
22 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
23 static guint64 debugger_compile_method (guint64 method_arg);
24 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
25 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
26 static guint64 debugger_create_string (guint64 dummy_argument, const gchar *string_argument);
27 static guint64 debugger_class_get_static_field_data (guint64 klass);
28 static guint64 debugger_lookup_class (guint64 image_argument, guint64 token_arg);
29 static guint64 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument);
30 static guint64 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument);
31 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
33 void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
36 * This is a global data symbol which is read by the debugger.
38 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
40 MONO_DEBUGGER_VERSION,
41 sizeof (MonoDebuggerInfo),
42 sizeof (MonoSymbolTable),
46 &debugger_compile_method,
47 &debugger_get_virtual_method,
48 &debugger_get_boxed_object,
49 &debugger_insert_breakpoint,
50 &debugger_remove_breakpoint,
51 &mono_debugger_runtime_invoke,
52 &debugger_create_string,
53 &debugger_class_get_static_field_data,
54 &debugger_lookup_class,
55 &debugger_lookup_type,
56 &debugger_lookup_assembly,
70 gpointer main_function;
71 gpointer notification_address;
72 MonoDebuggerThread *main_thread;
74 } MonoDebuggerManager;
76 MonoDebuggerManager MONO_DEBUGGER__manager = {
77 sizeof (MonoDebuggerManager),
78 sizeof (MonoDebuggerThread),
83 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
87 desc = mono_method_desc_new (string_argument, TRUE);
91 return (guint64) mono_debugger_insert_breakpoint_full (desc);
95 debugger_remove_breakpoint (guint64 breakpoint)
97 return mono_debugger_remove_breakpoint (breakpoint);
101 debugger_compile_method_cb (MonoMethod *method)
105 mono_debugger_lock ();
106 retval = mono_compile_method (method);
107 mono_debugger_unlock ();
109 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_METHOD_COMPILED, GPOINTER_TO_UINT (retval), 0);
115 debugger_compile_method (guint64 method_arg)
117 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
119 return GPOINTER_TO_UINT (debugger_compile_method_cb (method));
123 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
125 MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gssize) object_arg);
126 MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
128 if (mono_class_is_valuetype (mono_method_get_class (method)))
131 return GPOINTER_TO_UINT (mono_object_get_virtual_method (object, method));
135 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
137 static MonoObject *last_boxed_object = NULL;
138 MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gssize) klass_arg);
139 gpointer val = (gpointer) GUINT_TO_POINTER ((gssize) val_arg);
142 if (!mono_class_is_valuetype (klass))
145 boxed = mono_value_box (mono_domain_get (), klass, val);
146 last_boxed_object = boxed; // Protect the object from being garbage collected
148 return GPOINTER_TO_UINT (boxed);
152 debugger_create_string (guint64 dummy_argument, const gchar *string_argument)
154 return GPOINTER_TO_UINT (mono_string_new_wrapper (string_argument));
158 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument)
162 mono_debugger_lock ();
163 // retval = mono_debugger_lookup_type (string_argument);
165 mono_debugger_unlock ();
170 debugger_lookup_class (guint64 image_argument, guint64 token_argument)
172 MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gssize) image_argument);
173 guint32 token = (guint32) token_argument;
176 klass = mono_class_get (image, token);
178 mono_class_init (klass);
180 return GPOINTER_TO_UINT (klass);
184 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument)
188 mono_debugger_lock ();
189 retval = mono_debugger_lookup_assembly (string_argument);
190 mono_debugger_unlock ();
195 debugger_run_finally (guint64 context_argument, guint64 dummy)
197 mono_debugger_run_finally (GUINT_TO_POINTER (context_argument));
202 debugger_class_get_static_field_data (guint64 value)
204 MonoClass *klass = GUINT_TO_POINTER ((gssize) value);
205 MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
206 return GPOINTER_TO_UINT (mono_vtable_get_static_field_data (vtable));
210 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
212 mono_debugger_notification_function (event, data, arg);
216 debugger_thread_manager_thread_created (MonoDebuggerThread *thread)
219 thread_array = g_ptr_array_new ();
221 g_ptr_array_add (thread_array, thread);
225 debugger_thread_manager_add_thread (gsize tid, gpointer start_stack, gpointer func)
227 MonoDebuggerThread *thread = g_new0 (MonoDebuggerThread, 1);
231 thread->start_stack = start_stack;
233 mono_debugger_notification_function (
234 MONO_DEBUGGER_EVENT_THREAD_CREATED, GPOINTER_TO_UINT (thread), tid);
236 debugger_thread_manager_thread_created (thread);
240 debugger_thread_manager_start_resume (gsize tid)
245 debugger_thread_manager_end_resume (gsize tid)
249 extern void GC_push_all_stack (gpointer b, gpointer t);
252 debugger_gc_stop_world (void)
254 mono_debugger_notification_function (
255 MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
259 debugger_gc_start_world (void)
261 mono_debugger_notification_function (
262 MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
266 debugger_gc_push_all_stacks (void)
270 tid = GetCurrentThreadId ();
275 for (i = 0; i < thread_array->len; i++) {
276 MonoDebuggerThread *thread = g_ptr_array_index (thread_array, i);
277 gpointer end_stack = (thread->tid == tid) ? &i : thread->end_stack;
279 GC_push_all_stack (end_stack, thread->start_stack);
283 static GCThreadFunctions debugger_thread_vtable = {
286 debugger_gc_stop_world,
287 debugger_gc_push_all_stacks,
288 debugger_gc_start_world
292 debugger_thread_manager_init (void)
295 thread_array = g_ptr_array_new ();
297 gc_thread_vtable = &debugger_thread_vtable;
300 static MonoThreadCallbacks thread_callbacks = {
301 &debugger_compile_method_cb,
302 &debugger_thread_manager_add_thread,
303 &debugger_thread_manager_start_resume,
304 &debugger_thread_manager_end_resume
308 mono_debugger_init (void)
310 main_started_cond = CreateSemaphore (NULL, 0, 1, NULL);
311 main_ready_cond = CreateSemaphore (NULL, 0, 1, NULL);
313 mono_debugger_notification_function = mono_debugger_create_notification_function
314 (&MONO_DEBUGGER__manager.notification_address);
321 } DebuggerThreadArgs;
332 main_thread_handler (gpointer user_data)
334 MainThreadArgs *main_args = (MainThreadArgs *) user_data;
337 MONO_DEBUGGER__manager.main_tid = GetCurrentThreadId ();
338 MONO_DEBUGGER__manager.main_thread = g_new0 (MonoDebuggerThread, 1);
339 MONO_DEBUGGER__manager.main_thread->tid = GetCurrentThreadId ();
340 MONO_DEBUGGER__manager.main_thread->start_stack = &main_args;
342 debugger_thread_manager_thread_created (MONO_DEBUGGER__manager.main_thread);
344 ReleaseSemaphore (main_started_cond, 1, NULL);
347 * Wait until everything is ready.
349 WaitForSingleObject (main_ready_cond, INFINITE);
351 retval = mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
353 * This will never return.
355 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0, GPOINTER_TO_UINT (retval));
361 mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
363 MainThreadArgs main_args;
367 * Get and compile the main function.
370 image = mono_assembly_get_image (assembly);
371 debugger_main_method = mono_get_method (
372 image, mono_image_get_entry_point (image), NULL);
373 MONO_DEBUGGER__manager.main_function = mono_compile_method (debugger_main_method);
376 * Start the main thread and wait until it's ready.
379 main_args.domain = domain;
380 main_args.method = debugger_main_method;
381 main_args.argc = argc - 2;
382 main_args.argv = argv + 2;
384 mono_thread_create (domain, main_thread_handler, &main_args);
385 WaitForSingleObject (main_started_cond, INFINITE);
388 * Initialize the thread manager.
391 mono_debugger_event_handler = debugger_event_handler;
392 mono_install_thread_callbacks (&thread_callbacks);
393 debugger_thread_manager_init ();
396 * Reload symbol tables.
398 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
399 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER, 0, 0);
401 mono_debugger_unlock ();
404 * Signal the main thread that it can execute the managed Main().
406 ReleaseSemaphore (main_ready_cond, 1, NULL);
409 * This will never return.
411 mono_debugger_notification_function (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);