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