Merge pull request #2338 from BogdanovKirill/httpwritefix3
[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-internals.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 = (MonoDebugDataTable *)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_os_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 = (MonoDebugDataTable *)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 (MonoDebugHandle *)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 = (guint8 *)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 = (MonoDebugMethodAddress *)g_malloc0 (total_size);
486         } else {
487                 address = (MonoDebugMethodAddress *)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 = (MonoDebugMethodAddress *)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 (MonoType *, 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 = (MonoDebugMethodAddress *)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 MonoDebugSourceLocation *
779 mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
780 {
781         MonoDebugSourceLocation *location;
782
783         mono_debugger_lock ();
784         if (minfo->handle->ppdb)
785                 location = mono_ppdb_lookup_location (minfo, il_offset);
786         else
787                 location = mono_debug_symfile_lookup_location (minfo, il_offset);
788         mono_debugger_unlock ();
789         return location;
790 }
791
792 /*
793  * mono_debug_lookup_locals:
794  *
795  *   Return information about the local variables of MINFO.
796  * The result should be freed using mono_debug_free_locals ().
797  */
798 MonoDebugLocalsInfo*
799 mono_debug_lookup_locals (MonoMethod *method)
800 {
801         MonoDebugMethodInfo *minfo;
802         MonoDebugLocalsInfo *res;
803
804         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
805                 return NULL;
806
807         mono_debugger_lock ();
808         minfo = mono_debug_lookup_method_internal (method);
809         if (!minfo || !minfo->handle) {
810                 mono_debugger_unlock ();
811                 return NULL;
812         }
813
814         if (minfo->handle->ppdb) {
815                 res = mono_ppdb_lookup_locals (minfo);
816         } else {
817                 if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
818                         res = NULL;
819                 else
820                         res = mono_debug_symfile_lookup_locals (minfo);
821         }
822         mono_debugger_unlock ();
823
824         return res;
825 }
826
827 /*
828  * mono_debug_free_locals:
829  *
830  *   Free all the data allocated by mono_debug_lookup_locals ().
831  */
832 void
833 mono_debug_free_locals (MonoDebugLocalsInfo *info)
834 {
835         int i;
836
837         for (i = 0; i < info->num_locals; ++i)
838                 g_free (info->locals [i].name);
839         g_free (info->locals);
840         g_free (info->code_blocks);
841         g_free (info);
842 }
843
844 /**
845  * mono_debug_free_source_location:
846  * @location: A `MonoDebugSourceLocation'.
847  *
848  * Frees the @location.
849  */
850 void
851 mono_debug_free_source_location (MonoDebugSourceLocation *location)
852 {
853         if (location) {
854                 g_free (location->source_file);
855                 g_free (location);
856         }
857 }
858
859 /**
860  * mono_debug_print_stack_frame:
861  * @native_offset: Native offset within the @method's machine code.
862  *
863  * Conventient wrapper around mono_debug_lookup_source_location() which can be
864  * used if you only want to use the location to print a stack frame.
865  */
866 gchar *
867 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
868 {
869         MonoDebugSourceLocation *location;
870         gchar *fname, *ptr, *res;
871         int offset;
872
873         fname = mono_method_full_name (method, TRUE);
874         for (ptr = fname; *ptr; ptr++) {
875                 if (*ptr == ':') *ptr = '.';
876         }
877
878         location = mono_debug_lookup_source_location (method, native_offset, domain);
879
880         if (!location) {
881                 if (mono_debug_initialized) {
882                         mono_debugger_lock ();
883                         offset = il_offset_from_address (method, domain, native_offset);
884                         mono_debugger_unlock ();
885                 } else {
886                         offset = -1;
887                 }
888
889                 if (offset < 0)
890                         res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
891                 else
892                         res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
893                 g_free (fname);
894                 return res;
895         }
896
897         res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
898                                location->source_file, location->row);
899
900         g_free (fname);
901         mono_debug_free_source_location (location);
902         return res;
903 }
904
905 void
906 mono_set_is_debugger_attached (gboolean attached)
907 {
908         is_attached = attached;
909 }
910
911 gboolean
912 mono_is_debugger_attached (void)
913 {
914         return is_attached;
915 }
916
917 /*
918  * Bundles
919  */
920
921 typedef struct _BundledSymfile BundledSymfile;
922
923 struct _BundledSymfile {
924         BundledSymfile *next;
925         const char *aname;
926         const mono_byte *raw_contents;
927         int size;
928 };
929
930 static BundledSymfile *bundled_symfiles = NULL;
931
932 void
933 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
934 {
935         BundledSymfile *bsymfile;
936
937         bsymfile = g_new0 (BundledSymfile, 1);
938         bsymfile->aname = assembly_name;
939         bsymfile->raw_contents = raw_contents;
940         bsymfile->size = size;
941         bsymfile->next = bundled_symfiles;
942         bundled_symfiles = bsymfile;
943 }
944
945 static MonoDebugHandle *
946 open_symfile_from_bundle (MonoImage *image)
947 {
948         BundledSymfile *bsymfile;
949
950         for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
951                 if (strcmp (bsymfile->aname, image->module_name))
952                         continue;
953
954                 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
955         }
956
957         return NULL;
958 }
959
960 void
961 mono_debugger_lock (void)
962 {
963         g_assert (mono_debug_initialized);
964         mono_os_mutex_lock (&debugger_lock_mutex);
965 }
966
967 void
968 mono_debugger_unlock (void)
969 {
970         g_assert (mono_debug_initialized);
971         mono_os_mutex_unlock (&debugger_lock_mutex);
972 }
973
974 /**
975  * mono_debug_enabled:
976  *
977  * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
978  */
979 mono_bool
980 mono_debug_enabled (void)
981 {
982         return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
983 }
984
985 void
986 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
987 {
988         if (minfo->handle->ppdb)
989                 mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
990         else
991                 mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
992 }