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.
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>
30 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
32 #if NO_UNALIGNED_ACCESS
33 #define WRITE_UNALIGNED(type, addr, val) \
34 memcpy(addr, &val, sizeof(type))
35 #define READ_UNALIGNED(type, addr, val) \
36 memcpy(&val, addr, sizeof(type))
38 #define WRITE_UNALIGNED(type, addr, val) \
39 (*(type *)(addr) = (val))
40 #define READ_UNALIGNED(type, addr, val) \
41 val = (*(type *)(addr))
44 /* This contains per-domain info */
45 struct _MonoDebugDataTable {
47 GHashTable *method_address_hash;
50 /* This contains JIT debugging information about a method in serialized format */
51 struct _MonoDebugMethodAddress {
52 const guint8 *code_start;
54 guint8 data [MONO_ZERO_LEN_ARRAY];
57 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
59 static gboolean mono_debug_initialized = FALSE;
60 /* Maps MonoImage -> MonoMonoDebugHandle */
61 static GHashTable *mono_debug_handles;
62 /* Maps MonoDomain -> MonoDataTable */
63 static GHashTable *data_table_hash;
65 static mono_mutex_t debugger_lock_mutex;
67 static gboolean is_attached = FALSE;
69 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
71 static MonoDebugHandle *mono_debug_get_image (MonoImage *image);
72 static void mono_debug_add_assembly (MonoAssembly *assembly,
75 static MonoDebugHandle *open_symfile_from_bundle (MonoImage *image);
77 static MonoDebugDataTable *
78 create_data_table (MonoDomain *domain)
80 MonoDebugDataTable *table;
82 table = g_new0 (MonoDebugDataTable, 1);
84 table->mp = mono_mempool_new ();
85 table->method_address_hash = g_hash_table_new (NULL, NULL);
88 g_hash_table_insert (data_table_hash, domain, table);
94 free_data_table (MonoDebugDataTable *table)
96 mono_mempool_destroy (table->mp);
97 g_hash_table_destroy (table->method_address_hash);
102 static MonoDebugDataTable *
103 lookup_data_table (MonoDomain *domain)
105 MonoDebugDataTable *table;
107 table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
109 g_error ("lookup_data_table () failed for %p\n", domain);
116 free_debug_handle (MonoDebugHandle *handle)
119 mono_ppdb_close (handle);
121 mono_debug_close_mono_symbol_file (handle->symfile);
122 /* decrease the refcount added with mono_image_addref () */
123 mono_image_close (handle->image);
128 * Initialize debugging support.
130 * This method must be called after loading corlib,
131 * but before opening the application's main assembly because we need to set some
135 mono_debug_init (MonoDebugFormat format)
137 g_assert (!mono_debug_initialized);
138 if (format == MONO_DEBUG_FORMAT_DEBUGGER)
139 g_error ("The mdb debugger is no longer supported.");
141 mono_debug_initialized = TRUE;
142 mono_debug_format = format;
144 mono_os_mutex_init_recursive (&debugger_lock_mutex);
146 mono_debugger_lock ();
148 mono_debug_handles = g_hash_table_new_full
149 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
151 data_table_hash = g_hash_table_new_full (
152 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
154 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
156 mono_debugger_unlock ();
160 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
162 if (!mono_debug_initialized)
165 mono_debug_open_image (image, raw_contents, size);
169 mono_debug_cleanup (void)
171 if (mono_debug_handles)
172 g_hash_table_destroy (mono_debug_handles);
173 mono_debug_handles = NULL;
175 if (data_table_hash) {
176 g_hash_table_destroy (data_table_hash);
177 data_table_hash = NULL;
182 * mono_debug_domain_create:
185 mono_debug_domain_create (MonoDomain *domain)
187 if (!mono_debug_initialized)
190 mono_debugger_lock ();
192 create_data_table (domain);
194 mono_debugger_unlock ();
198 mono_debug_domain_unload (MonoDomain *domain)
200 MonoDebugDataTable *table;
202 if (!mono_debug_initialized)
205 mono_debugger_lock ();
207 table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
209 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
210 domain, mono_domain_get_id (domain));
211 mono_debugger_unlock ();
215 g_hash_table_remove (data_table_hash, domain);
217 mono_debugger_unlock ();
221 * LOCKING: Assumes the debug lock is held.
223 static MonoDebugHandle *
224 mono_debug_get_image (MonoImage *image)
226 return (MonoDebugHandle *)g_hash_table_lookup (mono_debug_handles, image);
230 * mono_debug_close_image:
233 mono_debug_close_image (MonoImage *image)
235 MonoDebugHandle *handle;
237 if (!mono_debug_initialized)
240 mono_debugger_lock ();
242 handle = mono_debug_get_image (image);
244 mono_debugger_unlock ();
248 g_hash_table_remove (mono_debug_handles, image);
250 mono_debugger_unlock ();
253 static MonoDebugHandle *
254 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
256 MonoDebugHandle *handle;
258 if (mono_image_is_dynamic (image))
261 mono_debugger_lock ();
263 handle = mono_debug_get_image (image);
264 if (handle != NULL) {
265 mono_debugger_unlock ();
269 handle = g_new0 (MonoDebugHandle, 1);
271 handle->image = image;
272 mono_image_addref (image);
274 /* Try a ppdb file first */
275 handle->ppdb = mono_ppdb_load_file (handle->image, raw_contents, size);
278 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, FALSE);
280 g_hash_table_insert (mono_debug_handles, image, handle);
282 mono_debugger_unlock ();
288 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
290 MonoDebugHandle *handle;
293 mono_debugger_lock ();
294 image = mono_assembly_get_image (assembly);
295 handle = open_symfile_from_bundle (image);
297 mono_debug_open_image (image, NULL, 0);
298 mono_debugger_unlock ();
301 struct LookupMethodData
303 MonoDebugMethodInfo *minfo;
308 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
310 MonoDebugHandle *handle = (MonoDebugHandle *) value;
311 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
317 data->minfo = mono_ppdb_lookup_method (handle, data->method);
318 else if (handle->symfile)
319 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
322 static MonoDebugMethodInfo *
323 mono_debug_lookup_method_internal (MonoMethod *method)
325 struct LookupMethodData data;
328 data.method = method;
330 if (!mono_debug_handles)
333 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
338 * mono_debug_lookup_method:
340 * Lookup symbol file information for the method \p method. The returned
341 * \c MonoDebugMethodInfo is a private structure, but it can be passed to
342 * \c mono_debug_symfile_lookup_location.
344 MonoDebugMethodInfo *
345 mono_debug_lookup_method (MonoMethod *method)
347 MonoDebugMethodInfo *minfo;
349 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
352 mono_debugger_lock ();
353 minfo = mono_debug_lookup_method_internal (method);
354 mono_debugger_unlock ();
365 lookup_image_func (gpointer key, gpointer value, gpointer user_data)
367 MonoDebugHandle *handle = (MonoDebugHandle *) value;
368 LookupImageData *data = (LookupImageData *) user_data;
373 if (handle->image == data->image && handle->symfile)
378 mono_debug_image_has_debug_info (MonoImage *image)
380 LookupImageData data;
382 if (!mono_debug_handles)
385 memset (&data, 0, sizeof (data));
388 mono_debugger_lock ();
389 g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
390 mono_debugger_unlock ();
395 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
398 guint8 byte = value & 0x7f;
409 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
414 guint8 byte = value & 0x7f;
417 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
428 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
430 write_leb128 (var->index, ptr, &ptr);
431 write_sleb128 (var->offset, ptr, &ptr);
432 write_leb128 (var->size, ptr, &ptr);
433 write_leb128 (var->begin_scope, ptr, &ptr);
434 write_leb128 (var->end_scope, ptr, &ptr);
435 WRITE_UNALIGNED (gpointer, ptr, var->type);
436 ptr += sizeof (gpointer);
441 * mono_debug_add_method:
443 MonoDebugMethodAddress *
444 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
446 MonoDebugDataTable *table;
447 MonoDebugMethodAddress *address;
448 guint8 buffer [BUFSIZ];
449 guint8 *ptr, *oldptr;
450 guint32 i, size, total_size, max_size;
452 mono_debugger_lock ();
454 table = lookup_data_table (domain);
456 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
457 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
459 if (max_size > BUFSIZ)
460 ptr = oldptr = (guint8 *)g_malloc (max_size);
462 ptr = oldptr = buffer;
464 write_leb128 (jit->prologue_end, ptr, &ptr);
465 write_leb128 (jit->epilogue_begin, ptr, &ptr);
467 write_leb128 (jit->num_line_numbers, ptr, &ptr);
468 for (i = 0; i < jit->num_line_numbers; i++) {
469 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
471 write_sleb128 (lne->il_offset, ptr, &ptr);
472 write_sleb128 (lne->native_offset, ptr, &ptr);
474 write_leb128 (jit->has_var_info, ptr, &ptr);
475 if (jit->has_var_info) {
476 *ptr++ = jit->this_var ? 1 : 0;
478 write_variable (jit->this_var, ptr, &ptr);
480 write_leb128 (jit->num_params, ptr, &ptr);
481 for (i = 0; i < jit->num_params; i++)
482 write_variable (&jit->params [i], ptr, &ptr);
484 write_leb128 (jit->num_locals, ptr, &ptr);
485 for (i = 0; i < jit->num_locals; i++)
486 write_variable (&jit->locals [i], ptr, &ptr);
488 *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
489 if (jit->gsharedvt_info_var) {
490 write_variable (jit->gsharedvt_info_var, ptr, &ptr);
491 write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
496 g_assert (size < max_size);
497 total_size = size + sizeof (MonoDebugMethodAddress);
499 if (method_is_dynamic (method)) {
500 address = (MonoDebugMethodAddress *)g_malloc0 (total_size);
502 address = (MonoDebugMethodAddress *)mono_mempool_alloc (table->mp, total_size);
505 address->code_start = jit->code_start;
506 address->code_size = jit->code_size;
508 memcpy (&address->data, oldptr, size);
509 if (max_size > BUFSIZ)
512 g_hash_table_insert (table->method_address_hash, method, address);
514 mono_debugger_unlock ();
519 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
521 MonoDebugDataTable *table;
522 MonoDebugMethodAddress *address;
524 if (!mono_debug_initialized)
527 g_assert (method_is_dynamic (method));
529 mono_debugger_lock ();
531 table = lookup_data_table (domain);
533 address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
537 g_hash_table_remove (table->method_address_hash, method);
539 mono_debugger_unlock ();
543 * mono_debug_add_delegate_trampoline:
546 mono_debug_add_delegate_trampoline (gpointer code, int size)
550 static inline guint32
551 read_leb128 (guint8 *ptr, guint8 **rptr)
553 guint32 result = 0, shift = 0;
556 guint8 byte = *ptr++;
558 result |= (byte & 0x7f) << shift;
559 if ((byte & 0x80) == 0)
569 read_sleb128 (guint8 *ptr, guint8 **rptr)
575 guint8 byte = *ptr++;
577 result |= (byte & 0x7f) << shift;
583 if ((shift < 32) && (byte & 0x40))
584 result |= - (1 << shift);
593 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
595 var->index = read_leb128 (ptr, &ptr);
596 var->offset = read_sleb128 (ptr, &ptr);
597 var->size = read_leb128 (ptr, &ptr);
598 var->begin_scope = read_leb128 (ptr, &ptr);
599 var->end_scope = read_leb128 (ptr, &ptr);
600 READ_UNALIGNED (MonoType *, ptr, var->type);
601 ptr += sizeof (gpointer);
606 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
610 g_free (jit->line_numbers);
611 g_free (jit->this_var);
612 g_free (jit->params);
613 g_free (jit->locals);
614 g_free (jit->gsharedvt_info_var);
615 g_free (jit->gsharedvt_locals_var);
619 static MonoDebugMethodJitInfo *
620 mono_debug_read_method (MonoDebugMethodAddress *address)
622 MonoDebugMethodJitInfo *jit;
626 jit = g_new0 (MonoDebugMethodJitInfo, 1);
627 jit->code_start = address->code_start;
628 jit->code_size = address->code_size;
630 ptr = (guint8 *) &address->data;
632 jit->prologue_end = read_leb128 (ptr, &ptr);
633 jit->epilogue_begin = read_leb128 (ptr, &ptr);
635 jit->num_line_numbers = read_leb128 (ptr, &ptr);
636 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
637 for (i = 0; i < jit->num_line_numbers; i++) {
638 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
640 lne->il_offset = read_sleb128 (ptr, &ptr);
641 lne->native_offset = read_sleb128 (ptr, &ptr);
643 jit->has_var_info = read_leb128 (ptr, &ptr);
644 if (jit->has_var_info) {
646 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
647 read_variable (jit->this_var, ptr, &ptr);
650 jit->num_params = read_leb128 (ptr, &ptr);
651 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
652 for (i = 0; i < jit->num_params; i++)
653 read_variable (&jit->params [i], ptr, &ptr);
655 jit->num_locals = read_leb128 (ptr, &ptr);
656 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
657 for (i = 0; i < jit->num_locals; i++)
658 read_variable (&jit->locals [i], ptr, &ptr);
661 jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
662 jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
663 read_variable (jit->gsharedvt_info_var, ptr, &ptr);
664 read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
671 static MonoDebugMethodJitInfo *
672 find_method (MonoMethod *method, MonoDomain *domain)
674 MonoDebugDataTable *table;
675 MonoDebugMethodAddress *address;
677 table = lookup_data_table (domain);
678 address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
683 return mono_debug_read_method (address);
686 MonoDebugMethodJitInfo *
687 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
689 MonoDebugMethodJitInfo *res;
691 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
694 mono_debugger_lock ();
695 res = find_method (method, domain);
696 mono_debugger_unlock ();
700 MonoDebugMethodAddressList *
701 mono_debug_lookup_method_addresses (MonoMethod *method)
703 g_assert_not_reached ();
708 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
710 MonoDebugMethodJitInfo *jit;
713 jit = find_method (method, domain);
714 if (!jit || !jit->line_numbers)
715 goto cleanup_and_fail;
717 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
718 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
720 if (lne.native_offset <= native_offset) {
721 mono_debug_free_method_jit_info (jit);
722 return lne.il_offset;
727 mono_debug_free_method_jit_info (jit);
732 * mono_debug_il_offset_from_address:
734 * Compute the IL offset corresponding to \p native_offset inside the native
735 * code of \p method in \p domain.
738 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
742 mono_debugger_lock ();
744 res = il_offset_from_address (method, domain, native_offset);
746 mono_debugger_unlock ();
752 * mono_debug_lookup_source_location:
753 * \param address Native offset within the \p method's machine code.
754 * Lookup the source code corresponding to the machine instruction located at
755 * native offset \p address within \p method.
756 * The returned \c MonoDebugSourceLocation contains both file / line number
757 * information and the corresponding IL offset. It must be freed by
758 * \c mono_debug_free_source_location.
760 MonoDebugSourceLocation *
761 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
763 MonoDebugMethodInfo *minfo;
764 MonoDebugSourceLocation *location;
767 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
770 mono_debugger_lock ();
771 minfo = mono_debug_lookup_method_internal (method);
772 if (!minfo || !minfo->handle) {
773 mono_debugger_unlock ();
777 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
778 mono_debugger_unlock ();
782 offset = il_offset_from_address (method, domain, address);
784 mono_debugger_unlock ();
788 if (minfo->handle->ppdb)
789 location = mono_ppdb_lookup_location (minfo, offset);
791 location = mono_debug_symfile_lookup_location (minfo, offset);
792 mono_debugger_unlock ();
797 * mono_debug_lookup_source_location_by_il:
799 * Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
801 MonoDebugSourceLocation *
802 mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain)
804 MonoDebugMethodInfo *minfo;
805 MonoDebugSourceLocation *location;
807 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
810 mono_debugger_lock ();
811 minfo = mono_debug_lookup_method_internal (method);
812 if (!minfo || !minfo->handle) {
813 mono_debugger_unlock ();
817 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
818 mono_debugger_unlock ();
822 if (minfo->handle->ppdb)
823 location = mono_ppdb_lookup_location (minfo, il_offset);
825 location = mono_debug_symfile_lookup_location (minfo, il_offset);
826 mono_debugger_unlock ();
830 MonoDebugSourceLocation *
831 mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
833 MonoDebugSourceLocation *location;
835 mono_debugger_lock ();
836 if (minfo->handle->ppdb)
837 location = mono_ppdb_lookup_location (minfo, il_offset);
839 location = mono_debug_symfile_lookup_location (minfo, il_offset);
840 mono_debugger_unlock ();
845 * mono_debug_lookup_locals:
847 * Return information about the local variables of MINFO.
848 * The result should be freed using mono_debug_free_locals ().
851 mono_debug_lookup_locals (MonoMethod *method)
853 MonoDebugMethodInfo *minfo;
854 MonoDebugLocalsInfo *res;
856 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
859 mono_debugger_lock ();
860 minfo = mono_debug_lookup_method_internal (method);
861 if (!minfo || !minfo->handle) {
862 mono_debugger_unlock ();
866 if (minfo->handle->ppdb) {
867 res = mono_ppdb_lookup_locals (minfo);
869 if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
872 res = mono_debug_symfile_lookup_locals (minfo);
874 mono_debugger_unlock ();
880 * mono_debug_free_locals:
882 * Free all the data allocated by mono_debug_lookup_locals ().
885 mono_debug_free_locals (MonoDebugLocalsInfo *info)
889 for (i = 0; i < info->num_locals; ++i)
890 g_free (info->locals [i].name);
891 g_free (info->locals);
892 g_free (info->code_blocks);
897 * mono_debug_lookup_method_async_debug_info:
899 * Return information about the async stepping information of method.
900 * The result should be freed using mono_debug_free_async_debug_info ().
902 MonoDebugMethodAsyncInfo*
903 mono_debug_lookup_method_async_debug_info (MonoMethod *method)
905 MonoDebugMethodInfo *minfo;
906 MonoDebugMethodAsyncInfo *res = NULL;
908 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
911 mono_debugger_lock ();
912 minfo = mono_debug_lookup_method_internal (method);
913 if (!minfo || !minfo->handle) {
914 mono_debugger_unlock ();
918 if (minfo->handle->ppdb)
919 res = mono_ppdb_lookup_method_async_debug_info (minfo);
921 mono_debugger_unlock ();
927 * mono_debug_free_method_async_debug_info:
929 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
932 mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo *info)
934 if (info->num_awaits) {
935 g_free (info->yield_offsets);
936 g_free (info->resume_offsets);
937 g_free (info->move_next_method_token);
943 * mono_debug_free_source_location:
944 * \param location A \c MonoDebugSourceLocation
945 * Frees the \p location.
948 mono_debug_free_source_location (MonoDebugSourceLocation *location)
951 g_free (location->source_file);
956 static int (*get_seq_point) (MonoDomain *domain, MonoMethod *method, gint32 native_offset);
959 mono_install_get_seq_point (MonoGetSeqPointFunc func)
961 get_seq_point = func;
965 * mono_debug_print_stack_frame:
966 * \param native_offset Native offset within the \p method's machine code.
967 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
968 * used if you only want to use the location to print a stack frame.
971 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
973 MonoDebugSourceLocation *location;
974 gchar *fname, *ptr, *res;
977 fname = mono_method_full_name (method, TRUE);
978 for (ptr = fname; *ptr; ptr++) {
979 if (*ptr == ':') *ptr = '.';
982 location = mono_debug_lookup_source_location (method, native_offset, domain);
985 if (mono_debug_initialized) {
986 mono_debugger_lock ();
987 offset = il_offset_from_address (method, domain, native_offset);
988 mono_debugger_unlock ();
993 if (offset < 0 && get_seq_point)
994 offset = get_seq_point (domain, method, native_offset);
997 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
999 char *mvid = mono_guid_to_string_minimal ((uint8_t*)method->klass->image->heap_guid.data);
1000 char *aotid = mono_runtime_get_aotid ();
1002 res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
1004 res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);
1013 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1014 location->source_file, location->row);
1017 mono_debug_free_source_location (location);
1022 mono_set_is_debugger_attached (gboolean attached)
1024 is_attached = attached;
1028 mono_is_debugger_attached (void)
1037 typedef struct _BundledSymfile BundledSymfile;
1039 struct _BundledSymfile {
1040 BundledSymfile *next;
1042 const mono_byte *raw_contents;
1046 static BundledSymfile *bundled_symfiles = NULL;
1049 * mono_register_symfile_for_assembly:
1052 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1054 BundledSymfile *bsymfile;
1056 bsymfile = g_new0 (BundledSymfile, 1);
1057 bsymfile->aname = assembly_name;
1058 bsymfile->raw_contents = raw_contents;
1059 bsymfile->size = size;
1060 bsymfile->next = bundled_symfiles;
1061 bundled_symfiles = bsymfile;
1064 static MonoDebugHandle *
1065 open_symfile_from_bundle (MonoImage *image)
1067 BundledSymfile *bsymfile;
1069 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1070 if (strcmp (bsymfile->aname, image->module_name))
1073 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
1080 mono_debugger_lock (void)
1082 g_assert (mono_debug_initialized);
1083 mono_os_mutex_lock (&debugger_lock_mutex);
1087 mono_debugger_unlock (void)
1089 g_assert (mono_debug_initialized);
1090 mono_os_mutex_unlock (&debugger_lock_mutex);
1094 * mono_debug_enabled:
1096 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1099 mono_debug_enabled (void)
1101 return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
1105 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
1107 if (minfo->handle->ppdb)
1108 mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
1110 mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);