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