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