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