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/mono-debug-debugger.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-ppdb.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/runtime.h>
29 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
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 if (!mono_debug_initialized
)
164 mono_debug_open_image (image
, raw_contents
, size
);
168 mono_debug_cleanup (void)
170 if (mono_debug_handles
)
171 g_hash_table_destroy (mono_debug_handles
);
172 mono_debug_handles
= NULL
;
174 if (data_table_hash
) {
175 g_hash_table_destroy (data_table_hash
);
176 data_table_hash
= NULL
;
181 mono_debug_domain_create (MonoDomain
*domain
)
183 if (!mono_debug_initialized
)
186 mono_debugger_lock ();
188 create_data_table (domain
);
190 mono_debugger_unlock ();
194 mono_debug_domain_unload (MonoDomain
*domain
)
196 MonoDebugDataTable
*table
;
198 if (!mono_debug_initialized
)
201 mono_debugger_lock ();
203 table
= (MonoDebugDataTable
*)g_hash_table_lookup (data_table_hash
, domain
);
205 g_warning (G_STRLOC
": unloading unknown domain %p / %d",
206 domain
, mono_domain_get_id (domain
));
207 mono_debugger_unlock ();
211 g_hash_table_remove (data_table_hash
, domain
);
213 mono_debugger_unlock ();
217 * LOCKING: Assumes the debug lock is held.
219 static MonoDebugHandle
*
220 mono_debug_get_image (MonoImage
*image
)
222 return (MonoDebugHandle
*)g_hash_table_lookup (mono_debug_handles
, image
);
226 mono_debug_close_image (MonoImage
*image
)
228 MonoDebugHandle
*handle
;
230 if (!mono_debug_initialized
)
233 mono_debugger_lock ();
235 handle
= mono_debug_get_image (image
);
237 mono_debugger_unlock ();
241 g_hash_table_remove (mono_debug_handles
, image
);
243 mono_debugger_unlock ();
246 static MonoDebugHandle
*
247 mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
)
249 MonoDebugHandle
*handle
;
251 if (mono_image_is_dynamic (image
))
254 mono_debugger_lock ();
256 handle
= mono_debug_get_image (image
);
257 if (handle
!= NULL
) {
258 mono_debugger_unlock ();
262 handle
= g_new0 (MonoDebugHandle
, 1);
264 handle
->image
= image
;
265 mono_image_addref (image
);
267 /* Try a ppdb file first */
268 handle
->ppdb
= mono_ppdb_load_file (handle
->image
, raw_contents
, size
);
271 handle
->symfile
= mono_debug_open_mono_symbols (handle
, raw_contents
, size
, FALSE
);
273 g_hash_table_insert (mono_debug_handles
, image
, handle
);
275 mono_debugger_unlock ();
281 mono_debug_add_assembly (MonoAssembly
*assembly
, gpointer user_data
)
283 MonoDebugHandle
*handle
;
286 mono_debugger_lock ();
287 image
= mono_assembly_get_image (assembly
);
288 handle
= open_symfile_from_bundle (image
);
290 mono_debug_open_image (image
, NULL
, 0);
291 mono_debugger_unlock ();
294 struct LookupMethodData
296 MonoDebugMethodInfo
*minfo
;
301 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
303 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
304 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
310 data
->minfo
= mono_ppdb_lookup_method (handle
, data
->method
);
311 else if (handle
->symfile
)
312 data
->minfo
= mono_debug_symfile_lookup_method (handle
, data
->method
);
315 static MonoDebugMethodInfo
*
316 mono_debug_lookup_method_internal (MonoMethod
*method
)
318 struct LookupMethodData data
;
321 data
.method
= method
;
323 if (!mono_debug_handles
)
326 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
331 * mono_debug_lookup_method:
333 * Lookup symbol file information for the method @method. The returned
334 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
335 * mono_debug_symfile_lookup_location().
337 MonoDebugMethodInfo
*
338 mono_debug_lookup_method (MonoMethod
*method
)
340 MonoDebugMethodInfo
*minfo
;
342 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
345 mono_debugger_lock ();
346 minfo
= mono_debug_lookup_method_internal (method
);
347 mono_debugger_unlock ();
358 lookup_image_func (gpointer key
, gpointer value
, gpointer user_data
)
360 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
361 LookupImageData
*data
= (LookupImageData
*) user_data
;
366 if (handle
->image
== data
->image
&& handle
->symfile
)
371 mono_debug_image_has_debug_info (MonoImage
*image
)
373 LookupImageData data
;
375 if (!mono_debug_handles
)
378 memset (&data
, 0, sizeof (data
));
381 mono_debugger_lock ();
382 g_hash_table_foreach (mono_debug_handles
, lookup_image_func
, &data
);
383 mono_debugger_unlock ();
388 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
391 guint8 byte
= value
& 0x7f;
402 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
407 guint8 byte
= value
& 0x7f;
410 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
421 write_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
423 write_leb128 (var
->index
, ptr
, &ptr
);
424 write_sleb128 (var
->offset
, ptr
, &ptr
);
425 write_leb128 (var
->size
, ptr
, &ptr
);
426 write_leb128 (var
->begin_scope
, ptr
, &ptr
);
427 write_leb128 (var
->end_scope
, ptr
, &ptr
);
428 WRITE_UNALIGNED (gpointer
, ptr
, var
->type
);
429 ptr
+= sizeof (gpointer
);
433 MonoDebugMethodAddress
*
434 mono_debug_add_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
, MonoDomain
*domain
)
436 MonoDebugDataTable
*table
;
437 MonoDebugMethodAddress
*address
;
438 guint8 buffer
[BUFSIZ
];
439 guint8
*ptr
, *oldptr
;
440 guint32 i
, size
, total_size
, max_size
;
442 mono_debugger_lock ();
444 table
= lookup_data_table (domain
);
446 max_size
= (5 * 5) + 1 + (10 * jit
->num_line_numbers
) +
447 (25 + sizeof (gpointer
)) * (1 + jit
->num_params
+ jit
->num_locals
);
449 if (max_size
> BUFSIZ
)
450 ptr
= oldptr
= (guint8
*)g_malloc (max_size
);
452 ptr
= oldptr
= buffer
;
454 write_leb128 (jit
->prologue_end
, ptr
, &ptr
);
455 write_leb128 (jit
->epilogue_begin
, ptr
, &ptr
);
457 write_leb128 (jit
->num_line_numbers
, ptr
, &ptr
);
458 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
459 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
461 write_sleb128 (lne
->il_offset
, ptr
, &ptr
);
462 write_sleb128 (lne
->native_offset
, ptr
, &ptr
);
464 write_leb128 (jit
->has_var_info
, ptr
, &ptr
);
465 if (jit
->has_var_info
) {
466 *ptr
++ = jit
->this_var
? 1 : 0;
468 write_variable (jit
->this_var
, ptr
, &ptr
);
470 write_leb128 (jit
->num_params
, ptr
, &ptr
);
471 for (i
= 0; i
< jit
->num_params
; i
++)
472 write_variable (&jit
->params
[i
], ptr
, &ptr
);
474 write_leb128 (jit
->num_locals
, ptr
, &ptr
);
475 for (i
= 0; i
< jit
->num_locals
; i
++)
476 write_variable (&jit
->locals
[i
], ptr
, &ptr
);
478 *ptr
++ = jit
->gsharedvt_info_var
? 1 : 0;
479 if (jit
->gsharedvt_info_var
) {
480 write_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
481 write_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
486 g_assert (size
< max_size
);
487 total_size
= size
+ sizeof (MonoDebugMethodAddress
);
489 if (method_is_dynamic (method
)) {
490 address
= (MonoDebugMethodAddress
*)g_malloc0 (total_size
);
492 address
= (MonoDebugMethodAddress
*)mono_mempool_alloc (table
->mp
, total_size
);
495 address
->code_start
= jit
->code_start
;
496 address
->code_size
= jit
->code_size
;
498 memcpy (&address
->data
, oldptr
, size
);
499 if (max_size
> BUFSIZ
)
502 g_hash_table_insert (table
->method_address_hash
, method
, address
);
504 mono_debugger_unlock ();
509 mono_debug_remove_method (MonoMethod
*method
, MonoDomain
*domain
)
511 MonoDebugDataTable
*table
;
512 MonoDebugMethodAddress
*address
;
514 if (!mono_debug_initialized
)
517 g_assert (method_is_dynamic (method
));
519 mono_debugger_lock ();
521 table
= lookup_data_table (domain
);
523 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (table
->method_address_hash
, method
);
527 g_hash_table_remove (table
->method_address_hash
, method
);
529 mono_debugger_unlock ();
533 mono_debug_add_delegate_trampoline (gpointer code
, int size
)
537 static inline guint32
538 read_leb128 (guint8
*ptr
, guint8
**rptr
)
540 guint32 result
= 0, shift
= 0;
543 guint8 byte
= *ptr
++;
545 result
|= (byte
& 0x7f) << shift
;
546 if ((byte
& 0x80) == 0)
556 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
562 guint8 byte
= *ptr
++;
564 result
|= (byte
& 0x7f) << shift
;
570 if ((shift
< 32) && (byte
& 0x40))
571 result
|= - (1 << shift
);
580 read_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
582 var
->index
= read_leb128 (ptr
, &ptr
);
583 var
->offset
= read_sleb128 (ptr
, &ptr
);
584 var
->size
= read_leb128 (ptr
, &ptr
);
585 var
->begin_scope
= read_leb128 (ptr
, &ptr
);
586 var
->end_scope
= read_leb128 (ptr
, &ptr
);
587 READ_UNALIGNED (MonoType
*, ptr
, var
->type
);
588 ptr
+= sizeof (gpointer
);
593 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
597 g_free (jit
->line_numbers
);
598 g_free (jit
->this_var
);
599 g_free (jit
->params
);
600 g_free (jit
->locals
);
601 g_free (jit
->gsharedvt_info_var
);
602 g_free (jit
->gsharedvt_locals_var
);
606 static MonoDebugMethodJitInfo
*
607 mono_debug_read_method (MonoDebugMethodAddress
*address
)
609 MonoDebugMethodJitInfo
*jit
;
613 jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
614 jit
->code_start
= address
->code_start
;
615 jit
->code_size
= address
->code_size
;
617 ptr
= (guint8
*) &address
->data
;
619 jit
->prologue_end
= read_leb128 (ptr
, &ptr
);
620 jit
->epilogue_begin
= read_leb128 (ptr
, &ptr
);
622 jit
->num_line_numbers
= read_leb128 (ptr
, &ptr
);
623 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
624 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
625 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
627 lne
->il_offset
= read_sleb128 (ptr
, &ptr
);
628 lne
->native_offset
= read_sleb128 (ptr
, &ptr
);
630 jit
->has_var_info
= read_leb128 (ptr
, &ptr
);
631 if (jit
->has_var_info
) {
633 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
634 read_variable (jit
->this_var
, ptr
, &ptr
);
637 jit
->num_params
= read_leb128 (ptr
, &ptr
);
638 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
639 for (i
= 0; i
< jit
->num_params
; i
++)
640 read_variable (&jit
->params
[i
], ptr
, &ptr
);
642 jit
->num_locals
= read_leb128 (ptr
, &ptr
);
643 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
644 for (i
= 0; i
< jit
->num_locals
; i
++)
645 read_variable (&jit
->locals
[i
], ptr
, &ptr
);
648 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
649 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
650 read_variable (jit
->gsharedvt_info_var
, ptr
, &ptr
);
651 read_variable (jit
->gsharedvt_locals_var
, ptr
, &ptr
);
658 static MonoDebugMethodJitInfo
*
659 find_method (MonoMethod
*method
, MonoDomain
*domain
)
661 MonoDebugDataTable
*table
;
662 MonoDebugMethodAddress
*address
;
664 table
= lookup_data_table (domain
);
665 address
= (MonoDebugMethodAddress
*)g_hash_table_lookup (table
->method_address_hash
, method
);
670 return mono_debug_read_method (address
);
673 MonoDebugMethodJitInfo
*
674 mono_debug_find_method (MonoMethod
*method
, MonoDomain
*domain
)
676 MonoDebugMethodJitInfo
*res
;
678 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
681 mono_debugger_lock ();
682 res
= find_method (method
, domain
);
683 mono_debugger_unlock ();
687 MonoDebugMethodAddressList
*
688 mono_debug_lookup_method_addresses (MonoMethod
*method
)
690 g_assert_not_reached ();
695 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
697 MonoDebugMethodJitInfo
*jit
;
700 jit
= find_method (method
, domain
);
701 if (!jit
|| !jit
->line_numbers
)
702 goto cleanup_and_fail
;
704 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
705 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
707 if (lne
.native_offset
<= native_offset
) {
708 mono_debug_free_method_jit_info (jit
);
709 return lne
.il_offset
;
714 mono_debug_free_method_jit_info (jit
);
719 * mono_debug_il_offset_from_address:
721 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
722 * code of METHOD in DOMAIN.
725 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
729 mono_debugger_lock ();
731 res
= il_offset_from_address (method
, domain
, native_offset
);
733 mono_debugger_unlock ();
739 * mono_debug_lookup_source_location:
740 * @address: Native offset within the @method's machine code.
742 * Lookup the source code corresponding to the machine instruction located at
743 * native offset @address within @method.
745 * The returned `MonoDebugSourceLocation' contains both file / line number
746 * information and the corresponding IL offset. It must be freed by
747 * mono_debug_free_source_location().
749 MonoDebugSourceLocation
*
750 mono_debug_lookup_source_location (MonoMethod
*method
, guint32 address
, MonoDomain
*domain
)
752 MonoDebugMethodInfo
*minfo
;
753 MonoDebugSourceLocation
*location
;
756 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
759 mono_debugger_lock ();
760 minfo
= mono_debug_lookup_method_internal (method
);
761 if (!minfo
|| !minfo
->handle
) {
762 mono_debugger_unlock ();
766 if (!minfo
->handle
->ppdb
&& (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))) {
767 mono_debugger_unlock ();
771 offset
= il_offset_from_address (method
, domain
, address
);
773 mono_debugger_unlock ();
777 if (minfo
->handle
->ppdb
)
778 location
= mono_ppdb_lookup_location (minfo
, offset
);
780 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
781 mono_debugger_unlock ();
785 MonoDebugSourceLocation
*
786 mono_debug_method_lookup_location (MonoDebugMethodInfo
*minfo
, int il_offset
)
788 MonoDebugSourceLocation
*location
;
790 mono_debugger_lock ();
791 if (minfo
->handle
->ppdb
)
792 location
= mono_ppdb_lookup_location (minfo
, il_offset
);
794 location
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
795 mono_debugger_unlock ();
800 * mono_debug_lookup_locals:
802 * Return information about the local variables of MINFO.
803 * The result should be freed using mono_debug_free_locals ().
806 mono_debug_lookup_locals (MonoMethod
*method
)
808 MonoDebugMethodInfo
*minfo
;
809 MonoDebugLocalsInfo
*res
;
811 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
814 mono_debugger_lock ();
815 minfo
= mono_debug_lookup_method_internal (method
);
816 if (!minfo
|| !minfo
->handle
) {
817 mono_debugger_unlock ();
821 if (minfo
->handle
->ppdb
) {
822 res
= mono_ppdb_lookup_locals (minfo
);
824 if (!minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
))
827 res
= mono_debug_symfile_lookup_locals (minfo
);
829 mono_debugger_unlock ();
835 * mono_debug_free_locals:
837 * Free all the data allocated by mono_debug_lookup_locals ().
840 mono_debug_free_locals (MonoDebugLocalsInfo
*info
)
844 for (i
= 0; i
< info
->num_locals
; ++i
)
845 g_free (info
->locals
[i
].name
);
846 g_free (info
->locals
);
847 g_free (info
->code_blocks
);
852 * mono_debug_lookup_method_async_debug_info:
854 * Return information about the async stepping information of method.
855 * The result should be freed using mono_debug_free_async_debug_info ().
857 MonoDebugMethodAsyncInfo
*
858 mono_debug_lookup_method_async_debug_info (MonoMethod
*method
)
860 MonoDebugMethodInfo
*minfo
;
861 MonoDebugMethodAsyncInfo
*res
= NULL
;
863 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
866 mono_debugger_lock ();
867 minfo
= mono_debug_lookup_method_internal (method
);
868 if (!minfo
|| !minfo
->handle
) {
869 mono_debugger_unlock ();
873 if (minfo
->handle
->ppdb
)
874 res
= mono_ppdb_lookup_method_async_debug_info (minfo
);
876 mono_debugger_unlock ();
882 * mono_debug_free_method_async_debug_info:
884 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
887 mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo
*info
)
889 if (info
->num_awaits
) {
890 g_free (info
->yield_offsets
);
891 g_free (info
->resume_offsets
);
892 g_free (info
->move_next_method_token
);
898 * mono_debug_free_source_location:
899 * @location: A `MonoDebugSourceLocation'.
901 * Frees the @location.
904 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
907 g_free (location
->source_file
);
912 static int (*get_seq_point
) (MonoDomain
*domain
, MonoMethod
*method
, gint32 native_offset
);
915 mono_install_get_seq_point (MonoGetSeqPointFunc func
)
917 get_seq_point
= func
;
921 * mono_debug_print_stack_frame:
922 * @native_offset: Native offset within the @method's machine code.
924 * Conventient wrapper around mono_debug_lookup_source_location() which can be
925 * used if you only want to use the location to print a stack frame.
928 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
930 MonoDebugSourceLocation
*location
;
931 gchar
*fname
, *ptr
, *res
;
934 fname
= mono_method_full_name (method
, TRUE
);
935 for (ptr
= fname
; *ptr
; ptr
++) {
936 if (*ptr
== ':') *ptr
= '.';
939 location
= mono_debug_lookup_source_location (method
, native_offset
, domain
);
942 if (mono_debug_initialized
) {
943 mono_debugger_lock ();
944 offset
= il_offset_from_address (method
, domain
, native_offset
);
945 mono_debugger_unlock ();
950 if (offset
< 0 && get_seq_point
)
951 offset
= get_seq_point (domain
, method
, native_offset
);
954 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
956 char *mvid
= mono_guid_to_string_minimal ((uint8_t*)method
->klass
->image
->heap_guid
.data
);
957 char *aotid
= mono_runtime_get_aotid ();
959 res
= g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname
, offset
, mvid
, aotid
);
961 res
= g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname
, offset
, mvid
);
970 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
971 location
->source_file
, location
->row
);
974 mono_debug_free_source_location (location
);
979 mono_set_is_debugger_attached (gboolean attached
)
981 is_attached
= attached
;
985 mono_is_debugger_attached (void)
994 typedef struct _BundledSymfile BundledSymfile
;
996 struct _BundledSymfile
{
997 BundledSymfile
*next
;
999 const mono_byte
*raw_contents
;
1003 static BundledSymfile
*bundled_symfiles
= NULL
;
1006 mono_register_symfile_for_assembly (const char *assembly_name
, const mono_byte
*raw_contents
, int size
)
1008 BundledSymfile
*bsymfile
;
1010 bsymfile
= g_new0 (BundledSymfile
, 1);
1011 bsymfile
->aname
= assembly_name
;
1012 bsymfile
->raw_contents
= raw_contents
;
1013 bsymfile
->size
= size
;
1014 bsymfile
->next
= bundled_symfiles
;
1015 bundled_symfiles
= bsymfile
;
1018 static MonoDebugHandle
*
1019 open_symfile_from_bundle (MonoImage
*image
)
1021 BundledSymfile
*bsymfile
;
1023 for (bsymfile
= bundled_symfiles
; bsymfile
; bsymfile
= bsymfile
->next
) {
1024 if (strcmp (bsymfile
->aname
, image
->module_name
))
1027 return mono_debug_open_image (image
, bsymfile
->raw_contents
, bsymfile
->size
);
1034 mono_debugger_lock (void)
1036 g_assert (mono_debug_initialized
);
1037 mono_os_mutex_lock (&debugger_lock_mutex
);
1041 mono_debugger_unlock (void)
1043 g_assert (mono_debug_initialized
);
1044 mono_os_mutex_unlock (&debugger_lock_mutex
);
1048 * mono_debug_enabled:
1050 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1053 mono_debug_enabled (void)
1055 return mono_debug_format
!= MONO_DEBUG_FORMAT_NONE
;
1059 mono_debug_get_seq_points (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int **source_files
, MonoSymSeqPoint
**seq_points
, int *n_seq_points
)
1061 if (minfo
->handle
->ppdb
)
1062 mono_ppdb_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);
1064 mono_debug_symfile_get_seq_points (minfo
, source_file
, source_file_list
, source_files
, seq_points
, n_seq_points
);