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