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