6 #include <mono/metadata/class.h>
7 #include <mono/metadata/assembly.h>
8 #include <mono/metadata/tabledefs.h>
9 #include <mono/metadata/tokentype.h>
10 #include <mono/metadata/debug-helpers.h>
11 #include <mono/metadata/debug-mono-symfile.h>
12 #include <mono/jit/codegen.h>
13 #include <mono/jit/debug.h>
15 #include "debug-private.h"
18 /* This is incremented each time the symbol table is modified.
19 * The debugger looks at this variable and if it has a higher value than its current
20 * copy of the symbol table, it must call debugger_update_symbol_file_table().
22 static guint32 debugger_symbol_file_table_generation = 0;
23 static guint32 debugger_symbol_file_table_modified = 0;
25 /* Caution: This variable may be accessed at any time from the debugger;
26 * it is very important not to modify the memory it is pointing to
27 * without previously setting this pointer back to NULL.
29 static MonoDebuggerSymbolFileTable *debugger_symbol_file_table = NULL;
31 /* Caution: This function MUST be called before touching the symbol table! */
32 static void release_symbol_file_table (void);
34 static void initialize_debugger_support (void);
36 static MonoDebugHandle *mono_debug_handle = NULL;
37 static gconstpointer debugger_notification_address = NULL;
38 static GCond *debugger_thread_cond = NULL;
39 static GStaticRecMutex debugger_lock_mutex = G_STATIC_REC_MUTEX_INIT;
40 static GMutex *debugger_thread_mutex = NULL;
41 static GCond *debugger_finished_cond = NULL;
42 static GMutex *debugger_finished_mutex = NULL;
43 static GCond *debugger_start_cond = NULL;
44 static GMutex *debugger_start_mutex = NULL;
45 static gboolean debugger_signalled = FALSE;
46 static gboolean must_send_finished = FALSE;
48 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
50 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
51 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
52 static int debugger_update_symbol_file_table (void);
53 static int debugger_update_symbol_file_table_internal (void);
54 static gpointer debugger_compile_method (MonoMethod *method);
56 static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
57 static void mono_debug_close_assembly (AssemblyDebugInfo* info);
58 static AssemblyDebugInfo *mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image);
61 * This is a global data symbol which is read by the debugger.
63 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
64 MONO_SYMBOL_FILE_DYNAMIC_MAGIC,
65 MONO_SYMBOL_FILE_DYNAMIC_VERSION,
66 sizeof (MonoDebuggerInfo),
67 &mono_generic_trampoline_code,
68 &mono_breakpoint_trampoline_code,
69 &debugger_symbol_file_table_generation,
70 &debugger_symbol_file_table_modified,
71 &debugger_notification_address,
72 &debugger_symbol_file_table,
73 &debugger_compile_method,
74 &debugger_insert_breakpoint,
75 &debugger_remove_breakpoint,
80 debugger_init_threads (void)
84 debugger_thread_cond = g_cond_new ();
85 debugger_finished_cond = g_cond_new ();
86 debugger_start_cond = g_cond_new ();
88 debugger_thread_mutex = g_mutex_new ();
89 debugger_finished_mutex = g_mutex_new ();
90 debugger_start_mutex = g_mutex_new ();
94 mono_debugger_lock (void)
96 g_static_rec_mutex_lock (&debugger_lock_mutex);
100 mono_debugger_unlock (void)
102 g_static_rec_mutex_unlock (&debugger_lock_mutex);
106 mono_debugger_signal (gboolean modified)
109 debugger_symbol_file_table_modified = TRUE;
110 if (!debugger_signalled) {
111 debugger_signalled = TRUE;
112 g_cond_signal (debugger_thread_cond);
117 mono_debugger_wait (void)
119 g_cond_wait (debugger_finished_cond, debugger_finished_mutex);
123 free_method_info (MonoDebugMethodInfo *minfo)
125 DebugMethodInfo *priv = minfo->user_data;
133 g_array_free (minfo->jit->line_numbers, TRUE);
134 g_free (minfo->jit->this_var);
135 g_free (minfo->jit->params);
136 g_free (minfo->jit->locals);
140 g_free (minfo->il_offsets);
145 debug_arg_warning (const char *message)
147 g_warning ("Error while processing --debug-args arguments: %s", message);
151 replace_suffix (const char *filename, const char *new_suffix)
153 const char *pos = strrchr (filename, '.');
156 return g_strdup_printf ("%s.%s", filename, new_suffix);
158 int len = pos - filename;
159 gchar *retval = g_malloc0 (len + strlen (new_suffix) + 2);
160 memcpy (retval, filename, len);
162 memcpy (retval + len + 1, new_suffix, strlen (new_suffix) + 1);
168 mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **args)
170 MonoDebugHandle *debug;
173 g_assert (!mono_debug_handle);
175 debug = g_new0 (MonoDebugHandle, 1);
176 debug->name = g_strdup (assembly->image->name);
177 debug->format = format;
178 debug->producer_name = g_strdup_printf ("Mono JIT compiler version %s", VERSION);
179 debug->next_idx = 100;
182 debug->type_hash = g_hash_table_new (NULL, NULL);
183 debug->source_files = g_ptr_array_new ();
185 debug->images = g_hash_table_new_full (NULL, NULL, NULL,
186 (GDestroyNotify) mono_debug_close_assembly);
188 for (ptr = args; ptr && *ptr; ptr++) {
189 const char *arg = *ptr;
192 switch (debug->format) {
193 case MONO_DEBUG_FORMAT_STABS:
194 case MONO_DEBUG_FORMAT_DWARF2:
195 if (!strncmp (arg, "filename=", 9)) {
197 debug_arg_warning ("The `filename' argument can be given only once.");
198 debug->filename = g_strdup (arg + 9);
200 } else if (!strncmp (arg, "objfile=", 8)) {
202 debug_arg_warning ("The `objfile' argument can be given only once.");
203 debug->objfile = g_strdup (arg + 8);
207 case MONO_DEBUG_FORMAT_MONO:
208 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
209 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
210 MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
216 if ((debug->format != MONO_DEBUG_FORMAT_MONO) &&
217 (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER)) {
218 if (!strcmp (arg, "dont_assemble")) {
219 debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
221 } else if (!strcmp (arg, "update_on_exit")) {
222 debug->flags |= MONO_DEBUG_FLAGS_UPDATE_ON_EXIT;
224 } else if (!strcmp (arg, "install_il_files")) {
225 debug->flags |= MONO_DEBUG_FLAGS_INSTALL_IL_FILES;
227 } else if (!strcmp (arg, "dont_update_il_files")) {
228 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES;
230 } else if (!strcmp (arg, "dont_create_il_files")) {
231 debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
236 message = g_strdup_printf ("Unknown argument `%s'.", arg);
237 debug_arg_warning (message);
241 switch (debug->format) {
242 case MONO_DEBUG_FORMAT_STABS:
243 if (!debug->filename)
244 debug->filename = g_strdup_printf ("%s-stabs.s", g_basename (debug->name));
246 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
248 case MONO_DEBUG_FORMAT_DWARF2:
249 if (!debug->filename)
250 debug->filename = g_strdup_printf ("%s-dwarf.s", g_basename (debug->name));
252 debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
254 case MONO_DEBUG_FORMAT_MONO:
255 mono_debugger_class_init_func = mono_debug_add_type;
257 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
258 mono_debugger_class_init_func = mono_debug_add_type;
259 initialize_debugger_support ();
262 g_assert_not_reached ();
265 mono_debugger_lock ();
266 release_symbol_file_table ();
268 mono_debug_handle = debug;
269 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
271 mono_debug_open_image (mono_debug_handle, assembly->image);
272 mono_debug_open_image (mono_debug_handle, mono_defaults.corlib);
274 mono_debug_add_type (mono_defaults.object_class);
275 mono_debug_add_type (mono_defaults.object_class);
276 mono_debug_add_type (mono_defaults.byte_class);
277 mono_debug_add_type (mono_defaults.void_class);
278 mono_debug_add_type (mono_defaults.boolean_class);
279 mono_debug_add_type (mono_defaults.sbyte_class);
280 mono_debug_add_type (mono_defaults.int16_class);
281 mono_debug_add_type (mono_defaults.uint16_class);
282 mono_debug_add_type (mono_defaults.int32_class);
283 mono_debug_add_type (mono_defaults.uint32_class);
284 mono_debug_add_type (mono_defaults.int_class);
285 mono_debug_add_type (mono_defaults.uint_class);
286 mono_debug_add_type (mono_defaults.int64_class);
287 mono_debug_add_type (mono_defaults.uint64_class);
288 mono_debug_add_type (mono_defaults.single_class);
289 mono_debug_add_type (mono_defaults.double_class);
290 mono_debug_add_type (mono_defaults.char_class);
291 mono_debug_add_type (mono_defaults.string_class);
292 mono_debug_add_type (mono_defaults.enum_class);
293 mono_debug_add_type (mono_defaults.array_class);
294 mono_debug_add_type (mono_defaults.multicastdelegate_class);
295 mono_debug_add_type (mono_defaults.asyncresult_class);
296 mono_debug_add_type (mono_defaults.waithandle_class);
297 mono_debug_add_type (mono_defaults.typehandle_class);
298 mono_debug_add_type (mono_defaults.fieldhandle_class);
299 mono_debug_add_type (mono_defaults.methodhandle_class);
300 mono_debug_add_type (mono_defaults.monotype_class);
301 mono_debug_add_type (mono_defaults.exception_class);
302 mono_debug_add_type (mono_defaults.threadabortexception_class);
303 mono_debug_add_type (mono_defaults.thread_class);
304 mono_debug_add_type (mono_defaults.transparent_proxy_class);
305 mono_debug_add_type (mono_defaults.real_proxy_class);
306 mono_debug_add_type (mono_defaults.mono_method_message_class);
307 mono_debug_add_type (mono_defaults.appdomain_class);
308 mono_debug_add_type (mono_defaults.field_info_class);
309 mono_debug_add_type (mono_defaults.stringbuilder_class);
310 mono_debug_add_type (mono_defaults.math_class);
311 mono_debug_add_type (mono_defaults.stack_frame_class);
312 mono_debug_add_type (mono_defaults.stack_trace_class);
313 mono_debug_add_type (mono_defaults.marshal_class);
314 mono_debug_add_type (mono_defaults.iserializeable_class);
315 mono_debug_add_type (mono_defaults.serializationinfo_class);
316 mono_debug_add_type (mono_defaults.streamingcontext_class);
318 debugger_update_symbol_file_table ();
320 mono_debugger_unlock ();
326 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
328 if (!mono_debug_handle)
331 mono_debugger_lock ();
332 mono_debug_open_image (mono_debug_handle, assembly->image);
333 mono_debugger_unlock ();
337 generate_il_offsets (AssemblyDebugInfo *info, MonoMethod *method)
339 GPtrArray *il_offsets = g_ptr_array_new ();
340 MonoClass *klass = method->klass;
341 MonoDebugMethodInfo *minfo;
342 DebugMethodInfo *priv;
345 g_assert (klass->image == info->image);
347 /* FIXME: doesn't work yet. */
348 if (!strcmp (klass->name_space, "System.Runtime.Remoting.Proxies"))
351 mono_class_init (klass);
353 minfo = g_new0 (MonoDebugMethodInfo, 1);
354 minfo->method = method;
355 minfo->user_data = priv = g_new0 (DebugMethodInfo, 1);
357 priv->name = g_strdup_printf ("%s%s%s.%s", klass->name_space, klass->name_space [0]? ".": "",
358 klass->name, method->name);
359 priv->source_file = info->source_file;
363 * Find the method index in the image.
365 for (i = 0; klass->methods && i < klass->method.count; ++i) {
366 if (klass->methods [i] == minfo->method) {
367 priv->method_number = klass->method.first + i + 1;
368 priv->first_line = info->mlines [priv->method_number];
373 g_assert (priv->method_number);
375 /* info->moffsets contains -1 "outside" of functions. */
376 for (i = priv->first_line; (i > 0) && (info->moffsets [i] == 0); i--)
378 priv->start_line = i + 1;
380 for (i = priv->start_line; info->moffsets [i] != -1; i++) {
381 MonoSymbolFileLineNumberEntry *lne = g_new0 (MonoSymbolFileLineNumberEntry, 1);
383 if (!info->moffsets [i] && (i > priv->start_line))
386 lne->offset = info->moffsets [i];
389 g_ptr_array_add (il_offsets, lne);
394 minfo->start_line = priv->first_line;
395 minfo->end_line = priv->last_line;
397 minfo->num_il_offsets = il_offsets->len;
398 minfo->il_offsets = g_new0 (MonoSymbolFileLineNumberEntry, il_offsets->len);
399 for (i = 0; i < il_offsets->len; i++) {
400 MonoSymbolFileLineNumberEntry *il = g_ptr_array_index (il_offsets, i);
402 minfo->il_offsets [i] = *il;
405 g_ptr_array_free (il_offsets, TRUE);
407 g_hash_table_insert (info->methods, method, minfo);
411 debug_load_method_lines (AssemblyDebugInfo* info)
413 MonoTableInfo *table = &info->image->tables [MONO_TABLE_METHOD];
419 if (info->always_create_il || !(info->handle->flags & MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES)) {
420 char *command = g_strdup_printf ("monodis --output=%s %s",
421 info->ilfile, info->image->name);
422 struct stat stata, statb;
423 int need_update = FALSE;
425 if (stat (info->image->name, &stata)) {
426 g_warning ("cannot access assembly file (%s): %s",
427 info->image->name, g_strerror (errno));
432 /* If the stat() failed or the file is older. */
433 if (stat (info->ilfile, &statb)) {
435 } else if (statb.st_mtime < stata.st_mtime)
439 #ifndef PLATFORM_WIN32
440 struct sigaction act, oldact;
445 #ifndef PLATFORM_WIN32
446 act.sa_handler = SIG_IGN;
447 act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
448 sigemptyset (&act.sa_mask);
449 sigaddset (&act.sa_mask, SIGCHLD);
450 sigprocmask (SIG_BLOCK, &act.sa_mask, &old_set);
451 sigaction (SIGCHLD, &act, &oldact);
454 g_print ("Recreating %s from %s.\n", info->ilfile, info->image->name);
456 ret = system (command);
458 #ifndef PLATFORM_WIN32
459 sigaction (SIGCHLD, &oldact, NULL);
460 sigprocmask (SIG_SETMASK, &old_set, NULL);
464 g_warning ("cannot create IL assembly file (%s): %s",
465 command, g_strerror (errno));
472 /* use an env var with directories for searching. */
473 if (!(f = fopen (info->ilfile, "r"))) {
474 g_warning ("cannot open IL assembly file %s", info->ilfile);
478 info->total_lines = 100;
479 info->moffsets = g_malloc (info->total_lines * sizeof (int));
482 while (fgets (buf, sizeof (buf), f)) {
485 info->moffsets [i++] = offset;
486 if (i + 2 >= info->total_lines) {
487 info->total_lines += 100;
488 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
489 g_assert (info->moffsets);
492 if (!sscanf (buf, " // method line %d", &mnum))
497 if (mnum >= info->nmethods)
500 while (fgets (buf, sizeof (buf), f)) {
504 if (i + 2 >= info->total_lines) {
505 info->total_lines += 100;
506 info->moffsets = g_realloc (info->moffsets, info->total_lines * sizeof (int));
507 g_assert (info->moffsets);
510 if (strstr (buf, "}")) {
515 if (sscanf (buf, " IL_%x:", &newoffset)) {
521 info->moffsets [i] = offset;
523 /* g_print ("method %d found at %d\n", mnum, pos); */
524 info->mlines [mnum] = pos;
528 for (idx = 1; idx <= table->rows; idx++) {
529 guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
530 MonoMethod *method = mono_get_method (info->image, token, NULL);
532 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
533 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
534 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
537 if (method->wrapper_type != MONO_WRAPPER_NONE)
540 generate_il_offsets (info, method);
545 record_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, guint32 line)
547 MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
549 lne->address = address;
550 lne->offset = offset;
553 g_array_append_val (minfo->jit->line_numbers, *lne);
557 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
559 guint32 st_address, st_line;
560 DebugMethodInfo *priv = minfo->user_data;
563 if (!priv || !info->moffsets)
566 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
568 st_line = priv->first_line;
569 st_address = minfo->jit->prologue_end;
571 /* This is the first actual code line of the method. */
572 record_line_number (minfo, st_address, 0, st_line);
574 /* start lines of basic blocks */
575 for (i = 0; i < cfg->block_count; ++i) {
578 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
579 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
580 gint32 line_inc = 0, addr_inc;
583 st_line = priv->first_line;
584 st_address = t->addr;
587 addr_inc = t->addr - st_address;
588 st_address += addr_inc;
590 if (t->cli_addr != -1) {
591 int *lines = info->moffsets + st_line;
594 while ((*k != -1) && (*k < t->cli_addr))
597 line_inc = k - lines;
602 if (t->cli_addr != -1)
603 record_line_number (minfo, st_address, t->cli_addr, st_line);
609 generate_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, int debug)
614 g_message (G_STRLOC ": searching IL offset %x", offset);
616 for (i = minfo->num_il_offsets - 1; i >= 0; i--) {
617 MonoDebugLineNumberEntry *lne;
619 if (minfo->il_offsets [i].offset > offset)
623 g_message (G_STRLOC ": found entry %d: offset = %x, row = %d",
624 i, minfo->il_offsets [i].offset, minfo->il_offsets [i].row);
626 if (minfo->jit->line_numbers->len) {
627 MonoDebugLineNumberEntry last = g_array_index (
628 minfo->jit->line_numbers, MonoDebugLineNumberEntry,
629 minfo->jit->line_numbers->len - 1);
631 /* Avoid writing more than one entry for the same line. */
632 if (minfo->il_offsets [i].row == last.line) {
634 g_message (G_STRLOC ": skipping line: line = %d, last line = %d, "
635 "last address = %x, address = %x, "
636 "last offset = %x, offset = %x",
637 last.line, minfo->il_offsets [i].row,
638 last.address, address, last.offset, offset);
645 g_message (G_STRLOC ": writing entry: line = %d, offfset = %x, address = %x",
646 minfo->il_offsets [i].row, offset, address);
648 lne = g_new0 (MonoDebugLineNumberEntry, 1);
649 lne->address = address;
650 lne->offset = offset;
651 lne->line = minfo->il_offsets [i].row;
653 g_array_append_val (minfo->jit->line_numbers, *lne);
659 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
661 MonoMethodHeader *header;
662 guint32 address, offset;
666 g_assert (info->symfile);
667 if (info->symfile->is_dynamic)
670 g_assert (!minfo->jit->line_numbers);
671 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
673 address = minfo->jit->prologue_end;
676 g_assert (((MonoMethodNormal*)minfo->method)->header);
677 header = ((MonoMethodNormal*)minfo->method)->header;
680 if (!strcmp (minfo->method->name, "Test") || !strcmp (minfo->method->name, "Main")) {
681 MonoMethodHeader *header = ((MonoMethodNormal*)minfo->method)->header;
684 mono_disassemble_code (minfo->jit->code_start, minfo->jit->code_size,
685 minfo->method->name);
687 printf ("\nDisassembly:\n%s\n", mono_disasm_code (
688 NULL, minfo->method, header->code, header->code + header->code_size));
689 g_message (G_STRLOC ": %x - %x", minfo->jit->prologue_end, minfo->jit->epilogue_begin);
693 generate_line_number (minfo, address, offset, debug);
695 /* start lines of basic blocks */
696 for (i = 0; i < cfg->block_count; ++i) {
699 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
700 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
702 if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
705 offset = t->cli_addr;
708 generate_line_number (minfo, address, offset, debug);
712 generate_line_number (minfo, minfo->jit->epilogue_begin, header->code_size, debug);
715 for (i = 0; i < minfo->jit->line_numbers->len; i++) {
716 MonoDebugLineNumberEntry lne = g_array_index (
717 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
719 g_message (G_STRLOC ": %x,%x,%d", lne.address, lne.offset, lne.line);
724 static AssemblyDebugInfo *
725 mono_debug_get_image (MonoDebugHandle* debug, MonoImage *image)
727 return g_hash_table_lookup (debug->images, image);
730 static AssemblyDebugInfo *
731 mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
733 AssemblyDebugInfo *info;
736 info = mono_debug_get_image (debug, image);
742 info = g_new0 (AssemblyDebugInfo, 1);
744 info->image->ref_count++;
745 info->name = g_strdup (image->assembly_name);
746 info->format = debug->format;
747 info->handle = debug;
748 info->methods = g_hash_table_new_full (g_direct_hash, g_direct_equal,
749 NULL, (GDestroyNotify) free_method_info);
751 info->source_file = debug->source_files->len;
752 g_ptr_array_add (debug->source_files, g_strdup_printf ("%s.il", image->assembly_name));
754 g_hash_table_insert (debug->images, image, info);
756 info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
757 info->mlines = g_new0 (int, info->nmethods);
759 for (ptr = image->references; ptr && *ptr; ptr++)
760 mono_debug_add_assembly (*ptr, NULL);
762 switch (info->format) {
763 case MONO_DEBUG_FORMAT_STABS:
764 case MONO_DEBUG_FORMAT_DWARF2:
765 if (debug->flags & MONO_DEBUG_FLAGS_INSTALL_IL_FILES) {
766 gchar *dirname = g_path_get_dirname (image->name);
767 info->ilfile = g_strdup_printf ("%s/%s.il", dirname, info->name);
770 info->ilfile = g_strdup_printf ("%s.il", info->name);
772 case MONO_DEBUG_FORMAT_MONO:
773 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
774 info->filename = replace_suffix (image->name, "dbg");
775 if (g_file_test (info->filename, G_FILE_TEST_EXISTS))
776 info->symfile = mono_debug_open_mono_symbol_file (info->image, info->filename, TRUE);
777 else if (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER)
778 info->symfile = mono_debug_create_mono_symbol_file (info->image);
779 debugger_symbol_file_table_generation++;
786 if ((debug->format != MONO_DEBUG_FORMAT_MONO) && (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
787 debug_load_method_lines (info);
793 mono_debug_write_symbols (MonoDebugHandle *debug)
795 if (!debug || !debug->dirty)
798 release_symbol_file_table ();
800 switch (debug->format) {
801 case MONO_DEBUG_FORMAT_STABS:
802 mono_debug_write_stabs (debug);
804 case MONO_DEBUG_FORMAT_DWARF2:
805 mono_debug_write_dwarf2 (debug);
807 case MONO_DEBUG_FORMAT_MONO:
808 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
811 g_assert_not_reached ();
814 debug->dirty = FALSE;
818 mono_debug_make_symbols (void)
820 if (!mono_debug_handle || !mono_debug_handle->dirty)
823 switch (mono_debug_handle->format) {
824 case MONO_DEBUG_FORMAT_STABS:
825 mono_debug_write_stabs (mono_debug_handle);
827 case MONO_DEBUG_FORMAT_DWARF2:
828 mono_debug_write_dwarf2 (mono_debug_handle);
830 case MONO_DEBUG_FORMAT_MONO:
831 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
832 debugger_update_symbol_file_table ();
835 g_assert_not_reached ();
838 mono_debug_handle->dirty = FALSE;
842 mono_debug_close_assembly (AssemblyDebugInfo* info)
844 switch (info->format) {
845 case MONO_DEBUG_FORMAT_MONO:
846 case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
847 if (info->symfile != NULL)
848 mono_debug_close_mono_symbol_file (info->symfile);
853 g_hash_table_destroy (info->methods);
854 g_free (info->mlines);
855 g_free (info->moffsets);
857 g_free (info->ilfile);
858 g_free (info->filename);
859 g_free (info->objfile);
864 mono_debug_cleanup (void)
866 release_symbol_file_table ();
868 if (!mono_debug_handle)
871 if (mono_debug_handle->flags & MONO_DEBUG_FLAGS_UPDATE_ON_EXIT)
872 mono_debug_write_symbols (mono_debug_handle);
874 g_hash_table_destroy (mono_debug_handle->images);
875 g_ptr_array_free (mono_debug_handle->source_files, TRUE);
876 g_hash_table_destroy (mono_debug_handle->type_hash);
877 g_free (mono_debug_handle->producer_name);
878 g_free (mono_debug_handle->name);
879 g_free (mono_debug_handle);
881 mono_debug_handle = NULL;
885 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
889 mono_class_init (klass);
891 index = GPOINTER_TO_INT (g_hash_table_lookup (debug->type_hash, klass));
897 index = ++debug->next_klass_idx;
898 g_hash_table_insert (debug->type_hash, klass, GINT_TO_POINTER (index));
903 switch (klass->byval_arg.type) {
904 case MONO_TYPE_CLASS:
906 mono_debug_get_type (debug, klass->parent);
908 for (i = 0; i < klass->method.count; i++) {
909 MonoMethod *method = klass->methods [i];
910 MonoType *ret_type = NULL;
913 if (method->signature->ret->type != MONO_TYPE_VOID)
914 ret_type = method->signature->ret;
917 MonoClass *ret_klass = mono_class_from_mono_type (ret_type);
918 mono_debug_get_type (debug, ret_klass);
921 for (j = 0; j < method->signature->param_count; j++) {
922 MonoType *sub_type = method->signature->params [j];
923 MonoClass *sub_klass = mono_class_from_mono_type (sub_type);
924 mono_debug_get_type (debug, sub_klass);
928 case MONO_TYPE_VALUETYPE:
929 for (i = 0; i < klass->field.count; i++) {
930 MonoClass *subclass = mono_class_from_mono_type (klass->fields [i].type);
931 mono_debug_get_type (debug, subclass);
934 case MONO_TYPE_ARRAY:
935 case MONO_TYPE_SZARRAY:
936 mono_debug_get_type (debug, klass->element_class);
946 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
950 if (!minfo->jit || !minfo->jit->line_numbers)
953 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
954 MonoDebugLineNumberEntry lne = g_array_index (
955 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
957 if (lne.address <= address)
965 address_from_il_offset (MonoDebugMethodInfo *minfo, guint32 il_offset)
969 if (!minfo->jit || !minfo->jit->line_numbers)
972 for (i = minfo->jit->line_numbers->len - 1; i >= 0; i--) {
973 MonoDebugLineNumberEntry lne = g_array_index (
974 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
976 if (lne.offset <= il_offset)
984 mono_debug_add_type (MonoClass *klass)
986 AssemblyDebugInfo* info;
988 if (!mono_debug_handle)
991 info = mono_debug_get_image (mono_debug_handle, klass->image);
994 if ((mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO) &&
995 (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
999 mono_debugger_lock ();
1000 mono_debug_symfile_add_type (info->symfile, klass);
1001 mono_debugger_signal (TRUE);
1002 mono_debugger_unlock ();
1007 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
1012 if (pos->abs_pos == 0)
1015 if (pos->pos.bid >= cfg->block_count)
1018 bblock = &cfg->bblocks [pos->pos.bid];
1019 if (pos->pos.tid >= bblock->forest->len)
1022 tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
1024 return tree->cli_addr;
1027 struct LookupMethodData
1029 MonoDebugMethodInfo *minfo;
1034 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
1036 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1037 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
1043 data->minfo = mono_debug_find_method (info->symfile, data->method);
1045 data->minfo = g_hash_table_lookup (info->methods, data->method);
1048 static MonoDebugMethodInfo *
1049 lookup_method (MonoMethod *method)
1051 struct LookupMethodData data = { NULL, method };
1053 if (!mono_debug_handle)
1056 g_hash_table_foreach (mono_debug_handle->images, lookup_method_func, &data);
1061 mono_debug_add_method (MonoFlowGraph *cfg)
1063 MonoMethod *method = cfg->method;
1064 MonoClass *klass = method->klass;
1065 AssemblyDebugInfo* info;
1066 MonoDebugMethodJitInfo *jit;
1067 MonoDebugMethodInfo *minfo;
1070 if (!mono_debug_handle)
1073 mono_class_init (klass);
1075 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
1076 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
1077 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
1078 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
1081 if (method->wrapper_type != MONO_WRAPPER_NONE)
1084 info = mono_debug_get_image (mono_debug_handle, klass->image);
1087 minfo = lookup_method (method);
1088 if (!minfo || minfo->jit)
1091 mono_debugger_lock ();
1093 mono_debug_handle->dirty = TRUE;
1095 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
1096 jit->code_start = cfg->start;
1097 jit->code_size = cfg->epilogue_end;
1098 jit->prologue_end = cfg->prologue_end;
1099 jit->epilogue_begin = cfg->epilog;
1100 jit->num_params = method->signature->param_count;
1101 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
1103 if (method->signature->hasthis) {
1104 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
1106 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
1107 jit->this_var->offset = ptr->offset;
1108 jit->this_var->size = ptr->size;
1111 for (i = 0; i < jit->num_params; i++) {
1112 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
1113 method->signature->hasthis;
1115 jit->params [i].offset = ptr [i].offset;
1116 jit->params [i].size = ptr [i].size;
1119 debug_generate_method_lines (info, minfo, cfg);
1120 if ((info->format == MONO_DEBUG_FORMAT_MONO) || (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1121 debug_update_il_offsets (info, minfo, cfg);
1123 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1124 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
1125 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
1126 MonoDebugVarInfo *locals;
1128 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
1129 for (i = 0; i < header->num_locals; i++) {
1130 gint32 begin_offset, end_offset;
1131 gint32 begin_scope, end_scope;
1133 if (ptr [i].reg >= 0) {
1134 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
1135 locals [i].offset = 0;
1137 locals [i].offset = ptr [i].offset;
1139 locals [i].size = ptr [i].size;
1141 begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
1142 end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
1143 if (end_offset >= 0)
1146 if (begin_offset >= 0)
1147 begin_scope = address_from_il_offset (minfo, begin_offset);
1150 if (end_offset >= 0)
1151 end_scope = address_from_il_offset (minfo, end_offset);
1155 if (begin_scope > 0)
1156 locals [i].begin_scope = begin_scope;
1158 locals [i].begin_scope = jit->prologue_end;
1160 locals [i].end_scope = end_scope;
1162 locals [i].end_scope = jit->epilogue_begin;
1165 jit->num_locals = header->num_locals;
1166 jit->locals = locals;
1169 if (info->symfile) {
1170 mono_debug_symfile_add_method (info->symfile, method);
1171 mono_debugger_signal (TRUE);
1174 mono_debugger_unlock ();
1178 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
1180 MonoDebugMethodInfo *minfo = lookup_method (method);
1185 if (minfo->symfile) {
1186 gint32 offset = il_offset_from_address (minfo, address);
1191 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
1198 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
1200 MonoDebugMethodInfo *minfo;
1205 minfo = lookup_method (method);
1206 if (!minfo || !minfo->il_offsets)
1209 return il_offset_from_address (minfo, address);
1213 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
1215 MonoDebugMethodInfo *minfo;
1220 minfo = lookup_method (method);
1221 if (!minfo || !minfo->il_offsets)
1224 return address_from_il_offset (minfo, il_offset);
1228 release_symbol_file_table ()
1230 MonoDebuggerSymbolFileTable *temp;
1232 if (!debugger_symbol_file_table)
1236 * Caution: The debugger may access the memory pointed to by this variable
1237 * at any time. It is very important to set the pointer to NULL
1238 * before freeing the area.
1241 temp = debugger_symbol_file_table;
1242 debugger_symbol_file_table = NULL;
1243 g_free (debugger_symbol_file_table);
1247 update_symbol_file_table_count_func (gpointer key, gpointer value, gpointer user_data)
1249 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1253 if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1256 ++ (* (int *) user_data);
1259 struct SymfileTableData
1261 MonoDebuggerSymbolFileTable *symfile_table;
1266 update_symbol_file_table_func (gpointer key, gpointer value, gpointer user_data)
1268 AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1269 struct SymfileTableData *data = (struct SymfileTableData *) user_data;
1273 if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1276 data->symfile_table->symfiles [data->index++] = info->symfile;
1280 debugger_update_symbol_file_table_internal (void)
1283 MonoDebuggerSymbolFileTable *symfile_table;
1284 struct SymfileTableData data;
1287 if (!mono_debug_handle)
1290 mono_debugger_lock ();
1292 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_count_func, &count);
1294 release_symbol_file_table ();
1296 size = sizeof (MonoDebuggerSymbolFileTable) + count * sizeof (MonoSymbolFile *);
1297 symfile_table = g_malloc0 (size);
1298 symfile_table->magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
1299 symfile_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
1300 symfile_table->total_size = size;
1301 symfile_table->count = count;
1302 symfile_table->generation = debugger_symbol_file_table_generation;
1303 symfile_table->global_symfile = mono_debugger_global_symbol_file;
1305 data.symfile_table = symfile_table;
1308 g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_func, &data);
1310 debugger_symbol_file_table = symfile_table;
1312 mono_debugger_unlock ();
1318 debugger_update_symbol_file_table (void)
1322 if (!mono_debug_handle)
1325 mono_debugger_lock ();
1326 retval = debugger_update_symbol_file_table_internal ();
1327 mono_debugger_unlock ();
1332 static gboolean has_mono_debugger_support = FALSE;
1335 * NOTE: We must not call any functions here which we ever may want to debug !
1338 debugger_thread_func (gpointer ptr)
1340 void (*notification_code) (void) = ptr;
1341 int last_generation = 0;
1344 * Lock the mutex and raise a SIGSTOP to give the debugger a chance to
1345 * attach to us. This is important since the `notification_code' contains a
1346 * breakpoint instruction which would otherwise be deadly for us.
1348 g_mutex_lock (debugger_thread_mutex);
1352 * Ok, we're now running in the debugger - signal the parent thread that
1353 * we're ready and enter the event loop.
1355 g_mutex_lock (debugger_start_mutex);
1356 g_cond_signal (debugger_start_cond);
1357 g_mutex_unlock (debugger_start_mutex);
1360 /* Wait for an event. */
1361 g_cond_wait (debugger_thread_cond, debugger_thread_mutex);
1363 /* Reload the symbol file table if necessary. */
1364 if (debugger_symbol_file_table_generation > last_generation) {
1365 debugger_update_symbol_file_table_internal ();
1366 last_generation = debugger_symbol_file_table_generation;
1370 * Send notification - we'll stop on a breakpoint instruction at a special
1371 * address. The debugger will reload the symbol tables while we're stopped -
1372 * and owning the `debugger_thread_mutex' so that no other thread can touch
1373 * them in the meantime.
1375 notification_code ();
1377 /* Clear modified and signalled flag. */
1378 debugger_symbol_file_table_modified = FALSE;
1379 debugger_signalled = FALSE;
1381 if (must_send_finished) {
1382 g_mutex_lock (debugger_finished_mutex);
1383 g_cond_signal (debugger_finished_cond);
1384 must_send_finished = FALSE;
1385 g_mutex_unlock (debugger_finished_mutex);
1393 initialize_debugger_support ()
1398 if (has_mono_debugger_support)
1400 debugger_init_threads ();
1401 has_mono_debugger_support = TRUE;
1403 ptr = buf = g_malloc0 (16);
1404 x86_breakpoint (buf);
1405 debugger_notification_address = buf;
1408 g_mutex_lock (debugger_start_mutex);
1411 * This mutex is only unlocked by the g_cond_wait() in
1412 * mono_debugger_wait().
1414 g_mutex_lock (debugger_finished_mutex);
1416 thread = g_thread_create (debugger_thread_func, ptr, FALSE, NULL);
1420 * Wait until the debugger thread has actually been started and the
1421 * debugger attached to it.
1423 g_cond_wait (debugger_start_cond, debugger_start_mutex);
1426 * We keep this mutex until mono_debugger_jit_exec().
1428 g_static_rec_mutex_lock (&debugger_lock_mutex);
1431 static GPtrArray *breakpoints = NULL;
1434 mono_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
1436 static int last_breakpoint_id = 0;
1437 MonoDebuggerBreakpointInfo *info;
1439 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1441 info->use_trampoline = use_trampoline;
1442 info->index = ++last_breakpoint_id;
1445 breakpoints = g_ptr_array_new ();
1447 g_ptr_array_add (breakpoints, info);
1453 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
1455 MonoMethodDesc *desc;
1457 desc = mono_method_desc_new (string_argument, FALSE);
1461 return mono_insert_breakpoint_full (desc, TRUE);
1465 debugger_remove_breakpoint (guint64 breakpoint)
1472 for (i = 0; i < breakpoints->len; i++) {
1473 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1475 if (info->index != breakpoint)
1478 mono_method_desc_free (info->desc);
1479 g_ptr_array_remove (breakpoints, info);
1488 debugger_compile_method (MonoMethod *method)
1492 mono_debugger_lock ();
1493 retval = mono_compile_method (method);
1494 mono_debugger_signal (FALSE);
1495 mono_debugger_unlock ();
1500 mono_remove_breakpoint (int breakpoint_id)
1502 return debugger_remove_breakpoint (breakpoint_id);
1506 mono_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1508 MonoMethodDesc *desc;
1510 desc = mono_method_desc_new (method_name, include_namespace);
1514 return mono_insert_breakpoint_full (desc, has_mono_debugger_support);
1518 mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
1522 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1525 for (i = 0; i < breakpoints->len; i++) {
1526 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1528 if (info->use_trampoline != use_trampoline)
1531 if (!mono_method_desc_full_match (info->desc, method))
1541 mono_debugger_trampoline_breakpoint_callback (void)
1543 mono_debugger_lock ();
1544 must_send_finished = TRUE;
1545 mono_debugger_signal (FALSE);
1546 mono_debugger_unlock ();
1548 mono_debugger_wait ();
1552 * This is a custom version of mono_jit_exec() which is used when we're being run inside
1553 * the Mono Debugger.
1556 mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
1558 MonoImage *image = assembly->image;
1562 method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
1564 addr = mono_compile_method (method);
1567 * The mutex has been locked in initialize_debugger_support(); we keep it locked
1568 * until we compiled the main method and signalled the debugger.
1570 must_send_finished = TRUE;
1571 mono_debugger_signal (TRUE);
1572 mono_debugger_unlock ();
1575 * Wait until the debugger has loaded the initial symbol tables.
1577 mono_debugger_wait ();
1579 return mono_runtime_run_main (method, argc, argv, NULL);