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/assembly-internals.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/appdomain.h>
19 #include <mono/metadata/class-internals.h>
20 #include <mono/metadata/mono-debug.h>
21 #include <mono/metadata/debug-internals.h>
22 #include <mono/metadata/mono-endian.h>
23 #include <mono/metadata/gc-internals.h>
24 #include <mono/metadata/mempool.h>
25 #include <mono/metadata/debug-mono-symfile.h>
26 #include <mono/metadata/debug-mono-ppdb.h>
27 #include <mono/metadata/exception-internals.h>
28 #include <mono/metadata/runtime.h>
31 #if NO_UNALIGNED_ACCESS
32 #define WRITE_UNALIGNED(type, addr, val) \
33 memcpy(addr, &val, sizeof(type))
34 #define READ_UNALIGNED(type, addr, val) \
35 memcpy(&val, addr, sizeof(type))
37 #define WRITE_UNALIGNED(type, addr, val) \
38 (*(type *)(addr) = (val))
39 #define READ_UNALIGNED(type, addr, val) \
40 val = (*(type *)(addr))
43 /* This contains per-domain info */
46 GHashTable
*method_hash
;
49 /* This contains JIT debugging information about a method in serialized format */
50 struct _MonoDebugMethodAddress
{
51 const guint8
*code_start
;
53 guint8 data
[MONO_ZERO_LEN_ARRAY
];
56 static MonoDebugFormat mono_debug_format
= MONO_DEBUG_FORMAT_NONE
;
58 static gboolean mono_debug_initialized
= FALSE
;
59 /* Maps MonoImage -> MonoMonoDebugHandle */
60 static GHashTable
*mono_debug_handles
;
62 static mono_mutex_t debugger_lock_mutex
;
64 static gboolean is_attached
= FALSE
;
66 static MonoDebugHandle
*mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
);
68 static MonoDebugHandle
*mono_debug_get_image (MonoImage
*image
);
69 static void add_assembly (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error
);
71 static MonoDebugHandle
*open_symfile_from_bundle (MonoImage
*image
);
73 static DebugDomainInfo
*
74 get_domain_info (MonoDomain
*domain
)
76 g_assert (domain
->debug_info
);
78 return (DebugDomainInfo
*)domain
->debug_info
;
82 free_debug_handle (MonoDebugHandle
*handle
)
85 mono_ppdb_close (handle
);
87 mono_debug_close_mono_symbol_file (handle
->symfile
);
88 /* decrease the refcount added with mono_image_addref () */
89 mono_image_close (handle
->image
);
94 * Initialize debugging support.
96 * This method must be called after loading corlib,
97 * but before opening the application's main assembly because we need to set some
101 mono_debug_init (MonoDebugFormat format
)
103 g_assert (!mono_debug_initialized
);
104 if (format
== MONO_DEBUG_FORMAT_DEBUGGER
)
105 g_error ("The mdb debugger is no longer supported.");
107 mono_debug_initialized
= TRUE
;
108 mono_debug_format
= format
;
110 mono_os_mutex_init_recursive (&debugger_lock_mutex
);
112 mono_debugger_lock ();
114 mono_debug_handles
= g_hash_table_new_full
115 (NULL
, NULL
, NULL
, (GDestroyNotify
) free_debug_handle
);
117 mono_install_assembly_load_hook_v2 (add_assembly
, NULL
);
119 mono_debugger_unlock ();
123 mono_debug_open_image_from_memory (MonoImage
*image
, const guint8
*raw_contents
, int size
)
125 MONO_ENTER_GC_UNSAFE
;
126 if (!mono_debug_initialized
)
129 mono_debug_open_image (image
, raw_contents
, size
);
135 mono_debug_cleanup (void)
137 if (mono_debug_handles
)
138 g_hash_table_destroy (mono_debug_handles
);
139 mono_debug_handles
= NULL
;
143 * mono_debug_domain_create:
146 mono_debug_domain_create (MonoDomain
*domain
)
148 DebugDomainInfo
*info
;
150 if (!mono_debug_initialized
)
153 info
= g_new0 (DebugDomainInfo
, 1);
154 info
->mp
= mono_mempool_new ();
155 info
->method_hash
= g_hash_table_new (NULL
, NULL
);
157 domain
->debug_info
= info
;
161 mono_debug_domain_unload (MonoDomain
*domain
)
163 DebugDomainInfo
*info
= (DebugDomainInfo
*)domain
->debug_info
;
168 mono_mempool_destroy (info
->mp
);
169 g_hash_table_destroy (info
->method_hash
);
175 * LOCKING: Assumes the debug lock is held.
177 static MonoDebugHandle
*
178 mono_debug_get_image (MonoImage
*image
)
180 return (MonoDebugHandle
*)g_hash_table_lookup (mono_debug_handles
, image
);
184 * mono_debug_close_image:
187 mono_debug_close_image (MonoImage
*image
)
189 MonoDebugHandle
*handle
;
191 if (!mono_debug_initialized
)
194 mono_debugger_lock ();
196 handle
= mono_debug_get_image (image
);
198 mono_debugger_unlock ();
202 g_hash_table_remove (mono_debug_handles
, image
);
204 mono_debugger_unlock ();
208 mono_debug_get_handle (MonoImage
*image
)
210 return mono_debug_open_image (image
, NULL
, 0);
213 static MonoDebugHandle
*
214 mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
)
216 MonoDebugHandle
*handle
;
218 if (mono_image_is_dynamic (image
))
221 mono_debugger_lock ();
223 handle
= mono_debug_get_image (image
);
224 if (handle
!= NULL
) {
225 mono_debugger_unlock ();
229 handle
= g_new0 (MonoDebugHandle
, 1);
231 handle
->image
= image
;
232 mono_image_addref (image
);
234 /* Try a ppdb file first */
235 handle
->ppdb
= mono_ppdb_load_file (handle
->image
, raw_contents
, size
);
238 handle
->symfile
= mono_debug_open_mono_symbols (handle
, raw_contents
, size
, FALSE
);
240 g_hash_table_insert (mono_debug_handles
, image
, handle
);
242 mono_debugger_unlock ();
248 add_assembly (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error
)
250 MonoDebugHandle
*handle
;
253 mono_debugger_lock ();
254 image
= mono_assembly_get_image_internal (assembly
);
255 handle
= open_symfile_from_bundle (image
);
257 mono_debug_open_image (image
, NULL
, 0);
258 mono_debugger_unlock ();
261 struct LookupMethodData
263 MonoDebugMethodInfo
*minfo
;
268 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
270 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
271 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
277 data
->minfo
= mono_ppdb_lookup_method (handle
, data
->method
);
278 else if (handle
->symfile
)
279 data
->minfo
= mono_debug_symfile_lookup_method (handle
, data
->method
);
282 static MonoDebugMethodInfo
*
283 lookup_method (MonoMethod
*method
)
285 struct LookupMethodData data
;
288 data
.method
= method
;
290 if (!mono_debug_handles
)
293 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
298 * mono_debug_lookup_method:
300 * Lookup symbol file information for the method \p method. The returned
301 * \c MonoDebugMethodInfo is a private structure, but it can be passed to
302 * \c mono_debug_symfile_lookup_location.
304 MonoDebugMethodInfo
*
305 mono_debug_lookup_method (MonoMethod
*method
)
307 MonoDebugMethodInfo
*minfo
;
309 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
312 mono_debugger_lock ();
313 minfo
= lookup_method (method
);
314 mono_debugger_unlock ();
325 lookup_image_func (gpointer key
, gpointer value
, gpointer user_data
)
327 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
328 LookupImageData
*data
= (LookupImageData
*) user_data
;
333 if (handle
->image
== data
->image
&& (handle
->symfile
|| handle
->ppdb
))
338 mono_debug_image_has_debug_info (MonoImage
*image
)
340 LookupImageData data
;
342 if (!mono_debug_handles
)
345 memset (&data
, 0, sizeof (data
));
348 mono_debugger_lock ();
349 g_hash_table_foreach (mono_debug_handles
, lookup_image_func
, &data
);
350 mono_debugger_unlock ();
355 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
358 guint8 byte
= value
& 0x7f;
369 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
374 guint8 byte
= value
& 0x7f;
377 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
387 /* leb128 uses a maximum of 5 bytes for a 32 bit value */
388 #define LEB128_MAX_SIZE 5
389 #define WRITE_VARIABLE_MAX_SIZE (5 * LEB128_MAX_SIZE + sizeof (gpointer))
392 write_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
394 write_leb128 (var
->index
, ptr
, &ptr
);
395 write_sleb128 (var
->offset
, ptr
, &ptr
);
396 write_leb128 (var
->size
, ptr
, &ptr
);
397 write_leb128 (var
->begin_scope
, ptr
, &ptr
);
398 write_leb128 (var
->end_scope
, ptr
, &ptr
);
399 WRITE_UNALIGNED (gpointer
, ptr
, var
->type
);
400 ptr
+= sizeof (gpointer
);
405 * mono_debug_add_method:
407 MonoDebugMethodAddress
*
408 mono_debug_add_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
, MonoDomain
*domain
)
410 DebugDomainInfo
*info
;
411 MonoDebugMethodAddress
*address
;
412 guint8 buffer
[BUFSIZ
];
413 guint8
*ptr
, *oldptr
;
414 guint32 i
, size
, total_size
, max_size
;
416 info
= get_domain_info (domain
);
418 max_size
= (5 * LEB128_MAX_SIZE
) + 1 + (2 * LEB128_MAX_SIZE
* jit
->num_line_numbers
);
419 if (jit
->has_var_info
) {
423 max_size
+= WRITE_VARIABLE_MAX_SIZE
;
425 max_size
+= LEB128_MAX_SIZE
;
426 max_size
+= jit
->num_params
* WRITE_VARIABLE_MAX_SIZE
;
428 max_size
+= LEB128_MAX_SIZE
;
429 max_size
+= jit
->num_locals
* WRITE_VARIABLE_MAX_SIZE
;
432 if (jit
->gsharedvt_info_var
)
433 max_size
+= 2 * WRITE_VARIABLE_MAX_SIZE
;
436 if (max_size
> BUFSIZ
)
437 ptr
= oldptr
= (guint8
*)g_malloc (max_size
);
439 ptr
= oldptr
= buffer
;
441 write_leb128 (jit
->prologue_end
, ptr
, &ptr
);
442 write_leb128 (jit
->epilogue_begin
, ptr
, &ptr
);
444 write_leb128 (jit
->num_line_numbers
, ptr
, &ptr
);
445 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
446 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
448 write_sleb128 (lne
->il_offset
, ptr
, &ptr
);
449 write_sleb128 (lne
->native_offset
, ptr
, &ptr
);
451 write_leb128 (jit
->has_var_info
, ptr
, &ptr
);
452 if (jit
->has_var_info
) {
453 *ptr
++ = jit
->this_var
? 1 : 0;
455 write_variable (jit
->this_var
, ptr
, &ptr
);
457 write_leb128 (jit
->num_params
, ptr
, &ptr
);
458 for (i
= 0; i
< jit
->num_params
; i
++)
459 write_variable (&jit
->params
[i
], ptr
, &ptr
);
461 write_leb128 (jit
->num_locals
, ptr
, &ptr
);
462 for (i
= 0; i
< jit
->num_locals
; i
++)
463 write_variable (&jit
->locals
[i
], ptr
, &ptr
);
465 *ptr
++ = jit
->gsharedvt_info_var
? 1 : 0;
466 if (jit
->gsharedvt_info_var
) {
467 write_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
468 write_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
473 g_assert (size
< max_size
);
474 total_size
= size
+ sizeof (MonoDebugMethodAddress
);
476 mono_debugger_lock ();
478 if (method_is_dynamic (method
)) {
479 address
= (MonoDebugMethodAddress
*)g_malloc0 (total_size
);
481 address
= (MonoDebugMethodAddress
*)mono_mempool_alloc (info
->mp
, total_size
);
484 address
->code_start
= jit
->code_start
;
485 address
->code_size
= jit
->code_size
;
487 memcpy (&address
->data
, oldptr
, size
);
488 if (max_size
> BUFSIZ
)
491 g_hash_table_insert (info
->method_hash
, method
, address
);
493 mono_debugger_unlock ();
498 mono_debug_remove_method (MonoMethod
*method
, MonoDomain
*domain
)
500 DebugDomainInfo
*info
;
501 MonoDebugMethodAddress
*address
;
503 if (!mono_debug_initialized
)
506 g_assert (method_is_dynamic (method
));
508 info
= get_domain_info (domain
);
510 mono_debugger_lock ();
512 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (info
->method_hash
, method
);
516 g_hash_table_remove (info
->method_hash
, method
);
518 mono_debugger_unlock ();
522 * mono_debug_add_delegate_trampoline:
525 mono_debug_add_delegate_trampoline (gpointer code
, int size
)
530 read_leb128 (guint8
*ptr
, guint8
**rptr
)
532 guint32 result
= 0, shift
= 0;
535 guint8 byte
= *ptr
++;
537 result
|= (byte
& 0x7f) << shift
;
538 if ((byte
& 0x80) == 0)
548 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
554 guint8 byte
= *ptr
++;
556 result
|= (byte
& 0x7f) << shift
;
562 if ((shift
< 32) && (byte
& 0x40))
563 result
|= - (1 << shift
);
572 read_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
574 var
->index
= read_leb128 (ptr
, &ptr
);
575 var
->offset
= read_sleb128 (ptr
, &ptr
);
576 var
->size
= read_leb128 (ptr
, &ptr
);
577 var
->begin_scope
= read_leb128 (ptr
, &ptr
);
578 var
->end_scope
= read_leb128 (ptr
, &ptr
);
579 READ_UNALIGNED (MonoType
*, ptr
, var
->type
);
580 ptr
+= sizeof (gpointer
);
585 free_method_jit_info (MonoDebugMethodJitInfo
*jit
, gboolean stack
)
589 g_free (jit
->line_numbers
);
590 g_free (jit
->this_var
);
591 g_free (jit
->params
);
592 g_free (jit
->locals
);
593 g_free (jit
->gsharedvt_info_var
);
594 g_free (jit
->gsharedvt_locals_var
);
600 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
602 return free_method_jit_info (jit
, FALSE
);
605 static MonoDebugMethodJitInfo
*
606 mono_debug_read_method (MonoDebugMethodAddress
*address
, MonoDebugMethodJitInfo
*jit
)
611 memset (jit
, 0, sizeof (*jit
));
612 jit
->code_start
= address
->code_start
;
613 jit
->code_size
= address
->code_size
;
615 ptr
= (guint8
*) &address
->data
;
617 jit
->prologue_end
= read_leb128 (ptr
, &ptr
);
618 jit
->epilogue_begin
= read_leb128 (ptr
, &ptr
);
620 jit
->num_line_numbers
= read_leb128 (ptr
, &ptr
);
621 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
622 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
623 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
625 lne
->il_offset
= read_sleb128 (ptr
, &ptr
);
626 lne
->native_offset
= read_sleb128 (ptr
, &ptr
);
628 jit
->has_var_info
= read_leb128 (ptr
, &ptr
);
629 if (jit
->has_var_info
) {
631 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
632 read_variable (jit
->this_var
, ptr
, &ptr
);
635 jit
->num_params
= read_leb128 (ptr
, &ptr
);
636 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
637 for (i
= 0; i
< jit
->num_params
; i
++)
638 read_variable (&jit
->params
[i
], ptr
, &ptr
);
640 jit
->num_locals
= read_leb128 (ptr
, &ptr
);
641 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
642 for (i
= 0; i
< jit
->num_locals
; i
++)
643 read_variable (&jit
->locals
[i
], ptr
, &ptr
);
646 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
647 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
648 read_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
649 read_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
656 static MonoDebugMethodJitInfo
*
657 find_method (MonoMethod
*method
, MonoDomain
*domain
, MonoDebugMethodJitInfo
*jit
)
659 DebugDomainInfo
*info
;
660 MonoDebugMethodAddress
*address
;
662 info
= get_domain_info (domain
);
663 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (info
->method_hash
, method
);
668 return mono_debug_read_method (address
, jit
);
671 MonoDebugMethodJitInfo
*
672 mono_debug_find_method (MonoMethod
*method
, MonoDomain
*domain
)
674 MonoDebugMethodJitInfo
*res
= g_new0 (MonoDebugMethodJitInfo
, 1);
676 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
679 mono_debugger_lock ();
680 find_method (method
, domain
, res
);
681 mono_debugger_unlock ();
685 MonoDebugMethodAddressList
*
686 mono_debug_lookup_method_addresses (MonoMethod
*method
)
688 g_assert_not_reached ();
693 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
695 MonoDebugMethodJitInfo mem
;
698 MonoDebugMethodJitInfo
*jit
= find_method (method
, domain
, &mem
);
699 if (!jit
|| !jit
->line_numbers
)
700 goto cleanup_and_fail
;
702 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
703 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
705 if (lne
.native_offset
<= native_offset
) {
706 free_method_jit_info (jit
, TRUE
);
707 return lne
.il_offset
;
712 free_method_jit_info (jit
, TRUE
);
717 * mono_debug_il_offset_from_address:
719 * Compute the IL offset corresponding to \p native_offset inside the native
720 * code of \p method in \p domain.
723 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
727 mono_debugger_lock ();
729 res
= il_offset_from_address (method
, domain
, native_offset
);
731 mono_debugger_unlock ();
737 * mono_debug_lookup_source_location:
738 * \param address Native offset within the \p method's machine code.
739 * Lookup the source code corresponding to the machine instruction located at
740 * native offset \p address within \p method.
741 * The returned \c MonoDebugSourceLocation contains both file / line number
742 * information and the corresponding IL offset. It must be freed by
743 * \c mono_debug_free_source_location.
745 MonoDebugSourceLocation
*
746 mono_debug_lookup_source_location (MonoMethod
*method
, guint32 address
, MonoDomain
*domain
)
748 MonoDebugMethodInfo
*minfo
;
749 MonoDebugSourceLocation
*location
;
752 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
755 mono_debugger_lock ();
756 minfo
= lookup_method (method
);
757 if (!minfo
|| !minfo
->handle
) {
758 mono_debugger_unlock ();
762 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
763 mono_debugger_unlock ();
767 offset
= il_offset_from_address (method
, domain
, address
);
769 mono_debugger_unlock ();
773 if (minfo
->handle
->ppdb
)
774 location
= mono_ppdb_lookup_location (minfo
, offset
);
776 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
777 mono_debugger_unlock ();
782 * mono_debug_lookup_source_location_by_il:
784 * Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
786 MonoDebugSourceLocation
*
787 mono_debug_lookup_source_location_by_il (MonoMethod
*method
, guint32 il_offset
, MonoDomain
*domain
)
789 MonoDebugMethodInfo
*minfo
;
790 MonoDebugSourceLocation
*location
;
792 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
795 mono_debugger_lock ();
796 minfo
= lookup_method (method
);
797 if (!minfo
|| !minfo
->handle
) {
798 mono_debugger_unlock ();
802 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
803 mono_debugger_unlock ();
807 if (minfo
->handle
->ppdb
)
808 location
= mono_ppdb_lookup_location (minfo
, il_offset
);
810 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
811 mono_debugger_unlock ();
815 MonoDebugSourceLocation
*
816 mono_debug_method_lookup_location (MonoDebugMethodInfo
*minfo
, int il_offset
)
818 MonoDebugSourceLocation
*location
;
820 mono_debugger_lock ();
821 if (minfo
->handle
->ppdb
)
822 location
= mono_ppdb_lookup_location (minfo
, il_offset
);
824 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
825 mono_debugger_unlock ();
830 * mono_debug_lookup_locals:
832 * Return information about the local variables of MINFO.
833 * The result should be freed using mono_debug_free_locals ().
836 mono_debug_lookup_locals (MonoMethod
*method
)
838 MonoDebugMethodInfo
*minfo
;
839 MonoDebugLocalsInfo
*res
;
841 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
844 mono_debugger_lock ();
845 minfo
= lookup_method (method
);
846 if (!minfo
|| !minfo
->handle
) {
847 mono_debugger_unlock ();
851 if (minfo
->handle
->ppdb
) {
852 res
= mono_ppdb_lookup_locals (minfo
);
854 if (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))
857 res
= mono_debug_symfile_lookup_locals (minfo
);
859 mono_debugger_unlock ();
865 * mono_debug_free_locals:
867 * Free all the data allocated by mono_debug_lookup_locals ().
870 mono_debug_free_locals (MonoDebugLocalsInfo
*info
)
874 for (i
= 0; i
< info
->num_locals
; ++i
)
875 g_free (info
->locals
[i
].name
);
876 g_free (info
->locals
);
877 g_free (info
->code_blocks
);
882 * mono_debug_lookup_method_async_debug_info:
884 * Return information about the async stepping information of method.
885 * The result should be freed using mono_debug_free_async_debug_info ().
887 MonoDebugMethodAsyncInfo
*
888 mono_debug_lookup_method_async_debug_info (MonoMethod
*method
)
890 MonoDebugMethodInfo
*minfo
;
891 MonoDebugMethodAsyncInfo
*res
= NULL
;
893 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
896 mono_debugger_lock ();
897 minfo
= lookup_method (method
);
898 if (!minfo
|| !minfo
->handle
) {
899 mono_debugger_unlock ();
903 if (minfo
->handle
->ppdb
)
904 res
= mono_ppdb_lookup_method_async_debug_info (minfo
);
906 mono_debugger_unlock ();
912 * mono_debug_free_method_async_debug_info:
914 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
917 mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo
*info
)
919 if (info
->num_awaits
) {
920 g_free (info
->yield_offsets
);
921 g_free (info
->resume_offsets
);
922 g_free (info
->move_next_method_token
);
928 * mono_debug_free_source_location:
929 * \param location A \c MonoDebugSourceLocation
930 * Frees the \p location.
933 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
936 g_free (location
->source_file
);
941 static int (*get_seq_point
) (MonoDomain
*domain
, MonoMethod
*method
, gint32 native_offset
);
944 mono_install_get_seq_point (MonoGetSeqPointFunc func
)
946 get_seq_point
= func
;
950 * mono_debug_print_stack_frame:
951 * \param native_offset Native offset within the \p method's machine code.
952 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
953 * used if you only want to use the location to print a stack frame.
956 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
958 MonoDebugSourceLocation
*location
;
959 gchar
*fname
, *ptr
, *res
;
962 fname
= mono_method_full_name (method
, TRUE
);
963 for (ptr
= fname
; *ptr
; ptr
++) {
964 if (*ptr
== ':') *ptr
= '.';
967 location
= mono_debug_lookup_source_location (method
, native_offset
, domain
);
970 if (mono_debug_initialized
) {
971 mono_debugger_lock ();
972 offset
= il_offset_from_address (method
, domain
, native_offset
);
973 mono_debugger_unlock ();
978 if (offset
< 0 && get_seq_point
)
979 offset
= get_seq_point (domain
, method
, native_offset
);
982 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
984 char *mvid
= mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method
->klass
)->heap_guid
.data
);
985 char *aotid
= mono_runtime_get_aotid ();
987 res
= g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname
, offset
, mvid
, aotid
);
989 res
= g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname
, offset
, mvid
);
998 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
999 location
->source_file
, location
->row
);
1002 mono_debug_free_source_location (location
);
1007 mono_set_is_debugger_attached (gboolean attached
)
1009 is_attached
= attached
;
1013 mono_is_debugger_attached (void)
1022 typedef struct _BundledSymfile BundledSymfile
;
1024 struct _BundledSymfile
{
1025 BundledSymfile
*next
;
1027 const mono_byte
*raw_contents
;
1031 static BundledSymfile
*bundled_symfiles
= NULL
;
1034 * mono_register_symfile_for_assembly:
1037 mono_register_symfile_for_assembly (const char *assembly_name
, const mono_byte
*raw_contents
, int size
)
1039 BundledSymfile
*bsymfile
;
1041 bsymfile
= g_new0 (BundledSymfile
, 1);
1042 bsymfile
->aname
= assembly_name
;
1043 bsymfile
->raw_contents
= raw_contents
;
1044 bsymfile
->size
= size
;
1045 bsymfile
->next
= bundled_symfiles
;
1046 bundled_symfiles
= bsymfile
;
1049 static MonoDebugHandle
*
1050 open_symfile_from_bundle (MonoImage
*image
)
1052 BundledSymfile
*bsymfile
;
1054 for (bsymfile
= bundled_symfiles
; bsymfile
; bsymfile
= bsymfile
->next
) {
1055 if (strcmp (bsymfile
->aname
, image
->module_name
))
1058 return mono_debug_open_image (image
, bsymfile
->raw_contents
, bsymfile
->size
);
1065 mono_debugger_lock (void)
1067 g_assert (mono_debug_initialized
);
1068 mono_os_mutex_lock (&debugger_lock_mutex
);
1072 mono_debugger_unlock (void)
1074 g_assert (mono_debug_initialized
);
1075 mono_os_mutex_unlock (&debugger_lock_mutex
);
1079 * mono_debug_enabled:
1081 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1084 mono_debug_enabled (void)
1086 return mono_debug_format
!= MONO_DEBUG_FORMAT_NONE
;
1090 mono_debug_get_seq_points (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int **source_files
, MonoSymSeqPoint
**seq_points
, int *n_seq_points
)
1092 if (minfo
->handle
->ppdb
)
1093 mono_ppdb_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);
1095 mono_debug_symfile_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);
1099 mono_debug_image_get_sourcelink (MonoImage
*image
)
1101 MonoDebugHandle
*handle
= mono_debug_get_handle (image
);
1103 if (handle
&& handle
->ppdb
)
1104 return mono_ppdb_get_sourcelink (handle
);