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 #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))
36 #define WRITE_UNALIGNED(type, addr, val) \
37 (*(type *)(addr) = (val))
38 #define READ_UNALIGNED(type, addr, val) \
39 val = (*(type *)(addr))
42 /* This contains per-domain info */
43 struct _MonoDebugDataTable
{
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
;
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
,
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
);
86 g_hash_table_insert (data_table_hash
, domain
, table
);
92 free_data_table (MonoDebugDataTable
*table
)
94 mono_mempool_destroy (table
->mp
);
95 g_hash_table_destroy (table
->method_address_hash
);
100 static MonoDebugDataTable
*
101 lookup_data_table (MonoDomain
*domain
)
103 MonoDebugDataTable
*table
;
105 table
= (MonoDebugDataTable
*)g_hash_table_lookup (data_table_hash
, domain
);
107 g_error ("lookup_data_table () failed for %p\n", domain
);
114 free_debug_handle (MonoDebugHandle
*handle
)
117 mono_ppdb_close (handle
);
119 mono_debug_close_mono_symbol_file (handle
->symfile
);
120 /* decrease the refcount added with mono_image_addref () */
121 mono_image_close (handle
->image
);
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
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 ();
158 mono_debug_open_image_from_memory (MonoImage
*image
, const guint8
*raw_contents
, int size
)
160 if (!mono_debug_initialized
)
163 mono_debug_open_image (image
, raw_contents
, size
);
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:
183 mono_debug_domain_create (MonoDomain
*domain
)
185 if (!mono_debug_initialized
)
188 mono_debugger_lock ();
190 create_data_table (domain
);
192 mono_debugger_unlock ();
196 mono_debug_domain_unload (MonoDomain
*domain
)
198 MonoDebugDataTable
*table
;
200 if (!mono_debug_initialized
)
203 mono_debugger_lock ();
205 table
= (MonoDebugDataTable
*)g_hash_table_lookup (data_table_hash
, domain
);
207 g_warning (G_STRLOC
": unloading unknown domain %p / %d",
208 domain
, mono_domain_get_id (domain
));
209 mono_debugger_unlock ();
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:
231 mono_debug_close_image (MonoImage
*image
)
233 MonoDebugHandle
*handle
;
235 if (!mono_debug_initialized
)
238 mono_debugger_lock ();
240 handle
= mono_debug_get_image (image
);
242 mono_debugger_unlock ();
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
))
259 mono_debugger_lock ();
261 handle
= mono_debug_get_image (image
);
262 if (handle
!= NULL
) {
263 mono_debugger_unlock ();
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
);
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 ();
286 mono_debug_add_assembly (MonoAssembly
*assembly
, gpointer user_data
)
288 MonoDebugHandle
*handle
;
291 mono_debugger_lock ();
292 image
= mono_assembly_get_image (assembly
);
293 handle
= open_symfile_from_bundle (image
);
295 mono_debug_open_image (image
, NULL
, 0);
296 mono_debugger_unlock ();
299 struct LookupMethodData
301 MonoDebugMethodInfo
*minfo
;
306 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
308 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
309 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
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
;
326 data
.method
= method
;
328 if (!mono_debug_handles
)
331 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
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
)
350 mono_debugger_lock ();
351 minfo
= mono_debug_lookup_method_internal (method
);
352 mono_debugger_unlock ();
363 lookup_image_func (gpointer key
, gpointer value
, gpointer user_data
)
365 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
366 LookupImageData
*data
= (LookupImageData
*) user_data
;
371 if (handle
->image
== data
->image
&& handle
->symfile
)
376 mono_debug_image_has_debug_info (MonoImage
*image
)
378 LookupImageData data
;
380 if (!mono_debug_handles
)
383 memset (&data
, 0, sizeof (data
));
386 mono_debugger_lock ();
387 g_hash_table_foreach (mono_debug_handles
, lookup_image_func
, &data
);
388 mono_debugger_unlock ();
393 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
396 guint8 byte
= value
& 0x7f;
407 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
412 guint8 byte
= value
& 0x7f;
415 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
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
);
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
);
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;
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
);
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
);
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
)
510 g_hash_table_insert (table
->method_address_hash
, method
, address
);
512 mono_debugger_unlock ();
517 mono_debug_remove_method (MonoMethod
*method
, MonoDomain
*domain
)
519 MonoDebugDataTable
*table
;
520 MonoDebugMethodAddress
*address
;
522 if (!mono_debug_initialized
)
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
);
535 g_hash_table_remove (table
->method_address_hash
, method
);
537 mono_debugger_unlock ();
541 * mono_debug_add_delegate_trampoline:
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;
554 guint8 byte
= *ptr
++;
556 result
|= (byte
& 0x7f) << shift
;
557 if ((byte
& 0x80) == 0)
567 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
573 guint8 byte
= *ptr
++;
575 result
|= (byte
& 0x7f) << shift
;
581 if ((shift
< 32) && (byte
& 0x40))
582 result
|= - (1 << shift
);
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
);
604 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
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
);
617 static MonoDebugMethodJitInfo
*
618 mono_debug_read_method (MonoDebugMethodAddress
*address
)
620 MonoDebugMethodJitInfo
*jit
;
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
) {
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
);
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
);
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
);
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
)
692 mono_debugger_lock ();
693 res
= find_method (method
, domain
);
694 mono_debugger_unlock ();
698 MonoDebugMethodAddressList
*
699 mono_debug_lookup_method_addresses (MonoMethod
*method
)
701 g_assert_not_reached ();
706 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
708 MonoDebugMethodJitInfo
*jit
;
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
;
725 mono_debug_free_method_jit_info (jit
);
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.
736 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
740 mono_debugger_lock ();
742 res
= il_offset_from_address (method
, domain
, native_offset
);
744 mono_debugger_unlock ();
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
;
765 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
768 mono_debugger_lock ();
769 minfo
= mono_debug_lookup_method_internal (method
);
770 if (!minfo
|| !minfo
->handle
) {
771 mono_debugger_unlock ();
775 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
776 mono_debugger_unlock ();
780 offset
= il_offset_from_address (method
, domain
, address
);
782 mono_debugger_unlock ();
786 if (minfo
->handle
->ppdb
)
787 location
= mono_ppdb_lookup_location (minfo
, offset
);
789 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
790 mono_debugger_unlock ();
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
)
808 mono_debugger_lock ();
809 minfo
= mono_debug_lookup_method_internal (method
);
810 if (!minfo
|| !minfo
->handle
) {
811 mono_debugger_unlock ();
815 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
816 mono_debugger_unlock ();
820 if (minfo
->handle
->ppdb
)
821 location
= mono_ppdb_lookup_location (minfo
, il_offset
);
823 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
824 mono_debugger_unlock ();
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
);
837 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
838 mono_debugger_unlock ();
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 ().
849 mono_debug_lookup_locals (MonoMethod
*method
)
851 MonoDebugMethodInfo
*minfo
;
852 MonoDebugLocalsInfo
*res
;
854 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
857 mono_debugger_lock ();
858 minfo
= mono_debug_lookup_method_internal (method
);
859 if (!minfo
|| !minfo
->handle
) {
860 mono_debugger_unlock ();
864 if (minfo
->handle
->ppdb
) {
865 res
= mono_ppdb_lookup_locals (minfo
);
867 if (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))
870 res
= mono_debug_symfile_lookup_locals (minfo
);
872 mono_debugger_unlock ();
878 * mono_debug_free_locals:
880 * Free all the data allocated by mono_debug_lookup_locals ().
883 mono_debug_free_locals (MonoDebugLocalsInfo
*info
)
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
);
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
)
909 mono_debugger_lock ();
910 minfo
= mono_debug_lookup_method_internal (method
);
911 if (!minfo
|| !minfo
->handle
) {
912 mono_debugger_unlock ();
916 if (minfo
->handle
->ppdb
)
917 res
= mono_ppdb_lookup_method_async_debug_info (minfo
);
919 mono_debugger_unlock ();
925 * mono_debug_free_method_async_debug_info:
927 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
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
);
941 * mono_debug_free_source_location:
942 * \param location A \c MonoDebugSourceLocation
943 * Frees the \p location.
946 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
949 g_free (location
->source_file
);
954 static int (*get_seq_point
) (MonoDomain
*domain
, MonoMethod
*method
, gint32 native_offset
);
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.
969 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
971 MonoDebugSourceLocation
*location
;
972 gchar
*fname
, *ptr
, *res
;
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
);
983 if (mono_debug_initialized
) {
984 mono_debugger_lock ();
985 offset
= il_offset_from_address (method
, domain
, native_offset
);
986 mono_debugger_unlock ();
991 if (offset
< 0 && get_seq_point
)
992 offset
= get_seq_point (domain
, method
, native_offset
);
995 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
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 ();
1000 res
= g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname
, offset
, mvid
, aotid
);
1002 res
= g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname
, offset
, mvid
);
1011 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
1012 location
->source_file
, location
->row
);
1015 mono_debug_free_source_location (location
);
1020 mono_set_is_debugger_attached (gboolean attached
)
1022 is_attached
= attached
;
1026 mono_is_debugger_attached (void)
1035 typedef struct _BundledSymfile BundledSymfile
;
1037 struct _BundledSymfile
{
1038 BundledSymfile
*next
;
1040 const mono_byte
*raw_contents
;
1044 static BundledSymfile
*bundled_symfiles
= NULL
;
1047 * mono_register_symfile_for_assembly:
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
))
1071 return mono_debug_open_image (image
, bsymfile
->raw_contents
, bsymfile
->size
);
1078 mono_debugger_lock (void)
1080 g_assert (mono_debug_initialized
);
1081 mono_os_mutex_lock (&debugger_lock_mutex
);
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.
1097 mono_debug_enabled (void)
1099 return mono_debug_format
!= MONO_DEBUG_FORMAT_NONE
;
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
);
1108 mono_debug_symfile_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);