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