2010-03-01 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / debug-debugger.c
1 #include <config.h>
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>
11 #include "mini.h"
12 #include <unistd.h>
13 #include <locale.h>
14 #include <string.h>
15
16 /*
17  * This file is only compiled on platforms where the debugger is supported - see the conditional
18  * definition of `debugger_sources' in Makefile.am.
19  *
20  * configure.in checks whether we're using the included libgc and disables the debugger if not.
21  */
22
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!"
27 #endif
28
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);
33
34 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
35 static void debugger_initialize (void);
36 static guint64 debugger_init_code_buffer (void);
37
38 static void debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg);
39
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);
52
53 static guint64 debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2);
54
55 #define EXECUTABLE_CODE_BUFFER_SIZE 4096
56 static guint8 *debugger_executable_code_buffer = NULL;
57
58 static GCThreadFunctions debugger_thread_vtable;
59
60 static MonoDebuggerMetadataInfo debugger_metadata_info = {
61         sizeof (MonoDebuggerMetadataInfo),
62         sizeof (MonoDefaults),
63         &mono_defaults,
64         MONO_SIZEOF_TYPE,
65         sizeof (MonoArrayType),
66         sizeof (MonoClass),
67         sizeof (MonoInternalThread),
68         G_STRUCT_OFFSET (MonoInternalThread, tid),
69         G_STRUCT_OFFSET (MonoInternalThread, stack_ptr),
70         G_STRUCT_OFFSET (MonoInternalThread, end_stack),
71         G_STRUCT_OFFSET (MonoClass, image),
72         G_STRUCT_OFFSET (MonoClass, instance_size),
73         G_STRUCT_OFFSET (MonoClass, parent),
74         G_STRUCT_OFFSET (MonoClass, type_token),
75         G_STRUCT_OFFSET (MonoClass, fields),
76         G_STRUCT_OFFSET (MonoClass, methods),
77         G_STRUCT_OFFSET (MonoClass, method.count),
78         G_STRUCT_OFFSET (MonoClass, this_arg),
79         G_STRUCT_OFFSET (MonoClass, byval_arg),
80         G_STRUCT_OFFSET (MonoClass, generic_class),
81         G_STRUCT_OFFSET (MonoClass, generic_container),
82         G_STRUCT_OFFSET (MonoClass, vtable),
83         sizeof (MonoClassField),
84         G_STRUCT_OFFSET (MonoClassField, type),
85         G_STRUCT_OFFSET (MonoClassField, offset),
86         G_STRUCT_OFFSET (MonoDefaults, corlib),
87         G_STRUCT_OFFSET (MonoDefaults, object_class),
88         G_STRUCT_OFFSET (MonoDefaults, byte_class),
89         G_STRUCT_OFFSET (MonoDefaults, void_class),
90         G_STRUCT_OFFSET (MonoDefaults, boolean_class),
91         G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
92         G_STRUCT_OFFSET (MonoDefaults, int16_class),
93         G_STRUCT_OFFSET (MonoDefaults, uint16_class),
94         G_STRUCT_OFFSET (MonoDefaults, int32_class),
95         G_STRUCT_OFFSET (MonoDefaults, uint32_class),
96         G_STRUCT_OFFSET (MonoDefaults, int_class),
97         G_STRUCT_OFFSET (MonoDefaults, uint_class),
98         G_STRUCT_OFFSET (MonoDefaults, int64_class),
99         G_STRUCT_OFFSET (MonoDefaults, uint64_class),
100         G_STRUCT_OFFSET (MonoDefaults, single_class),
101         G_STRUCT_OFFSET (MonoDefaults, double_class),
102         G_STRUCT_OFFSET (MonoDefaults, char_class),
103         G_STRUCT_OFFSET (MonoDefaults, string_class),
104         G_STRUCT_OFFSET (MonoDefaults, enum_class),
105         G_STRUCT_OFFSET (MonoDefaults, array_class),
106         G_STRUCT_OFFSET (MonoDefaults, delegate_class),
107         G_STRUCT_OFFSET (MonoDefaults, exception_class),
108         G_STRUCT_OFFSET (MonoMethod, klass),
109         G_STRUCT_OFFSET (MonoMethod, token),
110         G_STRUCT_OFFSET (MonoMethod, name) + sizeof (void *),
111         G_STRUCT_OFFSET (MonoMethodInflated, declaring),
112         G_STRUCT_OFFSET (MonoVTable, klass),
113         G_STRUCT_OFFSET (MonoVTable, vtable)
114 };
115
116 extern void MONO_DEBUGGER__notification_function (guint64 command, guint64 data, guint64 data2);
117
118 /*
119  * This is a global data symbol which is read by the debugger.
120  */
121 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
122         MONO_DEBUGGER_MAGIC,
123         MONO_DEBUGGER_MAJOR_VERSION,
124         MONO_DEBUGGER_MINOR_VERSION,
125         0, /* runtime_flags */
126         sizeof (MonoDebuggerInfo),
127         sizeof (MonoSymbolTable),
128         MONO_TRAMPOLINE_NUM,
129         mono_trampoline_code,
130         &MONO_DEBUGGER__notification_function,
131         &mono_symbol_table,
132         &debugger_metadata_info,
133         &mono_debug_debugger_version,
134
135         &debugger_compile_method,
136         &debugger_get_virtual_method,
137         &debugger_get_boxed_object,
138         &mono_debugger_runtime_invoke,
139         &debugger_class_get_static_field_data,
140         &debugger_run_finally,
141         &debugger_initialize,
142
143         &debugger_create_string,
144         &debugger_lookup_class,
145
146         &debugger_insert_method_breakpoint,
147         &debugger_insert_source_breakpoint,
148         &debugger_remove_breakpoint,
149
150         &debugger_register_class_init_callback,
151         &debugger_remove_class_init_callback,
152
153         &mono_debugger_thread_table,
154
155         &debugger_executable_code_buffer,
156         mono_breakpoint_info,
157         mono_breakpoint_info_index,
158
159         EXECUTABLE_CODE_BUFFER_SIZE,
160         MONO_BREAKPOINT_ARRAY_SIZE,
161
162         debugger_get_method_signature,
163         debugger_init_code_buffer,
164
165         &gc_thread_vtable,
166         &debugger_thread_vtable,
167
168         &mono_debugger_event_handler,
169         debugger_event_handler,
170
171         &_mono_debug_using_mono_debugger,
172         (gint32*)&_mono_debugger_interruption_request,
173
174         &debugger_abort_runtime_invoke
175 };
176
177 static guint64
178 debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2)
179 {
180         return mono_debugger_abort_runtime_invoke ();
181 }
182
183 static guint64
184 debugger_compile_method (guint64 method_arg)
185 {
186         MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
187         gpointer addr;
188
189         mono_debugger_lock ();
190         addr = mono_compile_method (method);
191         mono_debugger_unlock ();
192
193         return (guint64) (gsize) addr;
194 }
195
196 static guint64
197 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
198 {
199         MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
200         MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
201
202         if (mono_class_is_valuetype (mono_method_get_class (method)))
203                 return method_arg;
204
205         return (guint64) (gsize) mono_object_get_virtual_method (object, method);
206 }
207
208 static guint64
209 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
210 {
211         static MonoObject *last_boxed_object = NULL;
212         MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
213         gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
214         MonoObject *boxed;
215
216         if (!mono_class_is_valuetype (klass))
217                 return val_arg;
218
219         boxed = mono_value_box (mono_domain_get (), klass, val);
220         last_boxed_object = boxed; // Protect the object from being garbage collected
221
222         return (guint64) (gsize) boxed;
223 }
224
225 static guint64
226 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
227                         G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument)
228 {
229         return (guint64) (gsize) mono_string_new_wrapper (string_argument);
230 }
231
232 static gint64
233 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
234                        G_GNUC_UNUSED guint64 dummy2, gchar *full_name)
235 {
236         MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
237         gchar *name_space, *name, *pos;
238         MonoClass *klass;
239
240         pos = strrchr (full_name, '.');
241         if (pos) {
242                 name_space = full_name;
243                 *pos = 0;
244                 name = pos + 1;
245         } else {
246                 name = full_name;
247                 name_space = NULL;
248         }
249
250         klass = mono_class_from_name (image, name_space ? name_space : "", name);
251         if (!klass)
252                 return -1;
253
254         mono_class_init (klass);
255         mono_class_setup_methods (klass);
256         return (gint64) (gssize) klass;
257 }
258
259 static guint64
260 debugger_run_finally (guint64 context_argument, G_GNUC_UNUSED guint64 dummy)
261 {
262         mono_debugger_run_finally (GUINT_TO_POINTER ((gsize)context_argument));
263         return 0;
264 }
265
266 static guint64
267 debugger_class_get_static_field_data (guint64 value)
268 {
269         MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
270         MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
271         return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
272 }
273
274 static guint64
275 debugger_insert_method_breakpoint (guint64 method_argument, guint64 index)
276 {
277         MonoMethod *method = GUINT_TO_POINTER ((gsize) method_argument);
278         MonoDebugMethodAddressList *info;
279
280         mono_debugger_lock ();
281
282         if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
283                 const char *name = method->name;
284                 MonoMethod *nm = NULL;
285
286                 if (method->klass->parent == mono_defaults.multicastdelegate_class) {
287                         if (*name == 'I' && (strcmp (name, "Invoke") == 0))
288                                 nm = mono_marshal_get_delegate_invoke (method, NULL);
289                         else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
290                                 nm = mono_marshal_get_delegate_begin_invoke (method);
291                         else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
292                                 nm = mono_marshal_get_delegate_end_invoke (method);
293                 }
294
295                 if (!nm) {
296                         mono_debugger_unlock ();
297                         return 0;
298                 }
299
300                 method = nm;
301         }
302
303         info = mono_debugger_insert_method_breakpoint (method, index);
304
305         mono_debugger_unlock ();
306         return (guint64) (gsize) info;
307 }
308
309 static guint64
310 debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint64 index,
311                                    const gchar *class_name)
312 {
313         MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
314         MonoDebugMethodAddressList *info;
315         MonoClass *klass;
316         int i;
317
318         mono_debugger_lock ();
319
320         klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
321         if (!klass || !klass->inited || !klass->methods) {
322                 mono_debugger_unlock ();
323                 return 0;
324         }
325
326         for (i = 0; i < klass->method.count; i++) {
327                 MonoMethod *method = klass->methods [i];
328
329                 if (method->token != token)
330                         continue;
331
332                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
333                         const char *name = method->name;
334                         MonoMethod *nm = NULL;
335
336                         if (method->klass->parent == mono_defaults.multicastdelegate_class) {
337                                 if (*name == 'I' && (strcmp (name, "Invoke") == 0))
338                                         nm = mono_marshal_get_delegate_invoke (method, NULL);
339                                 else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
340                                         nm = mono_marshal_get_delegate_begin_invoke (method);
341                                 else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
342                                         nm = mono_marshal_get_delegate_end_invoke (method);
343                         }
344
345                         if (!nm) {
346                                 mono_debugger_unlock ();
347                                 return 0;
348                         }
349
350                         method = nm;
351                 }
352
353                 info = mono_debug_lookup_method_addresses (method);
354                 mono_debugger_unlock ();
355                 return (guint64) (gsize) info;
356         }
357
358         mono_debugger_unlock ();
359         return 0;
360 }
361
362 static void
363 debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy)
364 {
365         mono_debugger_lock ();
366         mono_debugger_remove_method_breakpoint (index);
367         mono_debugger_remove_class_init_callback (index);
368         mono_debugger_unlock ();
369 }
370
371 static guint64
372 debugger_register_class_init_callback (guint64 image_argument, guint64 token, guint64 index,
373                                        const gchar *class_name)
374 {
375         MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
376         MonoClass *klass;
377
378         mono_debugger_lock ();
379         klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
380         mono_debugger_unlock ();
381         return (guint64) (gsize) klass;
382 }
383
384 static void
385 debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy)
386 {
387         mono_debugger_lock ();
388         mono_debugger_remove_class_init_callback (index);
389         mono_debugger_unlock ();
390 }
391
392 static guint64
393 debugger_get_method_signature (guint64 method_arg, G_GNUC_UNUSED guint64 dummy)
394 {
395         MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
396         MonoMethodSignature *sig;
397
398         sig = mono_method_signature (method);
399         return (guint64) (gsize) sig;
400 }
401
402 static void
403 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
404 {
405         MONO_DEBUGGER__notification_function (event, data, arg);
406 }
407
408 static void
409 debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
410 {
411         mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_CREATED,
412                              (guint64) (gsize) stack_ptr, thread);
413 }
414
415 static void
416 debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
417 {
418         mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_EXITED,
419                              (guint64) (gsize) stack_ptr, thread);
420 }
421
422 static void
423 debugger_gc_stop_world (void)
424 {
425         mono_debugger_event (MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
426 }
427
428 static void
429 debugger_gc_start_world (void)
430 {
431         mono_debugger_event (MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
432 }
433
434 static GCThreadFunctions debugger_thread_vtable = {
435         NULL,
436
437         debugger_gc_thread_created,
438         debugger_gc_thread_exited,
439
440         debugger_gc_stop_world,
441         debugger_gc_start_world
442 };
443
444 static void
445 debugger_init_threads (void)
446 {
447         gc_thread_vtable = &debugger_thread_vtable;
448 }
449
450 #if 0
451
452 static void
453 debugger_finalize_threads (void)
454 {
455         gc_thread_vtable = NULL;
456 }
457
458 #endif
459
460 static guint64
461 debugger_init_code_buffer (void)
462 {
463         if (!debugger_executable_code_buffer)
464                 debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
465         return (guint64) (gsize) debugger_executable_code_buffer;
466 }
467
468 extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
469 extern long MONO_DEBUGGER__using_debugger;
470
471 static void
472 debugger_initialize (void)
473 {
474 }
475
476 /**
477  * Check whether we're running inside the debugger.
478  *
479  * There seems to be a bug in some versions of glibc which causes _dl_debug_state() being called with
480  * RT_CONSISTENT before relocations are done.
481  *
482  * If that happens, the debugger cannot read the `MONO_DEBUGGER__debugger_info' structure at the time
483  * the `libmono.so' library is loaded.
484  *
485  * As a workaround, the `mdb_debug_info' now also contains a global variable called
486  * `MONO_DEBUGGER__using_debugger' which may we set to 1 by the debugger to tell us that we're running
487  * inside the debugger.
488  *
489  * mini_init() checks this and calls mini_debugger_init() if necessary.
490  *
491  */
492
493 gboolean
494 mini_debug_running_inside_mdb (void)
495 {
496         return MONO_DEBUGGER__using_debugger || mono_debug_using_mono_debugger ();
497 }
498
499 void
500 mini_debugger_init (void)
501 {
502         if (mono_debugger_event_handler) {
503                 g_warning (G_STRLOC ": duplicate call to mono_debugger_init()!");
504                 return;
505         }
506
507         debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
508         mono_debugger_event_handler = debugger_event_handler;
509
510         /*
511          * Use an indirect call so gcc can't optimize it away.
512          */
513         MONO_DEBUGGER__debugger_info.initialize ();
514
515         debugger_init_threads ();
516
517         /*
518          * Initialize the thread manager.
519          *
520          * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
521          * linker from removing the .mdb_debug_info section.
522          */
523
524         mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
525                              (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
526 }
527
528 void
529 mini_debugger_set_attach_ok (void)
530 {
531         MONO_DEBUGGER__debugger_info.runtime_flags |= DEBUGGER_RUNTIME_FLAGS_ATTACH_OK;
532 }
533
534 typedef struct 
535 {
536         MonoDomain *domain;
537         const char *file;
538 } DebuggerThreadArgs;
539
540 typedef struct
541 {
542         MonoDomain *domain;
543         MonoMethod *method;
544         int argc;
545         char **argv;
546 } MainThreadArgs;
547
548 static guint32
549 main_thread_handler (gpointer user_data)
550 {
551         MainThreadArgs *main_args = (MainThreadArgs *) user_data;
552
553         return mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
554 }
555
556 int
557 mini_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
558 {
559         MainThreadArgs main_args;
560         MonoImage *image;
561         MonoMethod *main_method;
562
563         /*
564          * Get and compile the main function.
565          */
566
567         image = mono_assembly_get_image (assembly);
568         main_method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
569
570         /*
571          * Initialize managed code.
572          */
573         mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE,
574                              (guint64) (gssize) main_method, 0);
575
576         /*
577          * Start the main thread and wait until it's ready.
578          */
579
580         main_args.domain = domain;
581         main_args.method = main_method;
582         main_args.argc = argc;
583         main_args.argv = argv;
584
585 #if RUN_IN_SUBTHREAD
586         mono_thread_create (domain, main_thread_handler, &main_args);
587 #else
588         main_thread_handler (&main_args);
589 #endif
590
591         mono_thread_manage ();
592
593         /*
594          * This will never return.
595          */
596         mono_debugger_event (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);
597
598         return 0;
599 }