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 */
44 struct _MonoDebugDataTable
{
46 GHashTable
*method_address_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
;
61 /* Maps MonoDomain -> MonoDataTable */
62 static GHashTable
*data_table_hash
;
64 static mono_mutex_t debugger_lock_mutex
;
66 static gboolean is_attached
= FALSE
;
68 static MonoDebugHandle
*mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
);
70 static MonoDebugHandle
*mono_debug_get_image (MonoImage
*image
);
71 static void mono_debug_add_assembly (MonoAssembly
*assembly
,
74 static MonoDebugHandle
*open_symfile_from_bundle (MonoImage
*image
);
76 static MonoDebugDataTable
*
77 create_data_table (MonoDomain
*domain
)
79 MonoDebugDataTable
*table
;
81 table
= g_new0 (MonoDebugDataTable
, 1);
83 table
->mp
= mono_mempool_new ();
84 table
->method_address_hash
= g_hash_table_new (NULL
, NULL
);
87 g_hash_table_insert (data_table_hash
, domain
, table
);
93 free_data_table (MonoDebugDataTable
*table
)
95 mono_mempool_destroy (table
->mp
);
96 g_hash_table_destroy (table
->method_address_hash
);
101 static MonoDebugDataTable
*
102 lookup_data_table (MonoDomain
*domain
)
104 MonoDebugDataTable
*table
;
106 table
= (MonoDebugDataTable
*)g_hash_table_lookup (data_table_hash
, domain
);
108 g_error ("lookup_data_table () failed for %p\n", domain
);
115 free_debug_handle (MonoDebugHandle
*handle
)
118 mono_ppdb_close (handle
);
120 mono_debug_close_mono_symbol_file (handle
->symfile
);
121 /* decrease the refcount added with mono_image_addref () */
122 mono_image_close (handle
->image
);
127 * Initialize debugging support.
129 * This method must be called after loading corlib,
130 * but before opening the application's main assembly because we need to set some
134 mono_debug_init (MonoDebugFormat format
)
136 g_assert (!mono_debug_initialized
);
137 if (format
== MONO_DEBUG_FORMAT_DEBUGGER
)
138 g_error ("The mdb debugger is no longer supported.");
140 mono_debug_initialized
= TRUE
;
141 mono_debug_format
= format
;
143 mono_os_mutex_init_recursive (&debugger_lock_mutex
);
145 mono_debugger_lock ();
147 mono_debug_handles
= g_hash_table_new_full
148 (NULL
, NULL
, NULL
, (GDestroyNotify
) free_debug_handle
);
150 data_table_hash
= g_hash_table_new_full (
151 NULL
, NULL
, NULL
, (GDestroyNotify
) free_data_table
);
153 mono_install_assembly_load_hook (mono_debug_add_assembly
, NULL
);
155 mono_debugger_unlock ();
159 mono_debug_open_image_from_memory (MonoImage
*image
, const guint8
*raw_contents
, int size
)
161 MONO_ENTER_GC_UNSAFE
;
162 if (!mono_debug_initialized
)
165 mono_debug_open_image (image
, raw_contents
, size
);
171 mono_debug_cleanup (void)
173 if (mono_debug_handles
)
174 g_hash_table_destroy (mono_debug_handles
);
175 mono_debug_handles
= NULL
;
177 if (data_table_hash
) {
178 g_hash_table_destroy (data_table_hash
);
179 data_table_hash
= NULL
;
184 * mono_debug_domain_create:
187 mono_debug_domain_create (MonoDomain
*domain
)
189 if (!mono_debug_initialized
)
192 mono_debugger_lock ();
194 create_data_table (domain
);
196 mono_debugger_unlock ();
200 mono_debug_domain_unload (MonoDomain
*domain
)
202 MonoDebugDataTable
*table
;
204 if (!mono_debug_initialized
)
207 mono_debugger_lock ();
209 table
= (MonoDebugDataTable
*)g_hash_table_lookup (data_table_hash
, domain
);
211 g_warning (G_STRLOC
": unloading unknown domain %p / %d",
212 domain
, mono_domain_get_id (domain
));
213 mono_debugger_unlock ();
217 g_hash_table_remove (data_table_hash
, domain
);
219 mono_debugger_unlock ();
223 * LOCKING: Assumes the debug lock is held.
225 static MonoDebugHandle
*
226 mono_debug_get_image (MonoImage
*image
)
228 return (MonoDebugHandle
*)g_hash_table_lookup (mono_debug_handles
, image
);
232 * mono_debug_close_image:
235 mono_debug_close_image (MonoImage
*image
)
237 MonoDebugHandle
*handle
;
239 if (!mono_debug_initialized
)
242 mono_debugger_lock ();
244 handle
= mono_debug_get_image (image
);
246 mono_debugger_unlock ();
250 g_hash_table_remove (mono_debug_handles
, image
);
252 mono_debugger_unlock ();
256 mono_debug_get_handle (MonoImage
*image
)
258 return mono_debug_open_image (image
, NULL
, 0);
261 static MonoDebugHandle
*
262 mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
)
264 MonoDebugHandle
*handle
;
266 if (mono_image_is_dynamic (image
))
269 mono_debugger_lock ();
271 handle
= mono_debug_get_image (image
);
272 if (handle
!= NULL
) {
273 mono_debugger_unlock ();
277 handle
= g_new0 (MonoDebugHandle
, 1);
279 handle
->image
= image
;
280 mono_image_addref (image
);
282 /* Try a ppdb file first */
283 handle
->ppdb
= mono_ppdb_load_file (handle
->image
, raw_contents
, size
);
286 handle
->symfile
= mono_debug_open_mono_symbols (handle
, raw_contents
, size
, FALSE
);
288 g_hash_table_insert (mono_debug_handles
, image
, handle
);
290 mono_debugger_unlock ();
296 mono_debug_add_assembly (MonoAssembly
*assembly
, gpointer user_data
)
298 MonoDebugHandle
*handle
;
301 mono_debugger_lock ();
302 image
= mono_assembly_get_image_internal (assembly
);
303 handle
= open_symfile_from_bundle (image
);
305 mono_debug_open_image (image
, NULL
, 0);
306 mono_debugger_unlock ();
309 struct LookupMethodData
311 MonoDebugMethodInfo
*minfo
;
316 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
318 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
319 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
325 data
->minfo
= mono_ppdb_lookup_method (handle
, data
->method
);
326 else if (handle
->symfile
)
327 data
->minfo
= mono_debug_symfile_lookup_method (handle
, data
->method
);
330 static MonoDebugMethodInfo
*
331 mono_debug_lookup_method_internal (MonoMethod
*method
)
333 struct LookupMethodData data
;
336 data
.method
= method
;
338 if (!mono_debug_handles
)
341 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
346 * mono_debug_lookup_method:
348 * Lookup symbol file information for the method \p method. The returned
349 * \c MonoDebugMethodInfo is a private structure, but it can be passed to
350 * \c mono_debug_symfile_lookup_location.
352 MonoDebugMethodInfo
*
353 mono_debug_lookup_method (MonoMethod
*method
)
355 MonoDebugMethodInfo
*minfo
;
357 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
360 mono_debugger_lock ();
361 minfo
= mono_debug_lookup_method_internal (method
);
362 mono_debugger_unlock ();
373 lookup_image_func (gpointer key
, gpointer value
, gpointer user_data
)
375 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
376 LookupImageData
*data
= (LookupImageData
*) user_data
;
381 if (handle
->image
== data
->image
&& handle
->symfile
)
386 mono_debug_image_has_debug_info (MonoImage
*image
)
388 LookupImageData data
;
390 if (!mono_debug_handles
)
393 memset (&data
, 0, sizeof (data
));
396 mono_debugger_lock ();
397 g_hash_table_foreach (mono_debug_handles
, lookup_image_func
, &data
);
398 mono_debugger_unlock ();
403 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
406 guint8 byte
= value
& 0x7f;
417 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
422 guint8 byte
= value
& 0x7f;
425 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
436 write_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
438 write_leb128 (var
->index
, ptr
, &ptr
);
439 write_sleb128 (var
->offset
, ptr
, &ptr
);
440 write_leb128 (var
->size
, ptr
, &ptr
);
441 write_leb128 (var
->begin_scope
, ptr
, &ptr
);
442 write_leb128 (var
->end_scope
, ptr
, &ptr
);
443 WRITE_UNALIGNED (gpointer
, ptr
, var
->type
);
444 ptr
+= sizeof (gpointer
);
449 * mono_debug_add_method:
451 MonoDebugMethodAddress
*
452 mono_debug_add_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
, MonoDomain
*domain
)
454 MonoDebugDataTable
*table
;
455 MonoDebugMethodAddress
*address
;
456 guint8 buffer
[BUFSIZ
];
457 guint8
*ptr
, *oldptr
;
458 guint32 i
, size
, total_size
, max_size
;
460 mono_debugger_lock ();
462 table
= lookup_data_table (domain
);
464 max_size
= (5 * 5) + 1 + (10 * jit
->num_line_numbers
) +
465 (25 + sizeof (gpointer
)) * (1 + jit
->num_params
+ jit
->num_locals
);
467 if (max_size
> BUFSIZ
)
468 ptr
= oldptr
= (guint8
*)g_malloc (max_size
);
470 ptr
= oldptr
= buffer
;
472 write_leb128 (jit
->prologue_end
, ptr
, &ptr
);
473 write_leb128 (jit
->epilogue_begin
, ptr
, &ptr
);
475 write_leb128 (jit
->num_line_numbers
, ptr
, &ptr
);
476 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
477 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
479 write_sleb128 (lne
->il_offset
, ptr
, &ptr
);
480 write_sleb128 (lne
->native_offset
, ptr
, &ptr
);
482 write_leb128 (jit
->has_var_info
, ptr
, &ptr
);
483 if (jit
->has_var_info
) {
484 *ptr
++ = jit
->this_var
? 1 : 0;
486 write_variable (jit
->this_var
, ptr
, &ptr
);
488 write_leb128 (jit
->num_params
, ptr
, &ptr
);
489 for (i
= 0; i
< jit
->num_params
; i
++)
490 write_variable (&jit
->params
[i
], ptr
, &ptr
);
492 write_leb128 (jit
->num_locals
, ptr
, &ptr
);
493 for (i
= 0; i
< jit
->num_locals
; i
++)
494 write_variable (&jit
->locals
[i
], ptr
, &ptr
);
496 *ptr
++ = jit
->gsharedvt_info_var
? 1 : 0;
497 if (jit
->gsharedvt_info_var
) {
498 write_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
499 write_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
504 g_assert (size
< max_size
);
505 total_size
= size
+ sizeof (MonoDebugMethodAddress
);
507 if (method_is_dynamic (method
)) {
508 address
= (MonoDebugMethodAddress
*)g_malloc0 (total_size
);
510 address
= (MonoDebugMethodAddress
*)mono_mempool_alloc (table
->mp
, total_size
);
513 address
->code_start
= jit
->code_start
;
514 address
->code_size
= jit
->code_size
;
516 memcpy (&address
->data
, oldptr
, size
);
517 if (max_size
> BUFSIZ
)
520 g_hash_table_insert (table
->method_address_hash
, method
, address
);
522 mono_debugger_unlock ();
527 mono_debug_remove_method (MonoMethod
*method
, MonoDomain
*domain
)
529 MonoDebugDataTable
*table
;
530 MonoDebugMethodAddress
*address
;
532 if (!mono_debug_initialized
)
535 g_assert (method_is_dynamic (method
));
537 mono_debugger_lock ();
539 table
= lookup_data_table (domain
);
541 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (table
->method_address_hash
, method
);
545 g_hash_table_remove (table
->method_address_hash
, method
);
547 mono_debugger_unlock ();
551 * mono_debug_add_delegate_trampoline:
554 mono_debug_add_delegate_trampoline (gpointer code
, int size
)
558 static inline guint32
559 read_leb128 (guint8
*ptr
, guint8
**rptr
)
561 guint32 result
= 0, shift
= 0;
564 guint8 byte
= *ptr
++;
566 result
|= (byte
& 0x7f) << shift
;
567 if ((byte
& 0x80) == 0)
577 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
583 guint8 byte
= *ptr
++;
585 result
|= (byte
& 0x7f) << shift
;
591 if ((shift
< 32) && (byte
& 0x40))
592 result
|= - (1 << shift
);
601 read_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
603 var
->index
= read_leb128 (ptr
, &ptr
);
604 var
->offset
= read_sleb128 (ptr
, &ptr
);
605 var
->size
= read_leb128 (ptr
, &ptr
);
606 var
->begin_scope
= read_leb128 (ptr
, &ptr
);
607 var
->end_scope
= read_leb128 (ptr
, &ptr
);
608 READ_UNALIGNED (MonoType
*, ptr
, var
->type
);
609 ptr
+= sizeof (gpointer
);
614 mono_debug_free_method_jit_info_full (MonoDebugMethodJitInfo
*jit
, gboolean stack
)
618 g_free (jit
->line_numbers
);
619 g_free (jit
->this_var
);
620 g_free (jit
->params
);
621 g_free (jit
->locals
);
622 g_free (jit
->gsharedvt_info_var
);
623 g_free (jit
->gsharedvt_locals_var
);
629 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
631 return mono_debug_free_method_jit_info_full (jit
, FALSE
);
634 static MonoDebugMethodJitInfo
*
635 mono_debug_read_method (MonoDebugMethodAddress
*address
, MonoDebugMethodJitInfo
*jit
)
640 memset (jit
, 0, sizeof (*jit
));
641 jit
->code_start
= address
->code_start
;
642 jit
->code_size
= address
->code_size
;
644 ptr
= (guint8
*) &address
->data
;
646 jit
->prologue_end
= read_leb128 (ptr
, &ptr
);
647 jit
->epilogue_begin
= read_leb128 (ptr
, &ptr
);
649 jit
->num_line_numbers
= read_leb128 (ptr
, &ptr
);
650 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
651 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
652 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
654 lne
->il_offset
= read_sleb128 (ptr
, &ptr
);
655 lne
->native_offset
= read_sleb128 (ptr
, &ptr
);
657 jit
->has_var_info
= read_leb128 (ptr
, &ptr
);
658 if (jit
->has_var_info
) {
660 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
661 read_variable (jit
->this_var
, ptr
, &ptr
);
664 jit
->num_params
= read_leb128 (ptr
, &ptr
);
665 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
666 for (i
= 0; i
< jit
->num_params
; i
++)
667 read_variable (&jit
->params
[i
], ptr
, &ptr
);
669 jit
->num_locals
= read_leb128 (ptr
, &ptr
);
670 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
671 for (i
= 0; i
< jit
->num_locals
; i
++)
672 read_variable (&jit
->locals
[i
], ptr
, &ptr
);
675 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
676 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
677 read_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
678 read_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
685 static MonoDebugMethodJitInfo
*
686 find_method (MonoMethod
*method
, MonoDomain
*domain
, MonoDebugMethodJitInfo
*jit
)
688 MonoDebugDataTable
*table
;
689 MonoDebugMethodAddress
*address
;
691 table
= lookup_data_table (domain
);
692 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (table
->method_address_hash
, method
);
697 return mono_debug_read_method (address
, jit
);
700 MonoDebugMethodJitInfo
*
701 mono_debug_find_method (MonoMethod
*method
, MonoDomain
*domain
)
703 MonoDebugMethodJitInfo
*res
= g_new0 (MonoDebugMethodJitInfo
, 1);
705 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
708 mono_debugger_lock ();
709 find_method (method
, domain
, res
);
710 mono_debugger_unlock ();
714 MonoDebugMethodAddressList
*
715 mono_debug_lookup_method_addresses (MonoMethod
*method
)
717 g_assert_not_reached ();
722 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
724 MonoDebugMethodJitInfo mem
;
727 MonoDebugMethodJitInfo
*jit
= find_method (method
, domain
, &mem
);
728 if (!jit
|| !jit
->line_numbers
)
729 goto cleanup_and_fail
;
731 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
732 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
734 if (lne
.native_offset
<= native_offset
) {
735 mono_debug_free_method_jit_info_full (jit
, TRUE
);
736 return lne
.il_offset
;
741 mono_debug_free_method_jit_info_full (jit
, TRUE
);
746 * mono_debug_il_offset_from_address:
748 * Compute the IL offset corresponding to \p native_offset inside the native
749 * code of \p method in \p domain.
752 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
756 mono_debugger_lock ();
758 res
= il_offset_from_address (method
, domain
, native_offset
);
760 mono_debugger_unlock ();
766 * mono_debug_lookup_source_location:
767 * \param address Native offset within the \p method's machine code.
768 * Lookup the source code corresponding to the machine instruction located at
769 * native offset \p address within \p method.
770 * The returned \c MonoDebugSourceLocation contains both file / line number
771 * information and the corresponding IL offset. It must be freed by
772 * \c mono_debug_free_source_location.
774 MonoDebugSourceLocation
*
775 mono_debug_lookup_source_location (MonoMethod
*method
, guint32 address
, MonoDomain
*domain
)
777 MonoDebugMethodInfo
*minfo
;
778 MonoDebugSourceLocation
*location
;
781 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
784 mono_debugger_lock ();
785 minfo
= mono_debug_lookup_method_internal (method
);
786 if (!minfo
|| !minfo
->handle
) {
787 mono_debugger_unlock ();
791 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
792 mono_debugger_unlock ();
796 offset
= il_offset_from_address (method
, domain
, address
);
798 mono_debugger_unlock ();
802 if (minfo
->handle
->ppdb
)
803 location
= mono_ppdb_lookup_location (minfo
, offset
);
805 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
806 mono_debugger_unlock ();
811 * mono_debug_lookup_source_location_by_il:
813 * Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
815 MonoDebugSourceLocation
*
816 mono_debug_lookup_source_location_by_il (MonoMethod
*method
, guint32 il_offset
, MonoDomain
*domain
)
818 MonoDebugMethodInfo
*minfo
;
819 MonoDebugSourceLocation
*location
;
821 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
824 mono_debugger_lock ();
825 minfo
= mono_debug_lookup_method_internal (method
);
826 if (!minfo
|| !minfo
->handle
) {
827 mono_debugger_unlock ();
831 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
832 mono_debugger_unlock ();
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 ();
844 MonoDebugSourceLocation
*
845 mono_debug_method_lookup_location (MonoDebugMethodInfo
*minfo
, int il_offset
)
847 MonoDebugSourceLocation
*location
;
849 mono_debugger_lock ();
850 if (minfo
->handle
->ppdb
)
851 location
= mono_ppdb_lookup_location (minfo
, il_offset
);
853 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
854 mono_debugger_unlock ();
859 * mono_debug_lookup_locals:
861 * Return information about the local variables of MINFO.
862 * The result should be freed using mono_debug_free_locals ().
865 mono_debug_lookup_locals (MonoMethod
*method
)
867 MonoDebugMethodInfo
*minfo
;
868 MonoDebugLocalsInfo
*res
;
870 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
873 mono_debugger_lock ();
874 minfo
= mono_debug_lookup_method_internal (method
);
875 if (!minfo
|| !minfo
->handle
) {
876 mono_debugger_unlock ();
880 if (minfo
->handle
->ppdb
) {
881 res
= mono_ppdb_lookup_locals (minfo
);
883 if (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))
886 res
= mono_debug_symfile_lookup_locals (minfo
);
888 mono_debugger_unlock ();
894 * mono_debug_free_locals:
896 * Free all the data allocated by mono_debug_lookup_locals ().
899 mono_debug_free_locals (MonoDebugLocalsInfo
*info
)
903 for (i
= 0; i
< info
->num_locals
; ++i
)
904 g_free (info
->locals
[i
].name
);
905 g_free (info
->locals
);
906 g_free (info
->code_blocks
);
911 * mono_debug_lookup_method_async_debug_info:
913 * Return information about the async stepping information of method.
914 * The result should be freed using mono_debug_free_async_debug_info ().
916 MonoDebugMethodAsyncInfo
*
917 mono_debug_lookup_method_async_debug_info (MonoMethod
*method
)
919 MonoDebugMethodInfo
*minfo
;
920 MonoDebugMethodAsyncInfo
*res
= NULL
;
922 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
925 mono_debugger_lock ();
926 minfo
= mono_debug_lookup_method_internal (method
);
927 if (!minfo
|| !minfo
->handle
) {
928 mono_debugger_unlock ();
932 if (minfo
->handle
->ppdb
)
933 res
= mono_ppdb_lookup_method_async_debug_info (minfo
);
935 mono_debugger_unlock ();
941 * mono_debug_free_method_async_debug_info:
943 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
946 mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo
*info
)
948 if (info
->num_awaits
) {
949 g_free (info
->yield_offsets
);
950 g_free (info
->resume_offsets
);
951 g_free (info
->move_next_method_token
);
957 * mono_debug_free_source_location:
958 * \param location A \c MonoDebugSourceLocation
959 * Frees the \p location.
962 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
965 g_free (location
->source_file
);
970 static int (*get_seq_point
) (MonoDomain
*domain
, MonoMethod
*method
, gint32 native_offset
);
973 mono_install_get_seq_point (MonoGetSeqPointFunc func
)
975 get_seq_point
= func
;
979 * mono_debug_print_stack_frame:
980 * \param native_offset Native offset within the \p method's machine code.
981 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
982 * used if you only want to use the location to print a stack frame.
985 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
987 MonoDebugSourceLocation
*location
;
988 gchar
*fname
, *ptr
, *res
;
991 fname
= mono_method_full_name (method
, TRUE
);
992 for (ptr
= fname
; *ptr
; ptr
++) {
993 if (*ptr
== ':') *ptr
= '.';
996 location
= mono_debug_lookup_source_location (method
, native_offset
, domain
);
999 if (mono_debug_initialized
) {
1000 mono_debugger_lock ();
1001 offset
= il_offset_from_address (method
, domain
, native_offset
);
1002 mono_debugger_unlock ();
1007 if (offset
< 0 && get_seq_point
)
1008 offset
= get_seq_point (domain
, method
, native_offset
);
1011 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
1013 char *mvid
= mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method
->klass
)->heap_guid
.data
);
1014 char *aotid
= mono_runtime_get_aotid ();
1016 res
= g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname
, offset
, mvid
, aotid
);
1018 res
= g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname
, offset
, mvid
);
1027 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
1028 location
->source_file
, location
->row
);
1031 mono_debug_free_source_location (location
);
1036 mono_set_is_debugger_attached (gboolean attached
)
1038 is_attached
= attached
;
1042 mono_is_debugger_attached (void)
1051 typedef struct _BundledSymfile BundledSymfile
;
1053 struct _BundledSymfile
{
1054 BundledSymfile
*next
;
1056 const mono_byte
*raw_contents
;
1060 static BundledSymfile
*bundled_symfiles
= NULL
;
1063 * mono_register_symfile_for_assembly:
1066 mono_register_symfile_for_assembly (const char *assembly_name
, const mono_byte
*raw_contents
, int size
)
1068 BundledSymfile
*bsymfile
;
1070 bsymfile
= g_new0 (BundledSymfile
, 1);
1071 bsymfile
->aname
= assembly_name
;
1072 bsymfile
->raw_contents
= raw_contents
;
1073 bsymfile
->size
= size
;
1074 bsymfile
->next
= bundled_symfiles
;
1075 bundled_symfiles
= bsymfile
;
1078 static MonoDebugHandle
*
1079 open_symfile_from_bundle (MonoImage
*image
)
1081 BundledSymfile
*bsymfile
;
1083 for (bsymfile
= bundled_symfiles
; bsymfile
; bsymfile
= bsymfile
->next
) {
1084 if (strcmp (bsymfile
->aname
, image
->module_name
))
1087 return mono_debug_open_image (image
, bsymfile
->raw_contents
, bsymfile
->size
);
1094 mono_debugger_lock (void)
1096 g_assert (mono_debug_initialized
);
1097 mono_os_mutex_lock (&debugger_lock_mutex
);
1101 mono_debugger_unlock (void)
1103 g_assert (mono_debug_initialized
);
1104 mono_os_mutex_unlock (&debugger_lock_mutex
);
1108 * mono_debug_enabled:
1110 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1113 mono_debug_enabled (void)
1115 return mono_debug_format
!= MONO_DEBUG_FORMAT_NONE
;
1119 mono_debug_get_seq_points (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int **source_files
, MonoSymSeqPoint
**seq_points
, int *n_seq_points
)
1121 if (minfo
->handle
->ppdb
)
1122 mono_ppdb_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);
1124 mono_debug_symfile_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);