[sdks] Fixes llvm branch name (#8926)
[mono-project.git] / mono / metadata / mono-debug.c
blob1b0f618b5ec32063628662bd5906c68567d3bad9
1 /**
2 * \file
4 * Author:
5 * Mono Project (http://www.mono-project.com)
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.
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/debug-internals.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-symfile.h>
25 #include <mono/metadata/debug-mono-ppdb.h>
26 #include <mono/metadata/exception-internals.h>
27 #include <mono/metadata/runtime.h>
28 #include <string.h>
30 #if NO_UNALIGNED_ACCESS
31 #define WRITE_UNALIGNED(type, addr, val) \
32 memcpy(addr, &val, sizeof(type))
33 #define READ_UNALIGNED(type, addr, val) \
34 memcpy(&val, addr, sizeof(type))
35 #else
36 #define WRITE_UNALIGNED(type, addr, val) \
37 (*(type *)(addr) = (val))
38 #define READ_UNALIGNED(type, addr, val) \
39 val = (*(type *)(addr))
40 #endif
42 /* This contains per-domain info */
43 struct _MonoDebugDataTable {
44 MonoMemPool *mp;
45 GHashTable *method_address_hash;
48 /* This contains JIT debugging information about a method in serialized format */
49 struct _MonoDebugMethodAddress {
50 const guint8 *code_start;
51 guint32 code_size;
52 guint8 data [MONO_ZERO_LEN_ARRAY];
55 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
57 static gboolean mono_debug_initialized = FALSE;
58 /* Maps MonoImage -> MonoMonoDebugHandle */
59 static GHashTable *mono_debug_handles;
60 /* Maps MonoDomain -> MonoDataTable */
61 static GHashTable *data_table_hash;
63 static mono_mutex_t debugger_lock_mutex;
65 static gboolean is_attached = FALSE;
67 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
69 static MonoDebugHandle *mono_debug_get_image (MonoImage *image);
70 static void mono_debug_add_assembly (MonoAssembly *assembly,
71 gpointer user_data);
73 static MonoDebugHandle *open_symfile_from_bundle (MonoImage *image);
75 static MonoDebugDataTable *
76 create_data_table (MonoDomain *domain)
78 MonoDebugDataTable *table;
80 table = g_new0 (MonoDebugDataTable, 1);
82 table->mp = mono_mempool_new ();
83 table->method_address_hash = g_hash_table_new (NULL, NULL);
85 if (domain)
86 g_hash_table_insert (data_table_hash, domain, table);
88 return table;
91 static void
92 free_data_table (MonoDebugDataTable *table)
94 mono_mempool_destroy (table->mp);
95 g_hash_table_destroy (table->method_address_hash);
97 g_free (table);
100 static MonoDebugDataTable *
101 lookup_data_table (MonoDomain *domain)
103 MonoDebugDataTable *table;
105 table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
106 if (!table) {
107 g_error ("lookup_data_table () failed for %p\n", domain);
108 g_assert (table);
110 return table;
113 static void
114 free_debug_handle (MonoDebugHandle *handle)
116 if (handle->ppdb)
117 mono_ppdb_close (handle);
118 if (handle->symfile)
119 mono_debug_close_mono_symbol_file (handle->symfile);
120 /* decrease the refcount added with mono_image_addref () */
121 mono_image_close (handle->image);
122 g_free (handle);
126 * Initialize debugging support.
128 * This method must be called after loading corlib,
129 * but before opening the application's main assembly because we need to set some
130 * callbacks here.
132 void
133 mono_debug_init (MonoDebugFormat format)
135 g_assert (!mono_debug_initialized);
136 if (format == MONO_DEBUG_FORMAT_DEBUGGER)
137 g_error ("The mdb debugger is no longer supported.");
139 mono_debug_initialized = TRUE;
140 mono_debug_format = format;
142 mono_os_mutex_init_recursive (&debugger_lock_mutex);
144 mono_debugger_lock ();
146 mono_debug_handles = g_hash_table_new_full
147 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
149 data_table_hash = g_hash_table_new_full (
150 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
152 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
154 mono_debugger_unlock ();
157 void
158 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
160 if (!mono_debug_initialized)
161 return;
163 mono_debug_open_image (image, raw_contents, size);
166 void
167 mono_debug_cleanup (void)
169 if (mono_debug_handles)
170 g_hash_table_destroy (mono_debug_handles);
171 mono_debug_handles = NULL;
173 if (data_table_hash) {
174 g_hash_table_destroy (data_table_hash);
175 data_table_hash = NULL;
180 * mono_debug_domain_create:
182 void
183 mono_debug_domain_create (MonoDomain *domain)
185 if (!mono_debug_initialized)
186 return;
188 mono_debugger_lock ();
190 create_data_table (domain);
192 mono_debugger_unlock ();
195 void
196 mono_debug_domain_unload (MonoDomain *domain)
198 MonoDebugDataTable *table;
200 if (!mono_debug_initialized)
201 return;
203 mono_debugger_lock ();
205 table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
206 if (!table) {
207 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
208 domain, mono_domain_get_id (domain));
209 mono_debugger_unlock ();
210 return;
213 g_hash_table_remove (data_table_hash, domain);
215 mono_debugger_unlock ();
219 * LOCKING: Assumes the debug lock is held.
221 static MonoDebugHandle *
222 mono_debug_get_image (MonoImage *image)
224 return (MonoDebugHandle *)g_hash_table_lookup (mono_debug_handles, image);
228 * mono_debug_close_image:
230 void
231 mono_debug_close_image (MonoImage *image)
233 MonoDebugHandle *handle;
235 if (!mono_debug_initialized)
236 return;
238 mono_debugger_lock ();
240 handle = mono_debug_get_image (image);
241 if (!handle) {
242 mono_debugger_unlock ();
243 return;
246 g_hash_table_remove (mono_debug_handles, image);
248 mono_debugger_unlock ();
251 static MonoDebugHandle *
252 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
254 MonoDebugHandle *handle;
256 if (mono_image_is_dynamic (image))
257 return NULL;
259 mono_debugger_lock ();
261 handle = mono_debug_get_image (image);
262 if (handle != NULL) {
263 mono_debugger_unlock ();
264 return handle;
267 handle = g_new0 (MonoDebugHandle, 1);
269 handle->image = image;
270 mono_image_addref (image);
272 /* Try a ppdb file first */
273 handle->ppdb = mono_ppdb_load_file (handle->image, raw_contents, size);
275 if (!handle->ppdb)
276 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, FALSE);
278 g_hash_table_insert (mono_debug_handles, image, handle);
280 mono_debugger_unlock ();
282 return handle;
285 static void
286 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
288 MonoDebugHandle *handle;
289 MonoImage *image;
291 mono_debugger_lock ();
292 image = mono_assembly_get_image (assembly);
293 handle = open_symfile_from_bundle (image);
294 if (!handle)
295 mono_debug_open_image (image, NULL, 0);
296 mono_debugger_unlock ();
299 struct LookupMethodData
301 MonoDebugMethodInfo *minfo;
302 MonoMethod *method;
305 static void
306 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
308 MonoDebugHandle *handle = (MonoDebugHandle *) value;
309 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
311 if (data->minfo)
312 return;
314 if (handle->ppdb)
315 data->minfo = mono_ppdb_lookup_method (handle, data->method);
316 else if (handle->symfile)
317 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
320 static MonoDebugMethodInfo *
321 mono_debug_lookup_method_internal (MonoMethod *method)
323 struct LookupMethodData data;
325 data.minfo = NULL;
326 data.method = method;
328 if (!mono_debug_handles)
329 return NULL;
331 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
332 return data.minfo;
336 * mono_debug_lookup_method:
338 * Lookup symbol file information for the method \p method. The returned
339 * \c MonoDebugMethodInfo is a private structure, but it can be passed to
340 * \c mono_debug_symfile_lookup_location.
342 MonoDebugMethodInfo *
343 mono_debug_lookup_method (MonoMethod *method)
345 MonoDebugMethodInfo *minfo;
347 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
348 return NULL;
350 mono_debugger_lock ();
351 minfo = mono_debug_lookup_method_internal (method);
352 mono_debugger_unlock ();
353 return minfo;
356 typedef struct
358 gboolean found;
359 MonoImage *image;
360 } LookupImageData;
362 static void
363 lookup_image_func (gpointer key, gpointer value, gpointer user_data)
365 MonoDebugHandle *handle = (MonoDebugHandle *) value;
366 LookupImageData *data = (LookupImageData *) user_data;
368 if (data->found)
369 return;
371 if (handle->image == data->image && handle->symfile)
372 data->found = TRUE;
375 gboolean
376 mono_debug_image_has_debug_info (MonoImage *image)
378 LookupImageData data;
380 if (!mono_debug_handles)
381 return FALSE;
383 memset (&data, 0, sizeof (data));
384 data.image = image;
386 mono_debugger_lock ();
387 g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
388 mono_debugger_unlock ();
389 return data.found;
392 static inline void
393 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
395 do {
396 guint8 byte = value & 0x7f;
397 value >>= 7;
398 if (value)
399 byte |= 0x80;
400 *ptr++ = byte;
401 } while (value);
403 *rptr = ptr;
406 static inline void
407 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
409 gboolean more = 1;
411 while (more) {
412 guint8 byte = value & 0x7f;
413 value >>= 7;
415 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
416 more = 0;
417 else
418 byte |= 0x80;
419 *ptr++ = byte;
422 *rptr = ptr;
425 static void
426 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
428 write_leb128 (var->index, ptr, &ptr);
429 write_sleb128 (var->offset, ptr, &ptr);
430 write_leb128 (var->size, ptr, &ptr);
431 write_leb128 (var->begin_scope, ptr, &ptr);
432 write_leb128 (var->end_scope, ptr, &ptr);
433 WRITE_UNALIGNED (gpointer, ptr, var->type);
434 ptr += sizeof (gpointer);
435 *rptr = ptr;
439 * mono_debug_add_method:
441 MonoDebugMethodAddress *
442 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
444 MonoDebugDataTable *table;
445 MonoDebugMethodAddress *address;
446 guint8 buffer [BUFSIZ];
447 guint8 *ptr, *oldptr;
448 guint32 i, size, total_size, max_size;
450 mono_debugger_lock ();
452 table = lookup_data_table (domain);
454 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
455 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
457 if (max_size > BUFSIZ)
458 ptr = oldptr = (guint8 *)g_malloc (max_size);
459 else
460 ptr = oldptr = buffer;
462 write_leb128 (jit->prologue_end, ptr, &ptr);
463 write_leb128 (jit->epilogue_begin, ptr, &ptr);
465 write_leb128 (jit->num_line_numbers, ptr, &ptr);
466 for (i = 0; i < jit->num_line_numbers; i++) {
467 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
469 write_sleb128 (lne->il_offset, ptr, &ptr);
470 write_sleb128 (lne->native_offset, ptr, &ptr);
472 write_leb128 (jit->has_var_info, ptr, &ptr);
473 if (jit->has_var_info) {
474 *ptr++ = jit->this_var ? 1 : 0;
475 if (jit->this_var)
476 write_variable (jit->this_var, ptr, &ptr);
478 write_leb128 (jit->num_params, ptr, &ptr);
479 for (i = 0; i < jit->num_params; i++)
480 write_variable (&jit->params [i], ptr, &ptr);
482 write_leb128 (jit->num_locals, ptr, &ptr);
483 for (i = 0; i < jit->num_locals; i++)
484 write_variable (&jit->locals [i], ptr, &ptr);
486 *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
487 if (jit->gsharedvt_info_var) {
488 write_variable (jit->gsharedvt_info_var, ptr, &ptr);
489 write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
493 size = ptr - oldptr;
494 g_assert (size < max_size);
495 total_size = size + sizeof (MonoDebugMethodAddress);
497 if (method_is_dynamic (method)) {
498 address = (MonoDebugMethodAddress *)g_malloc0 (total_size);
499 } else {
500 address = (MonoDebugMethodAddress *)mono_mempool_alloc (table->mp, total_size);
503 address->code_start = jit->code_start;
504 address->code_size = jit->code_size;
506 memcpy (&address->data, oldptr, size);
507 if (max_size > BUFSIZ)
508 g_free (oldptr);
510 g_hash_table_insert (table->method_address_hash, method, address);
512 mono_debugger_unlock ();
513 return address;
516 void
517 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
519 MonoDebugDataTable *table;
520 MonoDebugMethodAddress *address;
522 if (!mono_debug_initialized)
523 return;
525 g_assert (method_is_dynamic (method));
527 mono_debugger_lock ();
529 table = lookup_data_table (domain);
531 address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
532 if (address)
533 g_free (address);
535 g_hash_table_remove (table->method_address_hash, method);
537 mono_debugger_unlock ();
541 * mono_debug_add_delegate_trampoline:
543 void
544 mono_debug_add_delegate_trampoline (gpointer code, int size)
548 static inline guint32
549 read_leb128 (guint8 *ptr, guint8 **rptr)
551 guint32 result = 0, shift = 0;
553 while (TRUE) {
554 guint8 byte = *ptr++;
556 result |= (byte & 0x7f) << shift;
557 if ((byte & 0x80) == 0)
558 break;
559 shift += 7;
562 *rptr = ptr;
563 return result;
566 static inline gint32
567 read_sleb128 (guint8 *ptr, guint8 **rptr)
569 gint32 result = 0;
570 guint32 shift = 0;
572 while (TRUE) {
573 guint8 byte = *ptr++;
575 result |= (byte & 0x7f) << shift;
576 shift += 7;
578 if (byte & 0x80)
579 continue;
581 if ((shift < 32) && (byte & 0x40))
582 result |= - (1 << shift);
583 break;
586 *rptr = ptr;
587 return result;
590 static void
591 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
593 var->index = read_leb128 (ptr, &ptr);
594 var->offset = read_sleb128 (ptr, &ptr);
595 var->size = read_leb128 (ptr, &ptr);
596 var->begin_scope = read_leb128 (ptr, &ptr);
597 var->end_scope = read_leb128 (ptr, &ptr);
598 READ_UNALIGNED (MonoType *, ptr, var->type);
599 ptr += sizeof (gpointer);
600 *rptr = ptr;
603 void
604 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
606 if (!jit)
607 return;
608 g_free (jit->line_numbers);
609 g_free (jit->this_var);
610 g_free (jit->params);
611 g_free (jit->locals);
612 g_free (jit->gsharedvt_info_var);
613 g_free (jit->gsharedvt_locals_var);
614 g_free (jit);
617 static MonoDebugMethodJitInfo *
618 mono_debug_read_method (MonoDebugMethodAddress *address)
620 MonoDebugMethodJitInfo *jit;
621 guint32 i;
622 guint8 *ptr;
624 jit = g_new0 (MonoDebugMethodJitInfo, 1);
625 jit->code_start = address->code_start;
626 jit->code_size = address->code_size;
628 ptr = (guint8 *) &address->data;
630 jit->prologue_end = read_leb128 (ptr, &ptr);
631 jit->epilogue_begin = read_leb128 (ptr, &ptr);
633 jit->num_line_numbers = read_leb128 (ptr, &ptr);
634 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
635 for (i = 0; i < jit->num_line_numbers; i++) {
636 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
638 lne->il_offset = read_sleb128 (ptr, &ptr);
639 lne->native_offset = read_sleb128 (ptr, &ptr);
641 jit->has_var_info = read_leb128 (ptr, &ptr);
642 if (jit->has_var_info) {
643 if (*ptr++) {
644 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
645 read_variable (jit->this_var, ptr, &ptr);
648 jit->num_params = read_leb128 (ptr, &ptr);
649 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
650 for (i = 0; i < jit->num_params; i++)
651 read_variable (&jit->params [i], ptr, &ptr);
653 jit->num_locals = read_leb128 (ptr, &ptr);
654 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
655 for (i = 0; i < jit->num_locals; i++)
656 read_variable (&jit->locals [i], ptr, &ptr);
658 if (*ptr++) {
659 jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
660 jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
661 read_variable (jit->gsharedvt_info_var, ptr, &ptr);
662 read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
666 return jit;
669 static MonoDebugMethodJitInfo *
670 find_method (MonoMethod *method, MonoDomain *domain)
672 MonoDebugDataTable *table;
673 MonoDebugMethodAddress *address;
675 table = lookup_data_table (domain);
676 address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
678 if (!address)
679 return NULL;
681 return mono_debug_read_method (address);
684 MonoDebugMethodJitInfo *
685 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
687 MonoDebugMethodJitInfo *res;
689 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
690 return NULL;
692 mono_debugger_lock ();
693 res = find_method (method, domain);
694 mono_debugger_unlock ();
695 return res;
698 MonoDebugMethodAddressList *
699 mono_debug_lookup_method_addresses (MonoMethod *method)
701 g_assert_not_reached ();
702 return NULL;
705 static gint32
706 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
708 MonoDebugMethodJitInfo *jit;
709 int i;
711 jit = find_method (method, domain);
712 if (!jit || !jit->line_numbers)
713 goto cleanup_and_fail;
715 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
716 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
718 if (lne.native_offset <= native_offset) {
719 mono_debug_free_method_jit_info (jit);
720 return lne.il_offset;
724 cleanup_and_fail:
725 mono_debug_free_method_jit_info (jit);
726 return -1;
730 * mono_debug_il_offset_from_address:
732 * Compute the IL offset corresponding to \p native_offset inside the native
733 * code of \p method in \p domain.
735 gint32
736 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
738 gint32 res;
740 mono_debugger_lock ();
742 res = il_offset_from_address (method, domain, native_offset);
744 mono_debugger_unlock ();
746 return res;
750 * mono_debug_lookup_source_location:
751 * \param address Native offset within the \p method's machine code.
752 * Lookup the source code corresponding to the machine instruction located at
753 * native offset \p address within \p method.
754 * The returned \c MonoDebugSourceLocation contains both file / line number
755 * information and the corresponding IL offset. It must be freed by
756 * \c mono_debug_free_source_location.
758 MonoDebugSourceLocation *
759 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
761 MonoDebugMethodInfo *minfo;
762 MonoDebugSourceLocation *location;
763 gint32 offset;
765 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
766 return NULL;
768 mono_debugger_lock ();
769 minfo = mono_debug_lookup_method_internal (method);
770 if (!minfo || !minfo->handle) {
771 mono_debugger_unlock ();
772 return NULL;
775 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
776 mono_debugger_unlock ();
777 return NULL;
780 offset = il_offset_from_address (method, domain, address);
781 if (offset < 0) {
782 mono_debugger_unlock ();
783 return NULL;
786 if (minfo->handle->ppdb)
787 location = mono_ppdb_lookup_location (minfo, offset);
788 else
789 location = mono_debug_symfile_lookup_location (minfo, offset);
790 mono_debugger_unlock ();
791 return location;
795 * mono_debug_lookup_source_location_by_il:
797 * Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
799 MonoDebugSourceLocation *
800 mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain)
802 MonoDebugMethodInfo *minfo;
803 MonoDebugSourceLocation *location;
805 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
806 return NULL;
808 mono_debugger_lock ();
809 minfo = mono_debug_lookup_method_internal (method);
810 if (!minfo || !minfo->handle) {
811 mono_debugger_unlock ();
812 return NULL;
815 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
816 mono_debugger_unlock ();
817 return NULL;
820 if (minfo->handle->ppdb)
821 location = mono_ppdb_lookup_location (minfo, il_offset);
822 else
823 location = mono_debug_symfile_lookup_location (minfo, il_offset);
824 mono_debugger_unlock ();
825 return location;
828 MonoDebugSourceLocation *
829 mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
831 MonoDebugSourceLocation *location;
833 mono_debugger_lock ();
834 if (minfo->handle->ppdb)
835 location = mono_ppdb_lookup_location (minfo, il_offset);
836 else
837 location = mono_debug_symfile_lookup_location (minfo, il_offset);
838 mono_debugger_unlock ();
839 return location;
843 * mono_debug_lookup_locals:
845 * Return information about the local variables of MINFO.
846 * The result should be freed using mono_debug_free_locals ().
848 MonoDebugLocalsInfo*
849 mono_debug_lookup_locals (MonoMethod *method)
851 MonoDebugMethodInfo *minfo;
852 MonoDebugLocalsInfo *res;
854 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
855 return NULL;
857 mono_debugger_lock ();
858 minfo = mono_debug_lookup_method_internal (method);
859 if (!minfo || !minfo->handle) {
860 mono_debugger_unlock ();
861 return NULL;
864 if (minfo->handle->ppdb) {
865 res = mono_ppdb_lookup_locals (minfo);
866 } else {
867 if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
868 res = NULL;
869 else
870 res = mono_debug_symfile_lookup_locals (minfo);
872 mono_debugger_unlock ();
874 return res;
878 * mono_debug_free_locals:
880 * Free all the data allocated by mono_debug_lookup_locals ().
882 void
883 mono_debug_free_locals (MonoDebugLocalsInfo *info)
885 int i;
887 for (i = 0; i < info->num_locals; ++i)
888 g_free (info->locals [i].name);
889 g_free (info->locals);
890 g_free (info->code_blocks);
891 g_free (info);
895 * mono_debug_lookup_method_async_debug_info:
897 * Return information about the async stepping information of method.
898 * The result should be freed using mono_debug_free_async_debug_info ().
900 MonoDebugMethodAsyncInfo*
901 mono_debug_lookup_method_async_debug_info (MonoMethod *method)
903 MonoDebugMethodInfo *minfo;
904 MonoDebugMethodAsyncInfo *res = NULL;
906 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
907 return NULL;
909 mono_debugger_lock ();
910 minfo = mono_debug_lookup_method_internal (method);
911 if (!minfo || !minfo->handle) {
912 mono_debugger_unlock ();
913 return NULL;
916 if (minfo->handle->ppdb)
917 res = mono_ppdb_lookup_method_async_debug_info (minfo);
919 mono_debugger_unlock ();
921 return res;
925 * mono_debug_free_method_async_debug_info:
927 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
929 void
930 mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo *info)
932 if (info->num_awaits) {
933 g_free (info->yield_offsets);
934 g_free (info->resume_offsets);
935 g_free (info->move_next_method_token);
937 g_free (info);
941 * mono_debug_free_source_location:
942 * \param location A \c MonoDebugSourceLocation
943 * Frees the \p location.
945 void
946 mono_debug_free_source_location (MonoDebugSourceLocation *location)
948 if (location) {
949 g_free (location->source_file);
950 g_free (location);
954 static int (*get_seq_point) (MonoDomain *domain, MonoMethod *method, gint32 native_offset);
956 void
957 mono_install_get_seq_point (MonoGetSeqPointFunc func)
959 get_seq_point = func;
963 * mono_debug_print_stack_frame:
964 * \param native_offset Native offset within the \p method's machine code.
965 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
966 * used if you only want to use the location to print a stack frame.
968 gchar *
969 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
971 MonoDebugSourceLocation *location;
972 gchar *fname, *ptr, *res;
973 int offset;
975 fname = mono_method_full_name (method, TRUE);
976 for (ptr = fname; *ptr; ptr++) {
977 if (*ptr == ':') *ptr = '.';
980 location = mono_debug_lookup_source_location (method, native_offset, domain);
982 if (!location) {
983 if (mono_debug_initialized) {
984 mono_debugger_lock ();
985 offset = il_offset_from_address (method, domain, native_offset);
986 mono_debugger_unlock ();
987 } else {
988 offset = -1;
991 if (offset < 0 && get_seq_point)
992 offset = get_seq_point (domain, method, native_offset);
994 if (offset < 0)
995 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
996 else {
997 char *mvid = mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method->klass)->heap_guid.data);
998 char *aotid = mono_runtime_get_aotid ();
999 if (aotid)
1000 res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
1001 else
1002 res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);
1004 g_free (aotid);
1005 g_free (mvid);
1007 g_free (fname);
1008 return res;
1011 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1012 location->source_file, location->row);
1014 g_free (fname);
1015 mono_debug_free_source_location (location);
1016 return res;
1019 void
1020 mono_set_is_debugger_attached (gboolean attached)
1022 is_attached = attached;
1025 gboolean
1026 mono_is_debugger_attached (void)
1028 return is_attached;
1032 * Bundles
1035 typedef struct _BundledSymfile BundledSymfile;
1037 struct _BundledSymfile {
1038 BundledSymfile *next;
1039 const char *aname;
1040 const mono_byte *raw_contents;
1041 int size;
1044 static BundledSymfile *bundled_symfiles = NULL;
1047 * mono_register_symfile_for_assembly:
1049 void
1050 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1052 BundledSymfile *bsymfile;
1054 bsymfile = g_new0 (BundledSymfile, 1);
1055 bsymfile->aname = assembly_name;
1056 bsymfile->raw_contents = raw_contents;
1057 bsymfile->size = size;
1058 bsymfile->next = bundled_symfiles;
1059 bundled_symfiles = bsymfile;
1062 static MonoDebugHandle *
1063 open_symfile_from_bundle (MonoImage *image)
1065 BundledSymfile *bsymfile;
1067 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1068 if (strcmp (bsymfile->aname, image->module_name))
1069 continue;
1071 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
1074 return NULL;
1077 void
1078 mono_debugger_lock (void)
1080 g_assert (mono_debug_initialized);
1081 mono_os_mutex_lock (&debugger_lock_mutex);
1084 void
1085 mono_debugger_unlock (void)
1087 g_assert (mono_debug_initialized);
1088 mono_os_mutex_unlock (&debugger_lock_mutex);
1092 * mono_debug_enabled:
1094 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1096 mono_bool
1097 mono_debug_enabled (void)
1099 return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
1102 void
1103 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
1105 if (minfo->handle->ppdb)
1106 mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
1107 else
1108 mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);