Merge pull request #3981 from kumpera/fix_symbolification_issues
[mono.git] / mono / metadata / mono-debug.c
1 /*
2  * mono-debug.c: 
3  *
4  * Author:
5  *      Mono Project (http://www.mono-project.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12
13 #include <config.h>
14 #include <mono/metadata/assembly.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/appdomain.h>
18 #include <mono/metadata/class-internals.h>
19 #include <mono/metadata/mono-debug.h>
20 #include <mono/metadata/mono-debug-debugger.h>
21 #include <mono/metadata/mono-endian.h>
22 #include <mono/metadata/gc-internals.h>
23 #include <mono/metadata/mempool.h>
24 #include <mono/metadata/debug-mono-ppdb.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/runtime.h>
27 #include <string.h>
28
29 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
30
31 #if NO_UNALIGNED_ACCESS
32 #define WRITE_UNALIGNED(type, addr, val) \
33         memcpy(addr, &val, sizeof(type))
34 #define READ_UNALIGNED(type, addr, val) \
35         memcpy(&val, addr, sizeof(type))
36 #else
37 #define WRITE_UNALIGNED(type, addr, val) \
38         (*(type *)(addr) = (val))
39 #define READ_UNALIGNED(type, addr, val) \
40         val = (*(type *)(addr))
41 #endif
42
43 /* This contains per-domain info */
44 struct _MonoDebugDataTable {
45         MonoMemPool *mp;
46         GHashTable *method_address_hash;
47 };
48
49 /* This contains JIT debugging information about a method in serialized format */
50 struct _MonoDebugMethodAddress {
51         const guint8 *code_start;
52         guint32 code_size;
53         guint8 data [MONO_ZERO_LEN_ARRAY];
54 };
55
56 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
57
58 static gboolean mono_debug_initialized = FALSE;
59 /* Maps MonoImage -> MonoMonoDebugHandle */
60 static GHashTable *mono_debug_handles;
61 /* Maps MonoDomain -> MonoDataTable */
62 static GHashTable *data_table_hash;
63
64 static mono_mutex_t debugger_lock_mutex;
65
66 static gboolean is_attached = FALSE;
67
68 static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image, const guint8 *raw_contents, int size);
69
70 static MonoDebugHandle     *mono_debug_get_image      (MonoImage *image);
71 static void                 mono_debug_add_assembly    (MonoAssembly *assembly,
72                                                         gpointer user_data);
73
74 static MonoDebugHandle     *open_symfile_from_bundle   (MonoImage *image);
75
76 static MonoDebugDataTable *
77 create_data_table (MonoDomain *domain)
78 {
79         MonoDebugDataTable *table;
80
81         table = g_new0 (MonoDebugDataTable, 1);
82
83         table->mp = mono_mempool_new ();
84         table->method_address_hash = g_hash_table_new (NULL, NULL);
85
86         if (domain)
87                 g_hash_table_insert (data_table_hash, domain, table);
88
89         return table;
90 }
91
92 static void
93 free_data_table (MonoDebugDataTable *table)
94 {
95         mono_mempool_destroy (table->mp);
96         g_hash_table_destroy (table->method_address_hash);
97
98         g_free (table);
99 }
100
101 static MonoDebugDataTable *
102 lookup_data_table (MonoDomain *domain)
103 {
104         MonoDebugDataTable *table;
105
106         table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
107         if (!table) {
108                 g_error ("lookup_data_table () failed for %p\n", domain);
109                 g_assert (table);
110         }
111         return table;
112 }
113
114 static void
115 free_debug_handle (MonoDebugHandle *handle)
116 {
117         if (handle->ppdb)
118                 mono_ppdb_close (handle);
119         if (handle->symfile)
120                 mono_debug_close_mono_symbol_file (handle->symfile);
121         /* decrease the refcount added with mono_image_addref () */
122         mono_image_close (handle->image);
123         g_free (handle);
124 }
125
126 /*
127  * Initialize debugging support.
128  *
129  * This method must be called after loading corlib,
130  * but before opening the application's main assembly because we need to set some
131  * callbacks here.
132  */
133 void
134 mono_debug_init (MonoDebugFormat format)
135 {
136         g_assert (!mono_debug_initialized);
137         if (format == MONO_DEBUG_FORMAT_DEBUGGER)
138                 g_error ("The mdb debugger is no longer supported.");
139
140         mono_debug_initialized = TRUE;
141         mono_debug_format = format;
142
143         mono_os_mutex_init_recursive (&debugger_lock_mutex);
144
145         mono_debugger_lock ();
146
147         mono_debug_handles = g_hash_table_new_full
148                 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
149
150         data_table_hash = g_hash_table_new_full (
151                 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
152
153         mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
154
155         mono_debugger_unlock ();
156 }
157
158 void
159 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
160 {
161         if (!mono_debug_initialized)
162                 return;
163
164         mono_debug_open_image (image, raw_contents, size);
165 }
166
167 void
168 mono_debug_cleanup (void)
169 {
170         if (mono_debug_handles)
171                 g_hash_table_destroy (mono_debug_handles);
172         mono_debug_handles = NULL;
173
174         if (data_table_hash) {
175                 g_hash_table_destroy (data_table_hash);
176                 data_table_hash = NULL;
177         }
178 }
179
180 void
181 mono_debug_domain_create (MonoDomain *domain)
182 {
183         if (!mono_debug_initialized)
184                 return;
185
186         mono_debugger_lock ();
187
188         create_data_table (domain);
189
190         mono_debugger_unlock ();
191 }
192
193 void
194 mono_debug_domain_unload (MonoDomain *domain)
195 {
196         MonoDebugDataTable *table;
197
198         if (!mono_debug_initialized)
199                 return;
200
201         mono_debugger_lock ();
202
203         table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
204         if (!table) {
205                 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
206                            domain, mono_domain_get_id (domain));
207                 mono_debugger_unlock ();
208                 return;
209         }
210
211         g_hash_table_remove (data_table_hash, domain);
212
213         mono_debugger_unlock ();
214 }
215
216 /*
217  * LOCKING: Assumes the debug lock is held.
218  */
219 static MonoDebugHandle *
220 mono_debug_get_image (MonoImage *image)
221 {
222         return (MonoDebugHandle *)g_hash_table_lookup (mono_debug_handles, image);
223 }
224
225 void
226 mono_debug_close_image (MonoImage *image)
227 {
228         MonoDebugHandle *handle;
229
230         if (!mono_debug_initialized)
231                 return;
232
233         mono_debugger_lock ();
234
235         handle = mono_debug_get_image (image);
236         if (!handle) {
237                 mono_debugger_unlock ();
238                 return;
239         }
240
241         g_hash_table_remove (mono_debug_handles, image);
242
243         mono_debugger_unlock ();
244 }
245
246 static MonoDebugHandle *
247 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
248 {
249         MonoDebugHandle *handle;
250
251         if (mono_image_is_dynamic (image))
252                 return NULL;
253
254         mono_debugger_lock ();
255
256         handle = mono_debug_get_image (image);
257         if (handle != NULL) {
258                 mono_debugger_unlock ();
259                 return handle;
260         }
261
262         handle = g_new0 (MonoDebugHandle, 1);
263
264         handle->image = image;
265         mono_image_addref (image);
266
267         /* Try a ppdb file first */
268         handle->ppdb = mono_ppdb_load_file (handle->image, raw_contents, size);
269
270         if (!handle->ppdb)
271                 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, FALSE);
272
273         g_hash_table_insert (mono_debug_handles, image, handle);
274
275         mono_debugger_unlock ();
276
277         return handle;
278 }
279
280 static void
281 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
282 {
283         MonoDebugHandle *handle;
284         MonoImage *image;
285
286         mono_debugger_lock ();
287         image = mono_assembly_get_image (assembly);
288         handle = open_symfile_from_bundle (image);
289         if (!handle)
290                 mono_debug_open_image (image, NULL, 0);
291         mono_debugger_unlock ();
292 }
293
294 struct LookupMethodData
295 {
296         MonoDebugMethodInfo *minfo;
297         MonoMethod *method;
298 };
299
300 static void
301 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
302 {
303         MonoDebugHandle *handle = (MonoDebugHandle *) value;
304         struct LookupMethodData *data = (struct LookupMethodData *) user_data;
305
306         if (data->minfo)
307                 return;
308
309         if (handle->ppdb)
310                 data->minfo = mono_ppdb_lookup_method (handle, data->method);
311         else if (handle->symfile)
312                 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
313 }
314
315 static MonoDebugMethodInfo *
316 mono_debug_lookup_method_internal (MonoMethod *method)
317 {
318         struct LookupMethodData data;
319
320         data.minfo = NULL;
321         data.method = method;
322
323         if (!mono_debug_handles)
324                 return NULL;
325
326         g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
327         return data.minfo;
328 }
329
330 /**
331  * mono_debug_lookup_method:
332  *
333  * Lookup symbol file information for the method @method.  The returned
334  * `MonoDebugMethodInfo' is a private structure, but it can be passed to
335  * mono_debug_symfile_lookup_location().
336  */
337 MonoDebugMethodInfo *
338 mono_debug_lookup_method (MonoMethod *method)
339 {
340         MonoDebugMethodInfo *minfo;
341
342         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
343                 return NULL;
344
345         mono_debugger_lock ();
346         minfo = mono_debug_lookup_method_internal (method);
347         mono_debugger_unlock ();
348         return minfo;
349 }
350
351 typedef struct
352 {
353         gboolean found;
354         MonoImage *image;
355 } LookupImageData;
356
357 static void
358 lookup_image_func (gpointer key, gpointer value, gpointer user_data)
359 {
360         MonoDebugHandle *handle = (MonoDebugHandle *) value;
361         LookupImageData *data = (LookupImageData *) user_data;
362
363         if (data->found)
364                 return;
365
366         if (handle->image == data->image && handle->symfile)
367                 data->found = TRUE;
368 }
369
370 gboolean
371 mono_debug_image_has_debug_info (MonoImage *image)
372 {
373         LookupImageData data;
374
375         if (!mono_debug_handles)
376                 return FALSE;
377
378         memset (&data, 0, sizeof (data));
379         data.image = image;
380
381         mono_debugger_lock ();
382         g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
383         mono_debugger_unlock ();
384         return data.found;
385 }
386
387 static inline void
388 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
389 {
390         do {
391                 guint8 byte = value & 0x7f;
392                 value >>= 7;
393                 if (value)
394                         byte |= 0x80;
395                 *ptr++ = byte;
396         } while (value);
397
398         *rptr = ptr;
399 }
400
401 static inline void
402 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
403 {
404         gboolean more = 1;
405
406         while (more) {
407                 guint8 byte = value & 0x7f;
408                 value >>= 7;
409
410                 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
411                         more = 0;
412                 else
413                         byte |= 0x80;
414                 *ptr++ = byte;
415         }
416
417         *rptr = ptr;
418 }
419
420 static void
421 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
422 {
423         write_leb128 (var->index, ptr, &ptr);
424         write_sleb128 (var->offset, ptr, &ptr);
425         write_leb128 (var->size, ptr, &ptr);
426         write_leb128 (var->begin_scope, ptr, &ptr);
427         write_leb128 (var->end_scope, ptr, &ptr);
428         WRITE_UNALIGNED (gpointer, ptr, var->type);
429         ptr += sizeof (gpointer);
430         *rptr = ptr;
431 }
432
433 MonoDebugMethodAddress *
434 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
435 {
436         MonoDebugDataTable *table;
437         MonoDebugMethodAddress *address;
438         guint8 buffer [BUFSIZ];
439         guint8 *ptr, *oldptr;
440         guint32 i, size, total_size, max_size;
441
442         mono_debugger_lock ();
443
444         table = lookup_data_table (domain);
445
446         max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
447                 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
448
449         if (max_size > BUFSIZ)
450                 ptr = oldptr = (guint8 *)g_malloc (max_size);
451         else
452                 ptr = oldptr = buffer;
453
454         write_leb128 (jit->prologue_end, ptr, &ptr);
455         write_leb128 (jit->epilogue_begin, ptr, &ptr);
456
457         write_leb128 (jit->num_line_numbers, ptr, &ptr);
458         for (i = 0; i < jit->num_line_numbers; i++) {
459                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
460
461                 write_sleb128 (lne->il_offset, ptr, &ptr);
462                 write_sleb128 (lne->native_offset, ptr, &ptr);
463         }
464         write_leb128 (jit->has_var_info, ptr, &ptr);
465         if (jit->has_var_info) {
466                 *ptr++ = jit->this_var ? 1 : 0;
467                 if (jit->this_var)
468                         write_variable (jit->this_var, ptr, &ptr);
469
470                 write_leb128 (jit->num_params, ptr, &ptr);
471                 for (i = 0; i < jit->num_params; i++)
472                         write_variable (&jit->params [i], ptr, &ptr);
473
474                 write_leb128 (jit->num_locals, ptr, &ptr);
475                 for (i = 0; i < jit->num_locals; i++)
476                         write_variable (&jit->locals [i], ptr, &ptr);
477
478                 *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
479                 if (jit->gsharedvt_info_var) {
480                         write_variable (jit->gsharedvt_info_var, ptr, &ptr);
481                         write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
482                 }
483         }
484
485         size = ptr - oldptr;
486         g_assert (size < max_size);
487         total_size = size + sizeof (MonoDebugMethodAddress);
488
489         if (method_is_dynamic (method)) {
490                 address = (MonoDebugMethodAddress *)g_malloc0 (total_size);
491         } else {
492                 address = (MonoDebugMethodAddress *)mono_mempool_alloc (table->mp, total_size);
493         }
494
495         address->code_start = jit->code_start;
496         address->code_size = jit->code_size;
497
498         memcpy (&address->data, oldptr, size);
499         if (max_size > BUFSIZ)
500                 g_free (oldptr);
501
502         g_hash_table_insert (table->method_address_hash, method, address);
503
504         mono_debugger_unlock ();
505         return address;
506 }
507
508 void
509 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
510 {
511         MonoDebugDataTable *table;
512         MonoDebugMethodAddress *address;
513
514         if (!mono_debug_initialized)
515                 return;
516
517         g_assert (method_is_dynamic (method));
518
519         mono_debugger_lock ();
520
521         table = lookup_data_table (domain);
522
523         address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
524         if (address)
525                 g_free (address);
526
527         g_hash_table_remove (table->method_address_hash, method);
528
529         mono_debugger_unlock ();
530 }
531
532 void
533 mono_debug_add_delegate_trampoline (gpointer code, int size)
534 {
535 }
536
537 static inline guint32
538 read_leb128 (guint8 *ptr, guint8 **rptr)
539 {
540         guint32 result = 0, shift = 0;
541
542         while (TRUE) {
543                 guint8 byte = *ptr++;
544
545                 result |= (byte & 0x7f) << shift;
546                 if ((byte & 0x80) == 0)
547                         break;
548                 shift += 7;
549         }
550
551         *rptr = ptr;
552         return result;
553 }
554
555 static inline gint32
556 read_sleb128 (guint8 *ptr, guint8 **rptr)
557 {
558         gint32 result = 0;
559         guint32 shift = 0;
560
561         while (TRUE) {
562                 guint8 byte = *ptr++;
563
564                 result |= (byte & 0x7f) << shift;
565                 shift += 7;
566
567                 if (byte & 0x80)
568                         continue;
569
570                 if ((shift < 32) && (byte & 0x40))
571                         result |= - (1 << shift);
572                 break;
573         }
574
575         *rptr = ptr;
576         return result;
577 }
578
579 static void
580 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
581 {
582         var->index = read_leb128 (ptr, &ptr);
583         var->offset = read_sleb128 (ptr, &ptr);
584         var->size = read_leb128 (ptr, &ptr);
585         var->begin_scope = read_leb128 (ptr, &ptr);
586         var->end_scope = read_leb128 (ptr, &ptr);
587         READ_UNALIGNED (MonoType *, ptr, var->type);
588         ptr += sizeof (gpointer);
589         *rptr = ptr;
590 }
591
592 void
593 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
594 {
595         if (!jit)
596                 return;
597         g_free (jit->line_numbers);
598         g_free (jit->this_var);
599         g_free (jit->params);
600         g_free (jit->locals);
601         g_free (jit->gsharedvt_info_var);
602         g_free (jit->gsharedvt_locals_var);
603         g_free (jit);
604 }
605
606 static MonoDebugMethodJitInfo *
607 mono_debug_read_method (MonoDebugMethodAddress *address)
608 {
609         MonoDebugMethodJitInfo *jit;
610         guint32 i;
611         guint8 *ptr;
612
613         jit = g_new0 (MonoDebugMethodJitInfo, 1);
614         jit->code_start = address->code_start;
615         jit->code_size = address->code_size;
616
617         ptr = (guint8 *) &address->data;
618
619         jit->prologue_end = read_leb128 (ptr, &ptr);
620         jit->epilogue_begin = read_leb128 (ptr, &ptr);
621
622         jit->num_line_numbers = read_leb128 (ptr, &ptr);
623         jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
624         for (i = 0; i < jit->num_line_numbers; i++) {
625                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
626
627                 lne->il_offset = read_sleb128 (ptr, &ptr);
628                 lne->native_offset = read_sleb128 (ptr, &ptr);
629         }
630         jit->has_var_info = read_leb128 (ptr, &ptr);
631         if (jit->has_var_info) {
632                 if (*ptr++) {
633                         jit->this_var = g_new0 (MonoDebugVarInfo, 1);
634                         read_variable (jit->this_var, ptr, &ptr);
635                 }
636
637                 jit->num_params = read_leb128 (ptr, &ptr);
638                 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
639                 for (i = 0; i < jit->num_params; i++)
640                         read_variable (&jit->params [i], ptr, &ptr);
641
642                 jit->num_locals = read_leb128 (ptr, &ptr);
643                 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
644                 for (i = 0; i < jit->num_locals; i++)
645                         read_variable (&jit->locals [i], ptr, &ptr);
646
647                 if (*ptr++) {
648                         jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
649                         jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
650                         read_variable (jit->gsharedvt_info_var, ptr, &ptr);
651                         read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
652                 }
653         }
654
655         return jit;
656 }
657
658 static MonoDebugMethodJitInfo *
659 find_method (MonoMethod *method, MonoDomain *domain)
660 {
661         MonoDebugDataTable *table;
662         MonoDebugMethodAddress *address;
663
664         table = lookup_data_table (domain);
665         address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
666
667         if (!address)
668                 return NULL;
669
670         return mono_debug_read_method (address);
671 }
672
673 MonoDebugMethodJitInfo *
674 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
675 {
676         MonoDebugMethodJitInfo *res;
677
678         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
679                 return NULL;
680
681         mono_debugger_lock ();
682         res = find_method (method, domain);
683         mono_debugger_unlock ();
684         return res;
685 }
686
687 MonoDebugMethodAddressList *
688 mono_debug_lookup_method_addresses (MonoMethod *method)
689 {
690         g_assert_not_reached ();
691         return NULL;
692 }
693
694 static gint32
695 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
696 {
697         MonoDebugMethodJitInfo *jit;
698         int i;
699
700         jit = find_method (method, domain);
701         if (!jit || !jit->line_numbers)
702                 goto cleanup_and_fail;
703
704         for (i = jit->num_line_numbers - 1; i >= 0; i--) {
705                 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
706
707                 if (lne.native_offset <= native_offset) {
708                         mono_debug_free_method_jit_info (jit);
709                         return lne.il_offset;
710                 }
711         }
712
713 cleanup_and_fail:
714         mono_debug_free_method_jit_info (jit);
715         return -1;
716 }
717
718 /**
719  * mono_debug_il_offset_from_address:
720  *
721  *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
722  * code of METHOD in DOMAIN.
723  */
724 gint32
725 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
726 {
727         gint32 res;
728
729         mono_debugger_lock ();
730
731         res = il_offset_from_address (method, domain, native_offset);
732
733         mono_debugger_unlock ();
734
735         return res;
736 }
737
738 /**
739  * mono_debug_lookup_source_location:
740  * @address: Native offset within the @method's machine code.
741  *
742  * Lookup the source code corresponding to the machine instruction located at
743  * native offset @address within @method.
744  *
745  * The returned `MonoDebugSourceLocation' contains both file / line number
746  * information and the corresponding IL offset.  It must be freed by
747  * mono_debug_free_source_location().
748  */
749 MonoDebugSourceLocation *
750 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
751 {
752         MonoDebugMethodInfo *minfo;
753         MonoDebugSourceLocation *location;
754         gint32 offset;
755
756         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
757                 return NULL;
758
759         mono_debugger_lock ();
760         minfo = mono_debug_lookup_method_internal (method);
761         if (!minfo || !minfo->handle) {
762                 mono_debugger_unlock ();
763                 return NULL;
764         }
765
766         if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
767                 mono_debugger_unlock ();
768                 return NULL;
769         }
770
771         offset = il_offset_from_address (method, domain, address);
772         if (offset < 0) {
773                 mono_debugger_unlock ();
774                 return NULL;
775         }
776
777         if (minfo->handle->ppdb)
778                 location = mono_ppdb_lookup_location (minfo, offset);
779         else
780                 location = mono_debug_symfile_lookup_location (minfo, offset);
781         mono_debugger_unlock ();
782         return location;
783 }
784
785 MonoDebugSourceLocation *
786 mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
787 {
788         MonoDebugSourceLocation *location;
789
790         mono_debugger_lock ();
791         if (minfo->handle->ppdb)
792                 location = mono_ppdb_lookup_location (minfo, il_offset);
793         else
794                 location = mono_debug_symfile_lookup_location (minfo, il_offset);
795         mono_debugger_unlock ();
796         return location;
797 }
798
799 /*
800  * mono_debug_lookup_locals:
801  *
802  *   Return information about the local variables of MINFO.
803  * The result should be freed using mono_debug_free_locals ().
804  */
805 MonoDebugLocalsInfo*
806 mono_debug_lookup_locals (MonoMethod *method)
807 {
808         MonoDebugMethodInfo *minfo;
809         MonoDebugLocalsInfo *res;
810
811         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
812                 return NULL;
813
814         mono_debugger_lock ();
815         minfo = mono_debug_lookup_method_internal (method);
816         if (!minfo || !minfo->handle) {
817                 mono_debugger_unlock ();
818                 return NULL;
819         }
820
821         if (minfo->handle->ppdb) {
822                 res = mono_ppdb_lookup_locals (minfo);
823         } else {
824                 if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
825                         res = NULL;
826                 else
827                         res = mono_debug_symfile_lookup_locals (minfo);
828         }
829         mono_debugger_unlock ();
830
831         return res;
832 }
833
834 /*
835  * mono_debug_free_locals:
836  *
837  *   Free all the data allocated by mono_debug_lookup_locals ().
838  */
839 void
840 mono_debug_free_locals (MonoDebugLocalsInfo *info)
841 {
842         int i;
843
844         for (i = 0; i < info->num_locals; ++i)
845                 g_free (info->locals [i].name);
846         g_free (info->locals);
847         g_free (info->code_blocks);
848         g_free (info);
849 }
850
851 /**
852  * mono_debug_free_source_location:
853  * @location: A `MonoDebugSourceLocation'.
854  *
855  * Frees the @location.
856  */
857 void
858 mono_debug_free_source_location (MonoDebugSourceLocation *location)
859 {
860         if (location) {
861                 g_free (location->source_file);
862                 g_free (location);
863         }
864 }
865
866 static int (*get_seq_point) (MonoDomain *domain, MonoMethod *method, gint32 native_offset);
867
868 void
869 mono_install_get_seq_point (MonoGetSeqPointFunc func)
870 {
871         get_seq_point = func;
872 }
873
874 /**
875  * mono_debug_print_stack_frame:
876  * @native_offset: Native offset within the @method's machine code.
877  *
878  * Conventient wrapper around mono_debug_lookup_source_location() which can be
879  * used if you only want to use the location to print a stack frame.
880  */
881 gchar *
882 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
883 {
884         MonoDebugSourceLocation *location;
885         gchar *fname, *ptr, *res;
886         int offset;
887
888         fname = mono_method_full_name (method, TRUE);
889         for (ptr = fname; *ptr; ptr++) {
890                 if (*ptr == ':') *ptr = '.';
891         }
892
893         location = mono_debug_lookup_source_location (method, native_offset, domain);
894
895         if (!location) {
896                 if (mono_debug_initialized) {
897                         mono_debugger_lock ();
898                         offset = il_offset_from_address (method, domain, native_offset);
899                         mono_debugger_unlock ();
900                 } else {
901                         offset = -1;
902                 }
903
904                 if (offset < 0 && get_seq_point)
905                         offset = get_seq_point (domain, method, native_offset);
906
907                 if (offset < 0)
908                         res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
909                 else {
910                         char *mvid = mono_guid_to_string_minimal ((uint8_t*)method->klass->image->heap_guid.data);
911                         char *aotid = mono_runtime_get_aotid ();
912                         if (aotid)
913                                 res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
914                         else
915                                 res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);
916
917                         g_free (aotid);
918                         g_free (mvid);
919                 }
920                 g_free (fname);
921                 return res;
922         }
923
924         res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
925                                location->source_file, location->row);
926
927         g_free (fname);
928         mono_debug_free_source_location (location);
929         return res;
930 }
931
932 void
933 mono_set_is_debugger_attached (gboolean attached)
934 {
935         is_attached = attached;
936 }
937
938 gboolean
939 mono_is_debugger_attached (void)
940 {
941         return is_attached;
942 }
943
944 /*
945  * Bundles
946  */
947
948 typedef struct _BundledSymfile BundledSymfile;
949
950 struct _BundledSymfile {
951         BundledSymfile *next;
952         const char *aname;
953         const mono_byte *raw_contents;
954         int size;
955 };
956
957 static BundledSymfile *bundled_symfiles = NULL;
958
959 void
960 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
961 {
962         BundledSymfile *bsymfile;
963
964         bsymfile = g_new0 (BundledSymfile, 1);
965         bsymfile->aname = assembly_name;
966         bsymfile->raw_contents = raw_contents;
967         bsymfile->size = size;
968         bsymfile->next = bundled_symfiles;
969         bundled_symfiles = bsymfile;
970 }
971
972 static MonoDebugHandle *
973 open_symfile_from_bundle (MonoImage *image)
974 {
975         BundledSymfile *bsymfile;
976
977         for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
978                 if (strcmp (bsymfile->aname, image->module_name))
979                         continue;
980
981                 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
982         }
983
984         return NULL;
985 }
986
987 void
988 mono_debugger_lock (void)
989 {
990         g_assert (mono_debug_initialized);
991         mono_os_mutex_lock (&debugger_lock_mutex);
992 }
993
994 void
995 mono_debugger_unlock (void)
996 {
997         g_assert (mono_debug_initialized);
998         mono_os_mutex_unlock (&debugger_lock_mutex);
999 }
1000
1001 /**
1002  * mono_debug_enabled:
1003  *
1004  * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1005  */
1006 mono_bool
1007 mono_debug_enabled (void)
1008 {
1009         return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
1010 }
1011
1012 void
1013 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
1014 {
1015         if (minfo->handle->ppdb)
1016                 mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
1017         else
1018                 mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
1019 }