2003-01-14 Martin Baulig <martin@ximian.com>
[mono.git] / mono / jit / debug.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <signal.h>
5 #include <sys/stat.h>
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>
14
15 #include "debug-private.h"
16 #include "helpers.h"
17
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().
21  */
22 static guint32 debugger_symbol_file_table_generation = 0;
23 static guint32 debugger_symbol_file_table_modified = 0;
24
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.
28  */
29 static MonoDebuggerSymbolFileTable *debugger_symbol_file_table = NULL;
30
31 /* Caution: This function MUST be called before touching the symbol table! */
32 static void release_symbol_file_table (void);
33
34 static void initialize_debugger_support (void);
35
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;
47
48 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
49
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);
55
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);
59
60 /*
61  * This is a global data symbol which is read by the debugger.
62  */
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,
76         &mono_runtime_invoke
77 };
78
79 static void
80 debugger_init_threads (void)
81 {
82         g_thread_init (NULL);
83
84         debugger_thread_cond = g_cond_new ();
85         debugger_finished_cond = g_cond_new ();
86         debugger_start_cond = g_cond_new ();
87
88         debugger_thread_mutex = g_mutex_new ();
89         debugger_finished_mutex = g_mutex_new ();
90         debugger_start_mutex = g_mutex_new ();
91 }
92
93 static void
94 mono_debugger_lock (void)
95 {
96         g_static_rec_mutex_lock (&debugger_lock_mutex);
97 }
98
99 static void
100 mono_debugger_unlock (void)
101 {
102         g_static_rec_mutex_unlock (&debugger_lock_mutex);
103 }
104
105 static void
106 mono_debugger_signal (gboolean modified)
107 {
108         if (modified)
109                 debugger_symbol_file_table_modified = TRUE;
110         if (!debugger_signalled) {
111                 debugger_signalled = TRUE;
112                 g_cond_signal (debugger_thread_cond);
113         }
114 }
115
116 static void
117 mono_debugger_wait (void)
118 {
119         g_cond_wait (debugger_finished_cond, debugger_finished_mutex);
120 }
121
122 static void
123 free_method_info (MonoDebugMethodInfo *minfo)
124 {
125         DebugMethodInfo *priv = minfo->user_data;
126
127         if (priv) {
128                 g_free (priv->name);
129                 g_free (priv);
130         }
131
132         if (minfo->jit) {
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);
137                 g_free (minfo->jit);
138         }
139
140         g_free (minfo->il_offsets);
141         g_free (minfo);
142 }
143
144 static void
145 debug_arg_warning (const char *message)
146 {
147         g_warning ("Error while processing --debug-args arguments: %s", message);
148 }
149
150 static gchar *
151 replace_suffix (const char *filename, const char *new_suffix)
152 {
153         const char *pos = strrchr (filename, '.');
154
155         if (!pos)
156                 return g_strdup_printf ("%s.%s", filename, new_suffix);
157         else {
158                 int len = pos - filename;
159                 gchar *retval = g_malloc0 (len + strlen (new_suffix) + 2);
160                 memcpy (retval, filename, len);
161                 retval [len] = '.';
162                 memcpy (retval + len + 1, new_suffix, strlen (new_suffix) + 1);
163                 return retval;
164         }
165 }
166
167 MonoDebugHandle*
168 mono_debug_open (MonoAssembly *assembly, MonoDebugFormat format, const char **args)
169 {
170         MonoDebugHandle *debug;
171         const char **ptr;
172
173         g_assert (!mono_debug_handle);
174
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;
180         debug->dirty = TRUE;
181
182         debug->type_hash = g_hash_table_new (NULL, NULL);
183         debug->source_files = g_ptr_array_new ();
184
185         debug->images = g_hash_table_new_full (NULL, NULL, NULL,
186                                                (GDestroyNotify) mono_debug_close_assembly);
187
188         for (ptr = args; ptr && *ptr; ptr++) {
189                 const char *arg = *ptr;
190                 gchar *message;
191
192                 switch (debug->format) {
193                 case MONO_DEBUG_FORMAT_STABS:
194                 case MONO_DEBUG_FORMAT_DWARF2:
195                         if (!strncmp (arg, "filename=", 9)) {
196                                 if (debug->filename)
197                                         debug_arg_warning ("The `filename' argument can be given only once.");
198                                 debug->filename = g_strdup (arg + 9);
199                                 continue;
200                         } else if (!strncmp (arg, "objfile=", 8)) {
201                                 if (debug->objfile)
202                                         debug_arg_warning ("The `objfile' argument can be given only once.");
203                                 debug->objfile = g_strdup (arg + 8);
204                                 continue;
205                         }
206                         break;
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;
211                         break;
212                 default:
213                         break;
214                 }
215
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;
220                                 continue;
221                         } else if (!strcmp (arg, "update_on_exit")) {
222                                 debug->flags |= MONO_DEBUG_FLAGS_UPDATE_ON_EXIT;
223                                 continue;
224                         } else if (!strcmp (arg, "install_il_files")) {
225                                 debug->flags |= MONO_DEBUG_FLAGS_INSTALL_IL_FILES;
226                                 continue;
227                         } else if (!strcmp (arg, "dont_update_il_files")) {
228                                 debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES;
229                                 continue;
230                         } else if (!strcmp (arg, "dont_create_il_files")) {
231                                 debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
232                                 continue;
233                         }
234                 }
235
236                 message = g_strdup_printf ("Unknown argument `%s'.", arg);
237                 debug_arg_warning (message);
238                 g_free (message);
239         }
240
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));
245                 if (!debug->objfile)
246                         debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
247                 break;
248         case MONO_DEBUG_FORMAT_DWARF2:
249                 if (!debug->filename)
250                         debug->filename = g_strdup_printf ("%s-dwarf.s", g_basename (debug->name));
251                 if (!debug->objfile)
252                         debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
253                 break;
254         case MONO_DEBUG_FORMAT_MONO:
255                 mono_debugger_class_init_func = mono_debug_add_type;
256                 break;
257         case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
258                 mono_debugger_class_init_func = mono_debug_add_type;
259                 initialize_debugger_support ();
260                 break;
261         default:
262                 g_assert_not_reached ();
263         }
264
265         mono_debugger_lock ();
266         release_symbol_file_table ();
267
268         mono_debug_handle = debug;
269         mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
270
271         mono_debug_open_image (mono_debug_handle, assembly->image);
272         mono_debug_open_image (mono_debug_handle, mono_defaults.corlib);
273
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);
317
318         debugger_update_symbol_file_table ();
319
320         mono_debugger_unlock ();
321
322         return debug;
323 }
324
325 static void
326 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
327 {
328         if (!mono_debug_handle)
329                 return;
330
331         mono_debugger_lock ();
332         mono_debug_open_image (mono_debug_handle, assembly->image);
333         mono_debugger_unlock ();
334 }
335
336 static void
337 generate_il_offsets (AssemblyDebugInfo *info, MonoMethod *method)
338 {
339         GPtrArray *il_offsets = g_ptr_array_new ();
340         MonoClass *klass = method->klass;
341         MonoDebugMethodInfo *minfo;
342         DebugMethodInfo *priv;
343         int i;
344
345         g_assert (klass->image == info->image);
346
347         /* FIXME: doesn't work yet. */
348         if (!strcmp (klass->name_space, "System.Runtime.Remoting.Proxies"))
349                 return;
350
351         mono_class_init (klass);
352
353         minfo = g_new0 (MonoDebugMethodInfo, 1);
354         minfo->method = method;
355         minfo->user_data = priv = g_new0 (DebugMethodInfo, 1);
356
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;
360         priv->info = info;
361
362         /*
363          * Find the method index in the image.
364          */
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];
369                         break;
370                 }
371         }
372
373         g_assert (priv->method_number);
374
375         /* info->moffsets contains -1 "outside" of functions. */
376         for (i = priv->first_line; (i > 0) && (info->moffsets [i] == 0); i--)
377                 ;
378         priv->start_line = i + 1;
379
380         for (i = priv->start_line; info->moffsets [i] != -1; i++) {
381                 MonoSymbolFileLineNumberEntry *lne = g_new0 (MonoSymbolFileLineNumberEntry, 1);
382
383                 if (!info->moffsets [i] && (i > priv->start_line))
384                         continue;
385
386                 lne->offset = info->moffsets [i];
387                 lne->row = i;
388
389                 g_ptr_array_add (il_offsets, lne);
390         }
391
392         priv->last_line = i;
393
394         minfo->start_line = priv->first_line;
395         minfo->end_line = priv->last_line;
396
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);
401
402                 minfo->il_offsets [i] = *il;
403         }
404
405         g_ptr_array_free (il_offsets, TRUE);
406
407         g_hash_table_insert (info->methods, method, minfo);
408 }
409
410 static void
411 debug_load_method_lines (AssemblyDebugInfo* info)
412 {
413         MonoTableInfo *table = &info->image->tables [MONO_TABLE_METHOD];
414         FILE *f;
415         char buf [1024];
416         int i, mnum, idx;
417         int offset = -1;
418
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;
424
425                 if (stat (info->image->name, &stata)) {
426                         g_warning ("cannot access assembly file (%s): %s",
427                                    info->image->name, g_strerror (errno));
428                         g_free (command);
429                         return;
430                 }
431
432                 /* If the stat() failed or the file is older. */
433                 if (stat (info->ilfile, &statb)) {
434                         need_update = TRUE;
435                 } else if (statb.st_mtime < stata.st_mtime)
436                         need_update = TRUE;
437
438                 if (need_update) {
439 #ifndef PLATFORM_WIN32
440                         struct sigaction act, oldact;
441                         sigset_t old_set;
442 #endif
443                         int ret;
444
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);
452 #endif
453                         
454                         g_print ("Recreating %s from %s.\n", info->ilfile, info->image->name);
455
456                         ret = system (command);
457
458 #ifndef PLATFORM_WIN32
459                         sigaction (SIGCHLD, &oldact, NULL);
460                         sigprocmask (SIG_SETMASK, &old_set, NULL);
461 #endif
462
463                         if (ret) {
464                                 g_warning ("cannot create IL assembly file (%s): %s",
465                                            command, g_strerror (errno));
466                                 g_free (command);
467                                 return;
468                         }
469                 }
470         }
471
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);
475                 return;
476         }
477
478         info->total_lines = 100;
479         info->moffsets = g_malloc (info->total_lines * sizeof (int));
480
481         i = 0;
482         while (fgets (buf, sizeof (buf), f)) {
483                 int pos = i;
484
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);
490                 }
491
492                 if (!sscanf (buf, " // method line %d", &mnum))
493                         continue;
494
495                 offset = 0;
496
497                 if (mnum >= info->nmethods)
498                         break;
499
500                 while (fgets (buf, sizeof (buf), f)) {
501                         int newoffset;
502
503                         ++i;
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);
508                         }
509
510                         if (strstr (buf, "}")) {
511                                 offset = -1;
512                                 break;
513                         }
514
515                         if (sscanf (buf, " IL_%x:", &newoffset)) {
516                                 offset = newoffset;
517                                 if (!offset)
518                                         pos = i;
519                         }
520
521                         info->moffsets [i] = offset;
522                 }
523                 /* g_print ("method %d found at %d\n", mnum, pos); */
524                 info->mlines [mnum] = pos;
525         }
526         fclose (f);
527
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);
531
532                 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
533                     (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
534                     (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
535                         continue;
536
537                 if (method->wrapper_type != MONO_WRAPPER_NONE)
538                         continue;
539
540                 generate_il_offsets (info, method);
541         }
542 }
543
544 static void
545 record_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, guint32 line)
546 {
547         MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
548
549         lne->address = address;
550         lne->offset = offset;
551         lne->line = line;
552
553         g_array_append_val (minfo->jit->line_numbers, *lne);
554 }
555
556 static void
557 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
558 {
559         guint32 st_address, st_line;
560         DebugMethodInfo *priv = minfo->user_data;
561         int i;
562
563         if (!priv || !info->moffsets)
564                 return;
565
566         minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
567
568         st_line = priv->first_line;
569         st_address = minfo->jit->prologue_end;
570
571         /* This is the first actual code line of the method. */
572         record_line_number (minfo, st_address, 0, st_line);
573
574         /* start lines of basic blocks */
575         for (i = 0; i < cfg->block_count; ++i) {
576                 int j;
577
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;
581
582                         if (!i && !j) {
583                                 st_line = priv->first_line;
584                                 st_address = t->addr;
585                         }
586
587                         addr_inc = t->addr - st_address;
588                         st_address += addr_inc;
589
590                         if (t->cli_addr != -1) {
591                                 int *lines = info->moffsets + st_line;
592                                 int *k = lines;
593
594                                 while ((*k != -1) && (*k < t->cli_addr))
595                                         k++;
596
597                                 line_inc = k - lines;
598                         }
599
600                         st_line += line_inc;
601
602                         if (t->cli_addr != -1)
603                                 record_line_number (minfo, st_address, t->cli_addr, st_line);
604                 }
605         }
606 }
607
608 static void
609 generate_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, int debug)
610 {
611         int i;
612
613         if (debug)
614                 g_message (G_STRLOC ": searching IL offset %x", offset);
615
616         for (i = minfo->num_il_offsets - 1; i >= 0; i--) {
617                 MonoDebugLineNumberEntry *lne;
618
619                 if (minfo->il_offsets [i].offset > offset)
620                         continue;
621
622                 if (debug)
623                         g_message (G_STRLOC ": found entry %d: offset = %x, row = %d",
624                                    i, minfo->il_offsets [i].offset, minfo->il_offsets [i].row);
625
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);
630
631                         /* Avoid writing more than one entry for the same line. */
632                         if (minfo->il_offsets [i].row == last.line) {
633                                 if (debug)
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);
639
640                                 return;
641                         }
642                 }
643
644                 if (debug)
645                         g_message (G_STRLOC ": writing entry: line = %d, offfset = %x, address = %x",
646                                    minfo->il_offsets [i].row, offset, address);
647
648                 lne = g_new0 (MonoDebugLineNumberEntry, 1);
649                 lne->address = address;
650                 lne->offset = offset;
651                 lne->line = minfo->il_offsets [i].row;
652
653                 g_array_append_val (minfo->jit->line_numbers, *lne);
654                 return;
655         }
656 }
657
658 static void
659 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
660 {
661         MonoMethodHeader *header;
662         guint32 address, offset;
663         int debug = 0;
664         int i;
665
666         g_assert (info->symfile);
667         if (info->symfile->is_dynamic)
668                 return;
669
670         g_assert (!minfo->jit->line_numbers);
671         minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
672
673         address = minfo->jit->prologue_end;
674         offset = 0;
675
676         g_assert (((MonoMethodNormal*)minfo->method)->header);
677         header = ((MonoMethodNormal*)minfo->method)->header;
678
679 #if 0
680         if (!strcmp (minfo->method->name, "Test") || !strcmp (minfo->method->name, "Main")) {
681                 MonoMethodHeader *header = ((MonoMethodNormal*)minfo->method)->header;
682
683                 debug = 1;
684                 mono_disassemble_code (minfo->jit->code_start, minfo->jit->code_size,
685                                        minfo->method->name);
686
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);
690         }
691 #endif
692
693         generate_line_number (minfo, address, offset, debug);
694
695         /* start lines of basic blocks */
696         for (i = 0; i < cfg->block_count; ++i) {
697                 int j;
698
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);
701
702                         if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
703                                 continue;
704
705                         offset = t->cli_addr;
706                         address = t->addr;
707
708                         generate_line_number (minfo, address, offset, debug);
709                 }
710         }
711
712         generate_line_number (minfo, minfo->jit->epilogue_begin, header->code_size, debug);
713
714         if (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);
718
719                         g_message (G_STRLOC ": %x,%x,%d", lne.address, lne.offset, lne.line);
720                 }
721         }
722 }
723
724 static AssemblyDebugInfo *
725 mono_debug_get_image (MonoDebugHandle* debug, MonoImage *image)
726 {
727         return g_hash_table_lookup (debug->images, image);
728 }
729
730 static AssemblyDebugInfo *
731 mono_debug_open_image (MonoDebugHandle* debug, MonoImage *image)
732 {
733         AssemblyDebugInfo *info;
734         MonoAssembly **ptr;
735
736         info = mono_debug_get_image (debug, image);
737         if (info != NULL)
738                 return info;
739
740         debug->dirty = TRUE;
741
742         info = g_new0 (AssemblyDebugInfo, 1);
743         info->image = image;
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);
750
751         info->source_file = debug->source_files->len;
752         g_ptr_array_add (debug->source_files, g_strdup_printf ("%s.il", image->assembly_name));
753
754         g_hash_table_insert (debug->images, image, info);
755
756         info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
757         info->mlines = g_new0 (int, info->nmethods);
758
759         for (ptr = image->references; ptr && *ptr; ptr++)
760                 mono_debug_add_assembly (*ptr, NULL);
761
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);
768                         g_free (dirname);
769                 } else
770                         info->ilfile = g_strdup_printf ("%s.il", info->name);
771                 break;
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++;
780                 break;
781
782         default:
783                 break;
784         }
785
786         if ((debug->format != MONO_DEBUG_FORMAT_MONO) && (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
787                 debug_load_method_lines (info);
788
789         return info;
790 }
791
792 void
793 mono_debug_write_symbols (MonoDebugHandle *debug)
794 {
795         if (!debug || !debug->dirty)
796                 return;
797
798         release_symbol_file_table ();
799         
800         switch (debug->format) {
801         case MONO_DEBUG_FORMAT_STABS:
802                 mono_debug_write_stabs (debug);
803                 break;
804         case MONO_DEBUG_FORMAT_DWARF2:
805                 mono_debug_write_dwarf2 (debug);
806                 break;
807         case MONO_DEBUG_FORMAT_MONO:
808         case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
809                 break;
810         default:
811                 g_assert_not_reached ();
812         }
813
814         debug->dirty = FALSE;
815 }
816
817 void
818 mono_debug_make_symbols (void)
819 {
820         if (!mono_debug_handle || !mono_debug_handle->dirty)
821                 return;
822         
823         switch (mono_debug_handle->format) {
824         case MONO_DEBUG_FORMAT_STABS:
825                 mono_debug_write_stabs (mono_debug_handle);
826                 break;
827         case MONO_DEBUG_FORMAT_DWARF2:
828                 mono_debug_write_dwarf2 (mono_debug_handle);
829                 break;
830         case MONO_DEBUG_FORMAT_MONO:
831         case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
832                 debugger_update_symbol_file_table ();
833                 break;
834         default:
835                 g_assert_not_reached ();
836         }
837
838         mono_debug_handle->dirty = FALSE;
839 }
840
841 static void
842 mono_debug_close_assembly (AssemblyDebugInfo* info)
843 {
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);
849                 break;
850         default:
851                 break;
852         }
853         g_hash_table_destroy (info->methods);
854         g_free (info->mlines);
855         g_free (info->moffsets);
856         g_free (info->name);
857         g_free (info->ilfile);
858         g_free (info->filename);
859         g_free (info->objfile);
860         g_free (info);
861 }
862
863 void
864 mono_debug_cleanup (void)
865 {
866         release_symbol_file_table ();
867
868         if (!mono_debug_handle)
869                 return;
870
871         if (mono_debug_handle->flags & MONO_DEBUG_FLAGS_UPDATE_ON_EXIT)
872                 mono_debug_write_symbols (mono_debug_handle);
873
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);
880
881         mono_debug_handle = NULL;
882 }
883
884 guint32
885 mono_debug_get_type (MonoDebugHandle *debug, MonoClass *klass)
886 {
887         guint index, i;
888
889         mono_class_init (klass);
890
891         index = GPOINTER_TO_INT (g_hash_table_lookup (debug->type_hash, klass));
892         if (index)
893                 return index;
894
895         debug->dirty = TRUE;
896
897         index = ++debug->next_klass_idx;
898         g_hash_table_insert (debug->type_hash, klass, GINT_TO_POINTER (index));
899
900         if (klass->enumtype)
901                 return index;
902
903         switch (klass->byval_arg.type) {
904         case MONO_TYPE_CLASS:
905                 if (klass->parent)
906                         mono_debug_get_type (debug, klass->parent);
907
908                 for (i = 0; i < klass->method.count; i++) {
909                         MonoMethod *method = klass->methods [i];
910                         MonoType *ret_type = NULL;
911                         int j;
912
913                         if (method->signature->ret->type != MONO_TYPE_VOID)
914                                 ret_type = method->signature->ret;
915
916                         if (ret_type) {
917                                 MonoClass *ret_klass = mono_class_from_mono_type (ret_type);
918                                 mono_debug_get_type (debug, ret_klass);
919                         }
920
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);
925                         }
926                 }
927                 // fall through
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);
932                 }
933                 break;
934         case MONO_TYPE_ARRAY:
935         case MONO_TYPE_SZARRAY:
936                 mono_debug_get_type (debug, klass->element_class);
937                 break;
938         default:
939                 break;
940         }
941
942         return index;
943 }
944
945 static gint32
946 il_offset_from_address (MonoDebugMethodInfo *minfo, guint32 address)
947 {
948         int i;
949
950         if (!minfo->jit || !minfo->jit->line_numbers)
951                 return -1;
952
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);
956
957                 if (lne.address <= address)
958                         return lne.offset;
959         }
960
961         return -1;
962 }
963
964 static gint32
965 address_from_il_offset (MonoDebugMethodInfo *minfo, guint32 il_offset)
966 {
967         int i;
968
969         if (!minfo->jit || !minfo->jit->line_numbers)
970                 return -1;
971
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);
975
976                 if (lne.offset <= il_offset)
977                         return lne.address;
978         }
979
980         return -1;
981 }
982
983 void
984 mono_debug_add_type (MonoClass *klass)
985 {
986         AssemblyDebugInfo* info;
987
988         if (!mono_debug_handle)
989                 return;
990
991         info = mono_debug_get_image (mono_debug_handle, klass->image);
992         g_assert (info);
993
994         if ((mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO) &&
995             (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
996                 return;
997
998         if (info->symfile) {
999                 mono_debugger_lock ();
1000                 mono_debug_symfile_add_type (info->symfile, klass);
1001                 mono_debugger_signal (TRUE);
1002                 mono_debugger_unlock ();
1003         }
1004 }
1005
1006 static gint32
1007 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
1008 {
1009         MonoBBlock *bblock;
1010         MBTree *tree;
1011
1012         if (pos->abs_pos == 0)
1013                 return -1;
1014
1015         if (pos->pos.bid >= cfg->block_count)
1016                 return -1;
1017
1018         bblock = &cfg->bblocks [pos->pos.bid];
1019         if (pos->pos.tid >= bblock->forest->len)
1020                 return -1;
1021
1022         tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
1023
1024         return tree->cli_addr;
1025 }
1026
1027 struct LookupMethodData
1028 {
1029         MonoDebugMethodInfo *minfo;
1030         MonoMethod *method;
1031 };
1032
1033 static void
1034 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
1035 {
1036         AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1037         struct LookupMethodData *data = (struct LookupMethodData *) user_data;
1038
1039         if (data->minfo)
1040                 return;
1041
1042         if (info->symfile)
1043                 data->minfo = mono_debug_find_method (info->symfile, data->method);
1044         else
1045                 data->minfo = g_hash_table_lookup (info->methods, data->method);
1046 }
1047
1048 static MonoDebugMethodInfo *
1049 lookup_method (MonoMethod *method)
1050 {
1051         struct LookupMethodData data = { NULL, method };
1052
1053         if (!mono_debug_handle)
1054                 return NULL;
1055
1056         g_hash_table_foreach (mono_debug_handle->images, lookup_method_func, &data);
1057         return data.minfo;
1058 }
1059
1060 void
1061 mono_debug_add_method (MonoFlowGraph *cfg)
1062 {
1063         MonoMethod *method = cfg->method;
1064         MonoClass *klass = method->klass;
1065         AssemblyDebugInfo* info;
1066         MonoDebugMethodJitInfo *jit;
1067         MonoDebugMethodInfo *minfo;
1068         int i;
1069
1070         if (!mono_debug_handle)
1071                 return;
1072
1073         mono_class_init (klass);
1074
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))
1079                 return;
1080
1081         if (method->wrapper_type != MONO_WRAPPER_NONE)
1082                 return;
1083
1084         info = mono_debug_get_image (mono_debug_handle, klass->image);
1085         g_assert (info);
1086
1087         minfo = lookup_method (method);
1088         if (!minfo || minfo->jit)
1089                 return;
1090
1091         mono_debugger_lock ();
1092
1093         mono_debug_handle->dirty = TRUE;
1094
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);
1102
1103         if (method->signature->hasthis) {
1104                 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
1105
1106                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
1107                 jit->this_var->offset = ptr->offset;
1108                 jit->this_var->size = ptr->size;
1109         }
1110
1111         for (i = 0; i < jit->num_params; i++) {
1112                 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
1113                         method->signature->hasthis;
1114
1115                 jit->params [i].offset = ptr [i].offset;
1116                 jit->params [i].size = ptr [i].size;
1117         }
1118
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);
1122
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;
1127
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;
1132
1133                         if (ptr [i].reg >= 0) {
1134                                 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
1135                                 locals [i].offset = 0;
1136                         } else
1137                                 locals [i].offset = ptr [i].offset;
1138
1139                         locals [i].size = ptr [i].size;
1140
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)
1144                                 end_offset++;
1145
1146                         if (begin_offset >= 0)
1147                                 begin_scope = address_from_il_offset (minfo, begin_offset);
1148                         else
1149                                 begin_scope = -1;
1150                         if (end_offset >= 0)
1151                                 end_scope = address_from_il_offset (minfo, end_offset);
1152                         else
1153                                 end_scope = -1;
1154
1155                         if (begin_scope > 0)
1156                                 locals [i].begin_scope = begin_scope;
1157                         else
1158                                 locals [i].begin_scope = jit->prologue_end;
1159                         if (end_scope > 0)
1160                                 locals [i].end_scope = end_scope;
1161                         else
1162                                 locals [i].end_scope = jit->epilogue_begin;
1163                 }
1164
1165                 jit->num_locals = header->num_locals;
1166                 jit->locals = locals;
1167         }
1168
1169         if (info->symfile) {
1170                 mono_debug_symfile_add_method (info->symfile, method);
1171                 mono_debugger_signal (TRUE);
1172         }
1173
1174         mono_debugger_unlock ();
1175 }
1176
1177 gchar *
1178 mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number)
1179 {
1180         MonoDebugMethodInfo *minfo = lookup_method (method);
1181
1182         if (!minfo)
1183                 return NULL;
1184
1185         if (minfo->symfile) {
1186                 gint32 offset = il_offset_from_address (minfo, address);
1187                 
1188                 if (offset < 0)
1189                         return NULL;
1190
1191                 return mono_debug_find_source_location (minfo->symfile, method, offset, line_number);
1192         }
1193
1194         return NULL;
1195 }
1196
1197 gint32
1198 mono_debug_il_offset_from_address (MonoMethod *method, gint32 address)
1199 {
1200         MonoDebugMethodInfo *minfo;
1201
1202         if (address < 0)
1203                 return -1;
1204
1205         minfo = lookup_method (method);
1206         if (!minfo || !minfo->il_offsets)
1207                 return -1;
1208
1209         return il_offset_from_address (minfo, address);
1210 }
1211
1212 gint32
1213 mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset)
1214 {
1215         MonoDebugMethodInfo *minfo;
1216
1217         if (il_offset < 0)
1218                 return -1;
1219
1220         minfo = lookup_method (method);
1221         if (!minfo || !minfo->il_offsets)
1222                 return -1;
1223
1224         return address_from_il_offset (minfo, il_offset);
1225 }
1226
1227 static void
1228 release_symbol_file_table ()
1229 {
1230         MonoDebuggerSymbolFileTable *temp;
1231
1232         if (!debugger_symbol_file_table)
1233                 return;
1234
1235         /*
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.
1239          */
1240
1241         temp = debugger_symbol_file_table;
1242         debugger_symbol_file_table = NULL;
1243         g_free (debugger_symbol_file_table);
1244 }
1245
1246 static void
1247 update_symbol_file_table_count_func (gpointer key, gpointer value, gpointer user_data)
1248 {
1249         AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1250
1251         if (!info->symfile)
1252                 return;
1253         if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1254                 return;
1255
1256         ++ (* (int *) user_data);
1257 }
1258
1259 struct SymfileTableData
1260 {
1261         MonoDebuggerSymbolFileTable *symfile_table;
1262         int index;
1263 };
1264
1265 static void
1266 update_symbol_file_table_func (gpointer key, gpointer value, gpointer user_data)
1267 {
1268         AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
1269         struct SymfileTableData *data = (struct SymfileTableData *) user_data;
1270
1271         if (!info->symfile)
1272                 return;
1273         if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
1274                 return;
1275
1276         data->symfile_table->symfiles [data->index++] = info->symfile;
1277 }
1278
1279 static int
1280 debugger_update_symbol_file_table_internal (void)
1281 {
1282         int count = 0;
1283         MonoDebuggerSymbolFileTable *symfile_table;
1284         struct SymfileTableData data;
1285         guint32 size;
1286
1287         if (!mono_debug_handle)
1288                 return FALSE;
1289
1290         mono_debugger_lock ();
1291
1292         g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_count_func, &count);
1293
1294         release_symbol_file_table ();
1295
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;
1304
1305         data.symfile_table = symfile_table;
1306         data.index = 0;
1307
1308         g_hash_table_foreach (mono_debug_handle->images, update_symbol_file_table_func, &data);
1309
1310         debugger_symbol_file_table = symfile_table;
1311
1312         mono_debugger_unlock ();
1313
1314         return TRUE;
1315 }
1316
1317 static int
1318 debugger_update_symbol_file_table (void)
1319 {
1320         int retval;
1321
1322         if (!mono_debug_handle)
1323                 return FALSE;
1324
1325         mono_debugger_lock ();
1326         retval = debugger_update_symbol_file_table_internal ();
1327         mono_debugger_unlock ();
1328
1329         return retval;
1330 }
1331
1332 static gboolean has_mono_debugger_support = FALSE;
1333
1334 /*
1335  * NOTE: We must not call any functions here which we ever may want to debug !
1336  */
1337 static gpointer
1338 debugger_thread_func (gpointer ptr)
1339 {
1340         void (*notification_code) (void) = ptr;
1341         int last_generation = 0;
1342
1343         /*
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.
1347          */
1348         g_mutex_lock (debugger_thread_mutex);
1349         raise (SIGSTOP);
1350
1351         /*
1352          * Ok, we're now running in the debugger - signal the parent thread that
1353          * we're ready and enter the event loop.
1354          */
1355         g_mutex_lock (debugger_start_mutex);
1356         g_cond_signal (debugger_start_cond);
1357         g_mutex_unlock (debugger_start_mutex);
1358
1359         while (TRUE) {
1360                 /* Wait for an event. */
1361                 g_cond_wait (debugger_thread_cond, debugger_thread_mutex);
1362
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;
1367                 }
1368
1369                 /*
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.
1374                  */
1375                 notification_code ();
1376
1377                 /* Clear modified and signalled flag. */
1378                 debugger_symbol_file_table_modified = FALSE;
1379                 debugger_signalled = FALSE;
1380
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);
1386                 }
1387         }
1388
1389         return NULL;
1390 }
1391
1392 static void
1393 initialize_debugger_support ()
1394 {
1395         guint8 *buf, *ptr;
1396         GThread *thread;
1397
1398         if (has_mono_debugger_support)
1399                 return;
1400         debugger_init_threads ();
1401         has_mono_debugger_support = TRUE;
1402
1403         ptr = buf = g_malloc0 (16);
1404         x86_breakpoint (buf);
1405         debugger_notification_address = buf;
1406         x86_ret (buf);
1407
1408         g_mutex_lock (debugger_start_mutex);
1409
1410         /*
1411          * This mutex is only unlocked by the g_cond_wait() in
1412          * mono_debugger_wait().
1413          */
1414         g_mutex_lock (debugger_finished_mutex);
1415
1416         thread = g_thread_create (debugger_thread_func, ptr, FALSE, NULL);
1417         g_assert (thread);
1418
1419         /*
1420          * Wait until the debugger thread has actually been started and the
1421          * debugger attached to it.
1422          */
1423         g_cond_wait (debugger_start_cond, debugger_start_mutex);
1424
1425         /*
1426          * We keep this mutex until mono_debugger_jit_exec().
1427          */
1428         g_static_rec_mutex_lock (&debugger_lock_mutex);
1429 }
1430
1431 static GPtrArray *breakpoints = NULL;
1432
1433 int
1434 mono_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
1435 {
1436         static int last_breakpoint_id = 0;
1437         MonoDebuggerBreakpointInfo *info;
1438
1439         info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1440         info->desc = desc;
1441         info->use_trampoline = use_trampoline;
1442         info->index = ++last_breakpoint_id;
1443
1444         if (!breakpoints)
1445                 breakpoints = g_ptr_array_new ();
1446
1447         g_ptr_array_add (breakpoints, info);
1448
1449         return info->index;
1450 }
1451
1452 static guint64
1453 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
1454 {
1455         MonoMethodDesc *desc;
1456
1457         desc = mono_method_desc_new (string_argument, FALSE);
1458         if (!desc)
1459                 return 0;
1460
1461         return mono_insert_breakpoint_full (desc, TRUE);
1462 }
1463
1464 static guint64
1465 debugger_remove_breakpoint (guint64 breakpoint)
1466 {
1467         int i;
1468
1469         if (!breakpoints)
1470                 return 0;
1471
1472         for (i = 0; i < breakpoints->len; i++) {
1473                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1474
1475                 if (info->index != breakpoint)
1476                         continue;
1477
1478                 mono_method_desc_free (info->desc);
1479                 g_ptr_array_remove (breakpoints, info);
1480                 g_free (info);
1481                 return 1;
1482         }
1483
1484         return 0;
1485 }
1486
1487 static gpointer
1488 debugger_compile_method (MonoMethod *method)
1489 {
1490         gpointer retval;
1491
1492         mono_debugger_lock ();
1493         retval = mono_compile_method (method);
1494         mono_debugger_signal (FALSE);
1495         mono_debugger_unlock ();
1496         return retval;
1497 }
1498
1499 int
1500 mono_remove_breakpoint (int breakpoint_id)
1501 {
1502         return debugger_remove_breakpoint (breakpoint_id);
1503 }
1504
1505 int
1506 mono_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1507 {
1508         MonoMethodDesc *desc;
1509
1510         desc = mono_method_desc_new (method_name, include_namespace);
1511         if (!desc)
1512                 return 0;
1513
1514         return mono_insert_breakpoint_full (desc, has_mono_debugger_support);
1515 }
1516
1517 int
1518 mono_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
1519 {
1520         int i;
1521
1522         if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1523                 return 0;
1524
1525         for (i = 0; i < breakpoints->len; i++) {
1526                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1527
1528                 if (info->use_trampoline != use_trampoline)
1529                         continue;
1530
1531                 if (!mono_method_desc_full_match (info->desc, method))
1532                         continue;
1533
1534                 return info->index;
1535         }
1536
1537         return 0;
1538 }
1539
1540 void
1541 mono_debugger_trampoline_breakpoint_callback (void)
1542 {
1543         mono_debugger_lock ();
1544         must_send_finished = TRUE;
1545         mono_debugger_signal (FALSE);
1546         mono_debugger_unlock ();
1547
1548         mono_debugger_wait ();
1549 }
1550
1551 /*
1552  * This is a custom version of mono_jit_exec() which is used when we're being run inside
1553  * the Mono Debugger.
1554  */
1555 int 
1556 mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
1557 {
1558         MonoImage *image = assembly->image;
1559         MonoMethod *method;
1560         gpointer addr;
1561
1562         method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
1563
1564         addr = mono_compile_method (method);
1565
1566         /*
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.
1569          */
1570         must_send_finished = TRUE;
1571         mono_debugger_signal (TRUE);
1572         mono_debugger_unlock ();
1573
1574         /*
1575          * Wait until the debugger has loaded the initial symbol tables.
1576          */
1577         mono_debugger_wait ();
1578
1579         return mono_runtime_run_main (method, argc, argv, NULL);
1580 }