8 #include <mono/metadata/class.h>
9 #include <mono/metadata/assembly.h>
10 #include <mono/metadata/tabledefs.h>
11 #include <mono/metadata/tokentype.h>
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/debug-mono-symfile.h>
14 #include <mono/jit/codegen.h>
15 #include <mono/jit/debug.h>
17 #include "debug-private.h"
20 #ifndef PLATFORM_WIN32
22 * NOTE: Functions and variables starting with `mono_debug_' and `debug_' are
23 * part of the general debugging code.
25 * Functions and variables starting with `mono_debugger_' and `debugger_'
26 * are only used when the JIT is running inside the Mono Debugger.
28 * FIXME: This file needs some API loving.
31 /* This is incremented each time the symbol table is modified.
32 * The debugger looks at this variable and if it has a higher value than its current
33 * copy of the symbol table, it must call debugger_update_symbol_file_table().
35 static guint32 debugger_symbol_file_table_generation = 0;
36 static guint32 debugger_symbol_file_table_modified = 0;
38 /* Caution: This variable may be accessed at any time from the debugger;
39 * it is very important not to modify the memory it is pointing to
40 * without previously setting this pointer back to NULL.
42 static MonoDebuggerSymbolFileTable *debugger_symbol_file_table = NULL;
44 /* Caution: This function MUST be called before touching the symbol table! */
45 static void release_symbol_file_table (void);
47 static void initialize_debugger_support (void);
49 static gboolean running_in_the_mono_debugger = FALSE;
51 static MonoDebugHandle *mono_debug_handle = NULL;
52 static gboolean mono_debug_initialized = FALSE;
53 static gconstpointer debugger_notification_address = NULL;
55 static CRITICAL_SECTION debugger_lock_mutex;
57 static gpointer debugger_thread_cond;
58 static gpointer debugger_start_cond;
60 static gpointer debugger_finished_cond;
61 static CRITICAL_SECTION debugger_finished_mutex;
63 static gboolean debugger_signalled = FALSE;
64 static gboolean must_send_finished = FALSE;
66 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
68 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
69 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
70 static int debugger_update_symbol_file_table (void);
71 static int debugger_update_symbol_file_table_internal (void);
72 static gpointer debugger_compile_method (MonoMethod *method);
74 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
75 static void mono_debug_close_assembly (AssemblyDebugInfo* info);
76 static AssemblyDebugInfo *mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image);
79 * This is a global data symbol which is read by the debugger.
81 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
82 MONO_SYMBOL_FILE_DYNAMIC_MAGIC,
83 MONO_SYMBOL_FILE_DYNAMIC_VERSION,
84 sizeof (MonoDebuggerInfo),
85 &mono_generic_trampoline_code,
86 &mono_breakpoint_trampoline_code,
87 &debugger_symbol_file_table_generation,
88 &debugger_symbol_file_table_modified,
89 &debugger_notification_address,
90 &debugger_symbol_file_table,
91 &debugger_compile_method,
92 &debugger_insert_breakpoint,
93 &debugger_remove_breakpoint,
98 debugger_init_threads (void)
100 debugger_thread_cond = CreateSemaphore (NULL, 0, 1, NULL);
101 debugger_start_cond = CreateSemaphore (NULL, 0, 1, NULL);
103 InitializeCriticalSection (&debugger_finished_mutex);
104 debugger_finished_cond = CreateSemaphore (NULL, 0, 1, NULL);
108 mono_debug_init (void)
110 if (!mono_debug_initialized) {
111 InitializeCriticalSection (&debugger_lock_mutex);
112 mono_debug_initialized = TRUE;
117 mono_debug_lock (void)
119 if (mono_debug_initialized)
120 EnterCriticalSection (&debugger_lock_mutex);
124 mono_debug_unlock (void)
126 if (mono_debug_initialized)
127 LeaveCriticalSection (&debugger_lock_mutex);
131 mono_debugger_signal (gboolean modified)
133 g_assert (running_in_the_mono_debugger);
135 debugger_symbol_file_table_modified = TRUE;
137 if (!debugger_signalled) {
138 debugger_signalled = TRUE;
139 ReleaseSemaphore (debugger_thread_cond, 1, NULL);
141 mono_debug_unlock ();
145 mono_debugger_wait (void)
147 g_assert (running_in_the_mono_debugger);
148 LeaveCriticalSection (&debugger_finished_mutex);
149 g_assert (WaitForSingleObject (debugger_finished_cond, INFINITE) == WAIT_OBJECT_0);
150 EnterCriticalSection (&debugger_finished_mutex);
154 free_method_info (MonoDebugMethodInfo *minfo)
156 DebugMethodInfo *priv = minfo->user_data;
164 g_array_free (minfo->jit->line_numbers, TRUE);
165 g_free (minfo->jit->this_var);
166 g_free (minfo->jit->params);
167 g_free (minfo->jit->locals);
171 g_free (minfo->il_offsets);
176 debug_arg_warning (const char *message)
178 g_warning ("Error while processing --debug-args arguments: %s", message);
182 replace_suffix (const char *filename, const char *new_suffix)
184 const char *pos = strrchr (filename, '.');
187 return g_strdup_printf ("%s.%s", filename, new_suffix);
189 int len = pos - filename;
190 gchar *retval = g_malloc0 (len + strlen (new_suffix) + 2);
191 memcpy (retval, filename, len);
193 memcpy (retval + len + 1, new_suffix, strlen (new_suffix) + 1);
199 mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **args)
201 MonoDebugHandle *debug;
204 g_assert (!mono_debug_handle);
208 debug = g_new0 (MonoDebugHandle, 1);
209 debug->name = g_strdup (assembly->image->name);
210 debug->format = format;
211 debug->producer_name = g_strdup_printf ("Mono JIT compiler version %s", VERSION);
212 debug->next_idx = 100;
215 debug->type_hash = g_hash_table_new (NULL, NULL);
216 debug->source_files = g_ptr_array_new ();
218 debug->images = g_hash_table_new_full (NULL, NULL, NULL,
219 (GDestroyNotify) mono_debug_close_assembly);
221 for (ptr = args; ptr && *ptr; ptr++) {
222 const char *arg = *ptr;
225 switch (debug->format) {
226 case MONO_DEBUG_FORMAT_STABS:
227 case MONO_DEBUG_FORMAT_DWARF2:
228 if (!strncmp (arg, "filename=", 9)) {
230 debug_arg_warning ("The `filename' argument can be given only once.");
231 debug->filename = g_strdup (arg + 9);
233 } else if (!strncmp (arg, "objfile=", 8)) {
235 debug_arg_warning ("The `objfile' argument can be given only once.");
236 debug->objfile = g_strdup (arg + 8);
240 case MONO_DEBUG_FORMAT_MONO:
241 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
242 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
243 MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
249 if ((debug->format != MONO_DEBUG_FORMAT_MONO) &&
250 (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER)) {
251 if (!strcmp (arg, "dont_assemble")) {
252 debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
254 } else if (!strcmp (arg, "update_on_exit")) {
255 debug->flags |= MONO_DEBUG_FLAGS_UPDATE_ON_EXIT;
257 } else if (!strcmp (arg, "install_il_files")) {
258 debug->flags |= MONO_DEBUG_FLAGS_INSTALL_IL_FILES;
260 } else if (!strcmp (arg, "dont_update_il_files")) {
261 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES;
263 } else if (!strcmp (arg, "dont_create_il_files")) {
264 debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
269 message = g_strdup_printf ("Unknown argument `%s'.", arg);
270 debug_arg_warning (message);
274 switch (debug->format) {
275 case MONO_DEBUG_FORMAT_STABS:
276 if (!debug->filename)
277 debug->filename = g_strdup_printf ("%s-stabs.s", g_basename (debug->name));
279 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
281 case MONO_DEBUG_FORMAT_DWARF2:
282 if (!debug->filename)
283 debug->filename = g_strdup_printf ("%s-dwarf.s", g_basename (debug->name));
285 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
287 case MONO_DEBUG_FORMAT_MONO:
288 mono_debugger_class_init_func = mono_debug_add_type;
290 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
291 mono_debugger_class_init_func = mono_debug_add_type;
292 initialize_debugger_support ();
295 g_assert_not_reached ();
299 release_symbol_file_table ();
301 mono_debug_handle = debug;
302 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
304 mono_debug_open_image (mono_debug_handle, assembly->image);
305 mono_debug_open_image (mono_debug_handle, mono_defaults.corlib);
307 mono_debug_add_type (mono_defaults.object_class);
308 mono_debug_add_type (mono_defaults.object_class);
309 mono_debug_add_type (mono_defaults.byte_class);
310 mono_debug_add_type (mono_defaults.void_class);
311 mono_debug_add_type (mono_defaults.boolean_class);
312 mono_debug_add_type (mono_defaults.sbyte_class);
313 mono_debug_add_type (mono_defaults.int16_class);
314 mono_debug_add_type (mono_defaults.uint16_class);
315 mono_debug_add_type (mono_defaults.int32_class);
316 mono_debug_add_type (mono_defaults.uint32_class);
317 mono_debug_add_type (mono_defaults.int_class);
318 mono_debug_add_type (mono_defaults.uint_class);
319 mono_debug_add_type (mono_defaults.int64_class);
320 mono_debug_add_type (mono_defaults.uint64_class);
321 mono_debug_add_type (mono_defaults.single_class);
322 mono_debug_add_type (mono_defaults.double_class);
323 mono_debug_add_type (mono_defaults.char_class);
324 mono_debug_add_type (mono_defaults.string_class);
325 mono_debug_add_type (mono_defaults.enum_class);
326 mono_debug_add_type (mono_defaults.array_class);
327 mono_debug_add_type (mono_defaults.multicastdelegate_class);
328 mono_debug_add_type (mono_defaults.asyncresult_class);
329 mono_debug_add_type (mono_defaults.waithandle_class);
330 mono_debug_add_type (mono_defaults.typehandle_class);
331 mono_debug_add_type (mono_defaults.fieldhandle_class);
332 mono_debug_add_type (mono_defaults.methodhandle_class);
333 mono_debug_add_type (mono_defaults.monotype_class);
334 mono_debug_add_type (mono_defaults.exception_class);
335 mono_debug_add_type (mono_defaults.threadabortexception_class);
336 mono_debug_add_type (mono_defaults.thread_class);
337 mono_debug_add_type (mono_defaults.transparent_proxy_class);
338 mono_debug_add_type (mono_defaults.real_proxy_class);
339 mono_debug_add_type (mono_defaults.mono_method_message_class);
340 mono_debug_add_type (mono_defaults.appdomain_class);
341 mono_debug_add_type (mono_defaults.field_info_class);
342 mono_debug_add_type (mono_defaults.stringbuilder_class);
343 mono_debug_add_type (mono_defaults.math_class);
344 mono_debug_add_type (mono_defaults.stack_frame_class);
345 mono_debug_add_type (mono_defaults.stack_trace_class);
346 mono_debug_add_type (mono_defaults.marshal_class);
347 mono_debug_add_type (mono_defaults.iserializeable_class);
348 mono_debug_add_type (mono_defaults.serializationinfo_class);
349 mono_debug_add_type (mono_defaults.streamingcontext_class);
351 debugger_update_symbol_file_table ();
353 mono_debug_unlock ();
359 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
361 if (!mono_debug_handle)
365 mono_debug_open_image (mono_debug_handle, assembly->image);
366 mono_debug_unlock ();
370 generate_il_offsets (AssemblyDebugInfo *info, MonoMethod *method)
372 GPtrArray *il_offsets = g_ptr_array_new ();
373 MonoClass *klass = method->klass;
374 MonoDebugMethodInfo *minfo;
375 DebugMethodInfo *priv;
378 g_assert (klass->image == info->image);
380 /* FIXME: doesn't work yet. */
381 if (!strcmp (klass->name_space, "System.Runtime.Remoting.Proxies"))
384 mono_class_init (klass);
386 minfo = g_new0 (MonoDebugMethodInfo, 1);
387 minfo->method = method;
388 minfo->user_data = priv = g_new0 (DebugMethodInfo, 1);
390 priv->name = g_strdup_printf ("%s%s%s.%s", klass->name_space, klass->name_space [0]? ".": "",
391 klass->name, method->name);
392 priv->source_file = info->source_file;
396 * Find the method index in the image.
398 for (i = 0; klass->methods && i < klass->method.count; ++i) {
399 if (klass->methods [i] == minfo->method) {
400 priv->method_number = klass->method.first + i + 1;
401 priv->first_line = info->mlines [priv->method_number];
406 g_assert (priv->method_number);
408 /* info->moffsets contains -1 "outside" of functions. */
409 for (i = priv->first_line; (i > 0) && (info->moffsets [i] == 0); i--)
411 priv->start_line = i + 1;
413 for (i = priv->start_line; info->moffsets [i] != -1; i++) {
414 MonoSymbolFileLineNumberEntry *lne = g_new0 (MonoSymbolFileLineNumberEntry, 1);
416 if (!info->moffsets [i] && (i > priv->start_line))
419 lne->offset = info->moffsets [i];
422 g_ptr_array_add (il_offsets, lne);
427 minfo->start_line = priv->first_line;
428 minfo->end_line = priv->last_line;
430 minfo->num_il_offsets = il_offsets->len;
431 minfo->il_offsets = g_new0 (MonoSymbolFileLineNumberEntry, il_offsets->len);
432 for (i = 0; i < il_offsets->len; i++) {
433 MonoSymbolFileLineNumberEntry *il = g_ptr_array_index (il_offsets, i);
435 minfo->il_offsets [i] = *il;
438 g_ptr_array_free (il_offsets, TRUE);
440 g_hash_table_insert (info->methods, method, minfo);
444 debug_load_method_lines (AssemblyDebugInfo* info)
446 MonoTableInfo *table = &info->image->tables [MONO_TABLE_METHOD];
452 if (info->always_create_il || !(info->handle->flags & MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES)) {
453 char *command = g_strdup_printf ("monodis --output=%s %s",
454 info->ilfile, info->image->name);
455 struct stat stata, statb;
456 int need_update = FALSE;
458 if (stat (info->image->name, &stata)) {
459 g_warning ("cannot access assembly file (%s): %s",
460 info->image->name, g_strerror (errno));
465 /* If the stat() failed or the file is older. */
466 if (stat (info->ilfile, &statb)) {
468 } else if (statb.st_mtime < stata.st_mtime)
472 #ifndef PLATFORM_WIN32
473 struct sigaction act, oldact;
478 #ifndef PLATFORM_WIN32
479 act.sa_handler = SIG_IGN;
480 act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
481 sigemptyset (&act.sa_mask);
482 sigaddset (&act.sa_mask, SIGCHLD);
483 sigprocmask (SIG_BLOCK, &act.sa_mask, &old_set);
484 sigaction (SIGCHLD, &act, &oldact);
487 g_print ("Recreating %s from %s.\n", info->ilfile, info->image->name);
489 ret = system (command);
491 #ifndef PLATFORM_WIN32
492 sigaction (SIGCHLD, &oldact, NULL);
493 sigprocmask (SIG_SETMASK, &old_set, NULL);
497 g_warning ("cannot create IL assembly file (%s): %s",
498 command, g_strerror (errno));
505 /* use an env var with directories for searching. */
506 if (!(f = fopen (info->ilfile, "r"))) {
507 g_warning ("cannot open IL assembly file %s", info->ilfile);
511 info->total_lines = 100;
512 info->moffsets = g_malloc (info->total_lines * sizeof (int));
515 while (fgets (buf, sizeof (buf), f)) {
518 info->moffsets [i++] = offset;
519 if (i + 2 >= info->total_lines) {
520 info->total_lines += 100;
521 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
522 g_assert (info->moffsets);
525 if (!sscanf (buf, " // method line %d", &mnum))
530 if (mnum >= info->nmethods)
533 while (fgets (buf, sizeof (buf), f)) {
537 if (i + 2 >= info->total_lines) {
538 info->total_lines += 100;
539 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
540 g_assert (info->moffsets);
543 if (strstr (buf, "}")) {
548 if (sscanf (buf, " IL_%x:", &newoffset)) {
554 info->moffsets [i] = offset;
556 /* g_print ("method %d found at %d\n", mnum, pos); */
557 info->mlines [mnum] = pos;
561 for (idx = 1; idx <= table->rows; idx++) {
562 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
563 MonoMethod *method = mono_get_method (info->image, token, NULL);
565 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
566 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
567 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
570 if (method->wrapper_type != MONO_WRAPPER_NONE)
573 generate_il_offsets (info, method);
578 record_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, guint32 line)
580 MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
582 lne->address = address;
583 lne->offset = offset;
586 g_array_append_val (minfo->jit->line_numbers, *lne);
590 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
592 guint32 st_address, st_line;
593 DebugMethodInfo *priv = minfo->user_data;
596 if (!priv || !info->moffsets)
599 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
601 st_line = priv->first_line;
602 st_address = minfo->jit->prologue_end;
604 /* This is the first actual code line of the method. */
605 record_line_number (minfo, st_address, 0, st_line);
607 /* start lines of basic blocks */
608 for (i = 0; i < cfg->block_count; ++i) {
611 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
612 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
613 gint32 line_inc = 0, addr_inc;
616 st_line = priv->first_line;
617 st_address = t->addr;
620 addr_inc = t->addr - st_address;
621 st_address += addr_inc;
623 if (t->cli_addr != -1) {
624 int *lines = info->moffsets + st_line;
627 while ((*k != -1) && (*k < t->cli_addr))
630 line_inc = k - lines;
635 if (t->cli_addr != -1)
636 record_line_number (minfo, st_address, t->cli_addr, st_line);
642 generate_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, int debug)
647 g_message (G_STRLOC ": searching IL offset %x", offset);
649 for (i = minfo->num_il_offsets - 1; i >= 0; i--) {
650 MonoDebugLineNumberEntry *lne;
652 if (minfo->il_offsets [i].offset > offset)
656 g_message (G_STRLOC ": found entry %d: offset = %x, row = %d",
657 i, minfo->il_offsets [i].offset, minfo->il_offsets [i].row);
659 if (minfo->jit->line_numbers->len) {
660 MonoDebugLineNumberEntry last = g_array_index (
661 minfo->jit->line_numbers, MonoDebugLineNumberEntry,
662 minfo->jit->line_numbers->len - 1);
664 /* Avoid writing more than one entry for the same line. */
665 if (minfo->il_offsets [i].row == last.line) {
667 g_message (G_STRLOC ": skipping line: line = %d, last line = %d, "
668 "last address = %x, address = %x, "
669 "last offset = %x, offset = %x",
670 last.line, minfo->il_offsets [i].row,
671 last.address, address, last.offset, offset);
678 g_message (G_STRLOC ": writing entry: line = %d, offfset = %x, address = %x",
679 minfo->il_offsets [i].row, offset, address);
681 lne = g_new0 (MonoDebugLineNumberEntry, 1);
682 lne->address = address;
683 lne->offset = offset;
684 lne->line = minfo->il_offsets [i].row;
686 g_array_append_val (minfo->jit->line_numbers, *lne);
692 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
694 MonoMethodHeader *header;
695 guint32 address, offset;
699 g_assert (info->symfile);
700 if (info->symfile->is_dynamic)
703 g_assert (!minfo->jit->line_numbers);
704 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
706 address = minfo->jit->prologue_end;
709 g_assert (((MonoMethodNormal*)minfo->method)->header);
710 header = ((MonoMethodNormal*)minfo->method)->header;
713 if (!strcmp (minfo->method->name, "Test") || !strcmp (minfo->method->name, "Main")) {
714 MonoMethodHeader *header = ((MonoMethodNormal*)minfo->method)->header;
717 mono_disassemble_code (minfo->jit->code_start, minfo->jit->code_size,
718 minfo->method->name);
720 printf ("\nDisassembly:\n%s\n", mono_disasm_code (
721 NULL, minfo->method, header->code, header->code + header->code_size));
722 g_message (G_STRLOC ": %x - %x", minfo->jit->prologue_end, minfo->jit->epilogue_begin);
726 generate_line_number (minfo, address, offset, debug);
728 /* start lines of basic blocks */
729 for (i = 0; i < cfg->block_count; ++i) {
732 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
733 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
735 if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
738 offset = t->cli_addr;
741 generate_line_number (minfo, address, offset, debug);
745 generate_line_number (minfo, minfo->jit->epilogue_begin, header->code_size, debug);
748 for (i = 0; i < minfo->jit->line_numbers->len; i++) {
749 MonoDebugLineNumberEntry lne = g_array_index (
750 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
752 g_message (G_STRLOC ": %x,%x,%d", lne.address, lne.offset, lne.line);
757 static AssemblyDebugInfo *
758 mono_debug_get_image (MonoDebugHandle* debug, MonoImage *image)
760 return g_hash_table_lookup (debug->images, image);
763 static AssemblyDebugInfo *
764 mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
766 AssemblyDebugInfo *info;
769 info = mono_debug_get_image (debug, image);
775 info = g_new0 (AssemblyDebugInfo, 1);
777 info->image->ref_count++;
778 info->name = g_strdup (image->assembly_name);
779 info->format = debug->format;
780 info->handle = debug;
781 info->methods = g_hash_table_new_full (g_direct_hash, g_direct_equal,
782 NULL, (GDestroyNotify) free_method_info);
784 info->source_file = debug->source_files->len;
785 g_ptr_array_add (debug->source_files, g_strdup_printf ("%s.il", image->assembly_name));
787 g_hash_table_insert (debug->images, image, info);
789 info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
790 info->mlines = g_new0 (int, info->nmethods);
792 for (ptr = image->references; ptr && *ptr; ptr++)
793 mono_debug_add_assembly (*ptr, NULL);
795 switch (info->format) {
796 case MONO_DEBUG_FORMAT_STABS:
797 case MONO_DEBUG_FORMAT_DWARF2:
798 if (debug->flags & MONO_DEBUG_FLAGS_INSTALL_IL_FILES) {
799 gchar *dirname = g_path_get_dirname (image->name);
800 info->ilfile = g_strdup_printf ("%s/%s.il", dirname, info->name);
803 info->ilfile = g_strdup_printf ("%s.il", info->name);
805 case MONO_DEBUG_FORMAT_MONO:
806 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
807 info->filename = replace_suffix (image->name, "dbg");
808 if (g_file_test (info->filename, G_FILE_TEST_EXISTS))
809 info->symfile = mono_debug_open_mono_symbol_file (info->image, info->filename, TRUE);
810 else if (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER)
811 info->symfile = mono_debug_create_mono_symbol_file (info->image);
812 debugger_symbol_file_table_generation++;
819 if ((debug->format != MONO_DEBUG_FORMAT_MONO) && (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
820 debug_load_method_lines (info);
826 mono_debug_write_symbols (MonoDebugHandle *debug)
828 if (!debug || !debug->dirty)
831 release_symbol_file_table ();
833 switch (debug->format) {
834 case MONO_DEBUG_FORMAT_STABS:
835 mono_debug_write_stabs (debug);
837 case MONO_DEBUG_FORMAT_DWARF2:
838 mono_debug_write_dwarf2 (debug);
840 case MONO_DEBUG_FORMAT_MONO:
841 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
844 g_assert_not_reached ();
847 debug->dirty = FALSE;
851 mono_debug_make_symbols (void)
853 if (!mono_debug_handle || !mono_debug_handle->dirty)
856 switch (mono_debug_handle->format) {
857 case MONO_DEBUG_FORMAT_STABS:
858 mono_debug_write_stabs (mono_debug_handle);
860 case MONO_DEBUG_FORMAT_DWARF2:
861 mono_debug_write_dwarf2 (mono_debug_handle);
863 case MONO_DEBUG_FORMAT_MONO:
864 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
865 debugger_update_symbol_file_table ();
868 g_assert_not_reached ();
871 mono_debug_handle->dirty = FALSE;
875 mono_debug_close_assembly (AssemblyDebugInfo* info)
877 switch (info->format) {
878 case MONO_DEBUG_FORMAT_MONO:
879 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
880 if (info->symfile != NULL)
881 mono_debug_close_mono_symbol_file (info->symfile);
886 g_hash_table_destroy (info->methods);
887 g_free (info->mlines);
888 g_free (info->moffsets);
890 g_free (info->ilfile);
891 g_free (info->filename);
892 g_free (info->objfile);
897 mono_debug_cleanup (void)
899 release_symbol_file_table ();
901 if (!mono_debug_handle)
904 if (mono_debug_handle->flags & MONO_DEBUG_FLAGS_UPDATE_ON_EXIT)
905 mono_debug_write_symbols (mono_debug_handle);
907 g_hash_table_destroy (mono_debug_handle->images);
908 g_ptr_array_free (mono_debug_handle->source_files, TRUE);
909 g_hash_table_destroy (mono_debug_handle->type_hash);
910 g_free (mono_debug_handle->producer_name);
911 g_free (mono_debug_handle->name);
912 g_free (mono_debug_handle);
914 mono_debug_handle = NULL;
918 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
922 mono_class_init (klass);
924 index = GPOINTER_TO_INT (g_hash_table_lookup (debug->type_hash, klass));
930 index = ++debug->next_klass_idx;
931 g_hash_table_insert (debug->type_hash, klass, GINT_TO_POINTER (index));
936 switch (klass->byval_arg.type) {
937 case MONO_TYPE_CLASS:
939 mono_debug_get_type (debug, klass->parent);
941 for (i = 0; i < klass->method.count; i++) {
942 MonoMethod *method = klass->methods [i];
943 MonoType *ret_type = NULL;
946 if (method->signature->ret->type != MONO_TYPE_VOID)
947 ret_type = method->signature->ret;
950 MonoClass *ret_klass = mono_class_from_mono_type (ret_type);
951 mono_debug_get_type (debug, ret_klass);
954 for (j = 0; j < method->signature->param_count; j++) {
955 MonoType *sub_type = method->signature->params [j];
956 MonoClass *sub_klass = mono_class_from_mono_type (sub_type);
957 mono_debug_get_type (debug, sub_klass);
961 case MONO_TYPE_VALUETYPE:
962 for (i = 0; i < klass->field.count; i++) {
963 MonoClass *subclass = mono_class_from_mono_type (klass->fields [i].type);
964 mono_debug_get_type (debug, subclass);
967 case MONO_TYPE_ARRAY:
968 case MONO_TYPE_SZARRAY:
969 mono_debug_get_type (debug, klass->element_class);
979 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
983 if (!minfo->jit || !minfo->jit->line_numbers)
986 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
987 MonoDebugLineNumberEntry lne = g_array_index (
988 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
990 if (lne.address <= address)
998 address_from_il_offset (MonoDebugMethodInfo *minfo, guint32 il_offset)
1002 if (!minfo->jit || !minfo->jit->line_numbers)
1005 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
1006 MonoDebugLineNumberEntry lne = g_array_index (
1007 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
1009 if (lne.offset <= il_offset)
1017 mono_debug_add_type (MonoClass *klass)
1019 AssemblyDebugInfo* info;
1021 if (!mono_debug_handle)
1024 info = mono_debug_get_image (mono_debug_handle, klass->image);
1027 if ((mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO) &&
1028 (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1031 if (info->symfile) {
1033 mono_debug_symfile_add_type (info->symfile, klass);
1034 if (running_in_the_mono_debugger)
1035 mono_debugger_signal (TRUE);
1036 mono_debug_unlock ();
1041 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
1046 if (pos->abs_pos == 0)
1049 if (pos->pos.bid >= cfg->block_count)
1052 bblock = &cfg->bblocks [pos->pos.bid];
1053 if (pos->pos.tid >= bblock->forest->len)
1056 tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
1058 return tree->cli_addr;
1061 struct LookupMethodData
1063 MonoDebugMethodInfo *minfo;
1068 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
1070 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1071 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
1077 data->minfo = mono_debug_find_method (info->symfile, data->method);
1079 data->minfo = g_hash_table_lookup (info->methods, data->method);
1082 static MonoDebugMethodInfo *
1083 lookup_method (MonoMethod *method)
1085 struct LookupMethodData data = { NULL, method };
1087 if (!mono_debug_handle)
1090 g_hash_table_foreach (mono_debug_handle->images, lookup_method_func, &data);
1095 mono_debug_add_method (MonoFlowGraph *cfg)
1097 MonoMethod *method = cfg->method;
1098 MonoClass *klass = method->klass;
1099 AssemblyDebugInfo* info;
1100 MonoDebugMethodJitInfo *jit;
1101 MonoDebugMethodInfo *minfo;
1104 if (!mono_debug_handle)
1107 mono_class_init (klass);
1109 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
1110 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
1111 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
1112 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
1115 if (method->wrapper_type != MONO_WRAPPER_NONE)
1118 info = mono_debug_get_image (mono_debug_handle, klass->image);
1121 minfo = lookup_method (method);
1122 if (!minfo || minfo->jit)
1127 mono_debug_handle->dirty = TRUE;
1129 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
1130 jit->code_start = cfg->start;
1131 jit->code_size = cfg->epilogue_end;
1132 jit->prologue_end = cfg->prologue_end;
1133 jit->epilogue_begin = cfg->epilog;
1134 jit->num_params = method->signature->param_count;
1135 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
1137 if (method->signature->hasthis) {
1138 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
1140 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
1141 jit->this_var->offset = ptr->offset;
1142 jit->this_var->size = ptr->size;
1145 for (i = 0; i < jit->num_params; i++) {
1146 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
1147 method->signature->hasthis;
1149 jit->params [i].offset = ptr [i].offset;
1150 jit->params [i].size = ptr [i].size;
1153 debug_generate_method_lines (info, minfo, cfg);
1154 if ((info->format == MONO_DEBUG_FORMAT_MONO) || (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1155 debug_update_il_offsets (info, minfo, cfg);
1157 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1158 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
1159 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
1160 MonoDebugVarInfo *locals;
1162 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
1163 for (i = 0; i < header->num_locals; i++) {
1164 gint32 begin_offset, end_offset;
1165 gint32 begin_scope, end_scope;
1167 if (ptr [i].reg >= 0) {
1168 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
1169 locals [i].offset = 0;
1171 locals [i].offset = ptr [i].offset;
1173 locals [i].size = ptr [i].size;
1175 begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
1176 end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
1177 if (end_offset >= 0)
1180 if (begin_offset >= 0)
1181 begin_scope = address_from_il_offset (minfo, begin_offset);
1184 if (end_offset >= 0)
1185 end_scope = address_from_il_offset (minfo, end_offset);
1189 if (begin_scope > 0)
1190 locals [i].begin_scope = begin_scope;
1192 locals [i].begin_scope = jit->prologue_end;
1194 locals [i].end_scope = end_scope;
1196 locals [i].end_scope = jit->epilogue_begin;
1199 jit->num_locals = header->num_locals;
1200 jit->locals = locals;
1203 if (info->symfile) {
1204 mono_debug_symfile_add_method (info->symfile, method);
1205 if (running_in_the_mono_debugger)
1206 mono_debugger_signal (TRUE);
1209 mono_debug_unlock ();
1213 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
1215 MonoDebugMethodInfo *minfo = lookup_method (method);
1220 if (minfo->symfile) {
1221 gint32 offset = il_offset_from_address (minfo, address);
1226 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
1233 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
1235 MonoDebugMethodInfo *minfo;
1240 minfo = lookup_method (method);
1241 if (!minfo || !minfo->il_offsets)
1244 return il_offset_from_address (minfo, address);
1248 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
1250 MonoDebugMethodInfo *minfo;
1255 minfo = lookup_method (method);
1256 if (!minfo || !minfo->il_offsets)
1259 return address_from_il_offset (minfo, il_offset);
1263 release_symbol_file_table ()
1265 MonoDebuggerSymbolFileTable *temp;
1267 if (!debugger_symbol_file_table)
1271 * Caution: The debugger may access the memory pointed to by this variable
1272 * at any time. It is very important to set the pointer to NULL
1273 * before freeing the area.
1276 temp = debugger_symbol_file_table;
1277 debugger_symbol_file_table = NULL;
1278 g_free (debugger_symbol_file_table);
1282 update_symbol_file_table_count_func (gpointer key, gpointer value, gpointer user_data)
1284 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1288 if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1291 ++ (* (int *) user_data);
1294 struct SymfileTableData
1296 MonoDebuggerSymbolFileTable *symfile_table;
1301 update_symbol_file_table_func (gpointer key, gpointer value, gpointer user_data)
1303 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1304 struct SymfileTableData *data = (struct SymfileTableData *) user_data;
1308 if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1311 data->symfile_table->symfiles [data->index++] = info->symfile;
1315 debugger_update_symbol_file_table_internal (void)
1318 MonoDebuggerSymbolFileTable *symfile_table;
1319 struct SymfileTableData data;
1322 if (!mono_debug_handle)
1327 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_count_func, &count);
1329 release_symbol_file_table ();
1331 size = sizeof (MonoDebuggerSymbolFileTable) + count * sizeof (MonoSymbolFile *);
1332 symfile_table = g_malloc0 (size);
1333 symfile_table->magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
1334 symfile_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
1335 symfile_table->total_size = size;
1336 symfile_table->count = count;
1337 symfile_table->generation = debugger_symbol_file_table_generation;
1338 symfile_table->global_symfile = mono_debugger_global_symbol_file;
1340 data.symfile_table = symfile_table;
1343 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_func, &data);
1345 debugger_symbol_file_table = symfile_table;
1347 mono_debug_unlock ();
1353 debugger_update_symbol_file_table (void)
1357 if (!mono_debug_handle)
1361 retval = debugger_update_symbol_file_table_internal ();
1362 mono_debug_unlock ();
1367 static pid_t debugger_background_thread;
1368 extern void mono_debugger_init_thread_debug (pid_t);
1371 * NOTE: We must not call any functions here which we ever may want to debug !
1374 debugger_thread_func (gpointer ptr)
1376 void (*notification_code) (void) = ptr;
1377 int last_generation = 0;
1379 mono_new_thread_init (NULL, &last_generation);
1380 debugger_background_thread = getpid ();
1383 * The parent thread waits on this condition because it needs our pid.
1385 ReleaseSemaphore (debugger_start_cond, 1, NULL);
1388 * This mutex is locked by the parent thread until the debugger actually
1389 * attached to us, so we don't need a SIGSTOP here anymore.
1394 /* Wait for an event. */
1395 mono_debug_unlock ();
1396 g_assert (WaitForSingleObject (debugger_thread_cond, INFINITE) == WAIT_OBJECT_0);
1399 /* Reload the symbol file table if necessary. */
1400 if (debugger_symbol_file_table_generation > last_generation) {
1401 debugger_update_symbol_file_table_internal ();
1402 last_generation = debugger_symbol_file_table_generation;
1406 * Send notification - we'll stop on a breakpoint instruction at a special
1407 * address. The debugger will reload the symbol tables while we're stopped -
1408 * and owning the `debugger_thread_mutex' so that no other thread can touch
1409 * them in the meantime.
1411 notification_code ();
1413 /* Clear modified and signalled flag. */
1414 debugger_symbol_file_table_modified = FALSE;
1415 debugger_signalled = FALSE;
1417 if (must_send_finished) {
1418 EnterCriticalSection (&debugger_finished_mutex);
1419 ReleaseSemaphore (debugger_finished_cond, 1, NULL);
1420 must_send_finished = FALSE;
1421 LeaveCriticalSection (&debugger_finished_mutex);
1429 initialize_debugger_support ()
1434 if (running_in_the_mono_debugger)
1436 debugger_init_threads ();
1437 running_in_the_mono_debugger = TRUE;
1439 ptr = buf = g_malloc0 (16);
1440 x86_breakpoint (buf);
1441 debugger_notification_address = buf;
1445 * We keep this mutex until mono_debugger_jit_exec().
1450 * This mutex is only unlocked in mono_debugger_wait().
1452 EnterCriticalSection (&debugger_finished_mutex);
1454 thread = CreateThread (NULL, 0, debugger_thread_func, ptr, FALSE, NULL);
1458 * Wait until the background thread set its pid.
1460 g_assert (WaitForSingleObject (debugger_start_cond, INFINITE) == WAIT_OBJECT_0);
1463 * Wait until the debugger thread has actually been started and we
1464 * have its pid, then actually start the background thread.
1466 #ifndef PLATFORM_WIN32
1467 mono_debugger_init_thread_debug (debugger_background_thread);
1471 static GPtrArray *breakpoints = NULL;
1474 mono_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
1476 static int last_breakpoint_id = 0;
1477 MonoDebuggerBreakpointInfo *info;
1479 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1481 info->use_trampoline = use_trampoline;
1482 info->index = ++last_breakpoint_id;
1485 breakpoints = g_ptr_array_new ();
1487 g_ptr_array_add (breakpoints, info);
1493 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
1495 MonoMethodDesc *desc;
1497 desc = mono_method_desc_new (string_argument, FALSE);
1501 return mono_insert_breakpoint_full (desc, TRUE);
1505 debugger_remove_breakpoint (guint64 breakpoint)
1512 for (i = 0; i < breakpoints->len; i++) {
1513 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1515 if (info->index != breakpoint)
1518 mono_method_desc_free (info->desc);
1519 g_ptr_array_remove (breakpoints, info);
1528 debugger_compile_method (MonoMethod *method)
1533 retval = mono_compile_method (method);
1534 mono_debugger_signal (FALSE);
1535 mono_debug_unlock ();
1540 mono_remove_breakpoint (int breakpoint_id)
1542 return debugger_remove_breakpoint (breakpoint_id);
1546 mono_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1548 MonoMethodDesc *desc;
1550 desc = mono_method_desc_new (method_name, include_namespace);
1554 return mono_insert_breakpoint_full (desc, running_in_the_mono_debugger);
1558 mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
1562 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1565 for (i = 0; i < breakpoints->len; i++) {
1566 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1568 if (info->use_trampoline != use_trampoline)
1571 if (!mono_method_desc_full_match (info->desc, method))
1581 mono_debugger_trampoline_breakpoint_callback (void)
1584 must_send_finished = TRUE;
1585 mono_debugger_signal (FALSE);
1586 mono_debug_unlock ();
1588 mono_debugger_wait ();
1592 * This is a custom version of mono_jit_exec() which is used when we're being run inside
1593 * the Mono Debugger.
1596 mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
1598 MonoImage *image = assembly->image;
1603 method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
1605 addr = mono_compile_method (method);
1608 * The mutex has been locked in initialize_debugger_support(); we keep it locked
1609 * until we compiled the main method and signalled the debugger.
1611 must_send_finished = TRUE;
1612 mono_debugger_signal (TRUE);
1613 mono_debug_unlock ();
1616 * Wait until the debugger has loaded the initial symbol tables.
1618 mono_debugger_wait ();
1620 retval = mono_runtime_run_main (method, argc, argv, NULL);
1623 * Kill the background thread.
1625 #ifndef PLATFORM_WIN32
1626 /* Someone should look at this too */
1627 kill (debugger_background_thread, SIGKILL);
1635 mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **args)
1641 mono_debug_write_symbols (MonoDebugHandle *debug)
1646 mono_debug_make_symbols (void)
1651 mono_debug_cleanup (void)
1656 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
1662 mono_debug_add_type (MonoClass *klass)
1667 mono_debug_add_method (MonoFlowGraph *cfg)
1672 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
1678 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
1684 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
1690 mono_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
1696 mono_remove_breakpoint (int breakpoint_id)
1702 mono_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1708 mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
1714 mono_debugger_trampoline_breakpoint_callback (void)
1719 mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
1723 #endif /* PLATFORM_WIN32 */