[merp] Remove dead code (#20043)
[mono-project.git] / mono / metadata / mono-debug.c
blobda69c5ab33c244c6615fa87919804e69fa9be243
1 /**
2 * \file
4 * Author:
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.
13 #include <config.h>
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>
29 #include <string.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))
36 #else
37 #define WRITE_UNALIGNED(type, addr, val) \
38 (*(type *)(addr) = (val))
39 #define READ_UNALIGNED(type, addr, val) \
40 val = (*(type *)(addr))
41 #endif
43 /* This contains per-domain info */
44 typedef struct {
45 MonoMemPool *mp;
46 GHashTable *method_hash;
47 } DebugDomainInfo;
49 /* This contains JIT debugging information about a method in serialized format */
50 struct _MonoDebugMethodAddress {
51 const guint8 *code_start;
52 guint32 code_size;
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;
81 static void
82 free_debug_handle (MonoDebugHandle *handle)
84 if (handle->ppdb)
85 mono_ppdb_close (handle);
86 if (handle->symfile)
87 mono_debug_close_mono_symbol_file (handle->symfile);
88 /* decrease the refcount added with mono_image_addref () */
89 mono_image_close (handle->image);
90 g_free (handle);
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
98 * callbacks here.
100 void
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 ();
122 void
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)
127 goto leave;
129 mono_debug_open_image (image, raw_contents, size);
130 leave:
131 MONO_EXIT_GC_UNSAFE;
134 void
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:
145 void
146 mono_debug_domain_create (MonoDomain *domain)
148 DebugDomainInfo *info;
150 if (!mono_debug_initialized)
151 return;
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;
160 void
161 mono_debug_domain_unload (MonoDomain *domain)
163 DebugDomainInfo *info = (DebugDomainInfo*)domain->debug_info;
165 if (!info)
166 return;
168 mono_mempool_destroy (info->mp);
169 g_hash_table_destroy (info->method_hash);
171 g_free (info);
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:
186 void
187 mono_debug_close_image (MonoImage *image)
189 MonoDebugHandle *handle;
191 if (!mono_debug_initialized)
192 return;
194 mono_debugger_lock ();
196 handle = mono_debug_get_image (image);
197 if (!handle) {
198 mono_debugger_unlock ();
199 return;
202 g_hash_table_remove (mono_debug_handles, image);
204 mono_debugger_unlock ();
207 MonoDebugHandle *
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))
219 return NULL;
221 mono_debugger_lock ();
223 handle = mono_debug_get_image (image);
224 if (handle != NULL) {
225 mono_debugger_unlock ();
226 return handle;
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);
237 if (!handle->ppdb)
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 ();
244 return handle;
247 static void
248 add_assembly (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer user_data, MonoError *error)
250 MonoDebugHandle *handle;
251 MonoImage *image;
253 mono_debugger_lock ();
254 image = mono_assembly_get_image_internal (assembly);
255 handle = open_symfile_from_bundle (image);
256 if (!handle)
257 mono_debug_open_image (image, NULL, 0);
258 mono_debugger_unlock ();
261 struct LookupMethodData
263 MonoDebugMethodInfo *minfo;
264 MonoMethod *method;
267 static void
268 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
270 MonoDebugHandle *handle = (MonoDebugHandle *) value;
271 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
273 if (data->minfo)
274 return;
276 if (handle->ppdb)
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;
287 data.minfo = NULL;
288 data.method = method;
290 if (!mono_debug_handles)
291 return NULL;
293 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
294 return data.minfo;
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)
310 return NULL;
312 mono_debugger_lock ();
313 minfo = lookup_method (method);
314 mono_debugger_unlock ();
315 return minfo;
318 typedef struct
320 gboolean found;
321 MonoImage *image;
322 } LookupImageData;
324 static void
325 lookup_image_func (gpointer key, gpointer value, gpointer user_data)
327 MonoDebugHandle *handle = (MonoDebugHandle *) value;
328 LookupImageData *data = (LookupImageData *) user_data;
330 if (data->found)
331 return;
333 if (handle->image == data->image && (handle->symfile || handle->ppdb))
334 data->found = TRUE;
337 gboolean
338 mono_debug_image_has_debug_info (MonoImage *image)
340 LookupImageData data;
342 if (!mono_debug_handles)
343 return FALSE;
345 memset (&data, 0, sizeof (data));
346 data.image = image;
348 mono_debugger_lock ();
349 g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
350 mono_debugger_unlock ();
351 return data.found;
354 static void
355 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
357 do {
358 guint8 byte = value & 0x7f;
359 value >>= 7;
360 if (value)
361 byte |= 0x80;
362 *ptr++ = byte;
363 } while (value);
365 *rptr = ptr;
368 static void
369 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
371 gboolean more = 1;
373 while (more) {
374 guint8 byte = value & 0x7f;
375 value >>= 7;
377 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
378 more = 0;
379 else
380 byte |= 0x80;
381 *ptr++ = byte;
384 *rptr = ptr;
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))
391 static void
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);
401 *rptr = ptr;
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) {
420 /* this */
421 max_size += 1;
422 if (jit->this_var)
423 max_size += WRITE_VARIABLE_MAX_SIZE;
424 /* params */
425 max_size += LEB128_MAX_SIZE;
426 max_size += jit->num_params * WRITE_VARIABLE_MAX_SIZE;
427 /* locals */
428 max_size += LEB128_MAX_SIZE;
429 max_size += jit->num_locals * WRITE_VARIABLE_MAX_SIZE;
430 /* gsharedvt */
431 max_size += 1;
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);
438 else
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;
454 if (jit->this_var)
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);
472 size = ptr - oldptr;
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);
480 } else {
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)
489 g_free (oldptr);
491 g_hash_table_insert (info->method_hash, method, address);
493 mono_debugger_unlock ();
494 return address;
497 void
498 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
500 DebugDomainInfo *info;
501 MonoDebugMethodAddress *address;
503 if (!mono_debug_initialized)
504 return;
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);
513 if (address)
514 g_free (address);
516 g_hash_table_remove (info->method_hash, method);
518 mono_debugger_unlock ();
522 * mono_debug_add_delegate_trampoline:
524 void
525 mono_debug_add_delegate_trampoline (gpointer code, int size)
529 static guint32
530 read_leb128 (guint8 *ptr, guint8 **rptr)
532 guint32 result = 0, shift = 0;
534 while (TRUE) {
535 guint8 byte = *ptr++;
537 result |= (byte & 0x7f) << shift;
538 if ((byte & 0x80) == 0)
539 break;
540 shift += 7;
543 *rptr = ptr;
544 return result;
547 static gint32
548 read_sleb128 (guint8 *ptr, guint8 **rptr)
550 gint32 result = 0;
551 guint32 shift = 0;
553 while (TRUE) {
554 guint8 byte = *ptr++;
556 result |= (byte & 0x7f) << shift;
557 shift += 7;
559 if (byte & 0x80)
560 continue;
562 if ((shift < 32) && (byte & 0x40))
563 result |= - (1 << shift);
564 break;
567 *rptr = ptr;
568 return result;
571 static void
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);
581 *rptr = ptr;
584 static void
585 free_method_jit_info (MonoDebugMethodJitInfo *jit, gboolean stack)
587 if (!jit)
588 return;
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);
595 if (!stack)
596 g_free (jit);
599 void
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)
608 guint32 i;
609 guint8 *ptr;
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) {
630 if (*ptr++) {
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);
645 if (*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);
653 return jit;
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);
665 if (!address)
666 return NULL;
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)
677 return NULL;
679 mono_debugger_lock ();
680 find_method (method, domain, res);
681 mono_debugger_unlock ();
682 return res;
685 MonoDebugMethodAddressList *
686 mono_debug_lookup_method_addresses (MonoMethod *method)
688 g_assert_not_reached ();
689 return NULL;
692 static gint32
693 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
695 MonoDebugMethodJitInfo mem;
696 int i;
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;
711 cleanup_and_fail:
712 free_method_jit_info (jit, TRUE);
713 return -1;
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.
722 gint32
723 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
725 gint32 res;
727 mono_debugger_lock ();
729 res = il_offset_from_address (method, domain, native_offset);
731 mono_debugger_unlock ();
733 return res;
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;
750 gint32 offset;
752 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
753 return NULL;
755 mono_debugger_lock ();
756 minfo = lookup_method (method);
757 if (!minfo || !minfo->handle) {
758 mono_debugger_unlock ();
759 return NULL;
762 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
763 mono_debugger_unlock ();
764 return NULL;
767 offset = il_offset_from_address (method, domain, address);
768 if (offset < 0) {
769 mono_debugger_unlock ();
770 return NULL;
773 if (minfo->handle->ppdb)
774 location = mono_ppdb_lookup_location (minfo, offset);
775 else
776 location = mono_debug_symfile_lookup_location (minfo, offset);
777 mono_debugger_unlock ();
778 return location;
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)
793 return NULL;
795 mono_debugger_lock ();
796 minfo = lookup_method (method);
797 if (!minfo || !minfo->handle) {
798 mono_debugger_unlock ();
799 return NULL;
802 if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
803 mono_debugger_unlock ();
804 return NULL;
807 if (minfo->handle->ppdb)
808 location = mono_ppdb_lookup_location (minfo, il_offset);
809 else
810 location = mono_debug_symfile_lookup_location (minfo, il_offset);
811 mono_debugger_unlock ();
812 return location;
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);
823 else
824 location = mono_debug_symfile_lookup_location (minfo, il_offset);
825 mono_debugger_unlock ();
826 return location;
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 ().
835 MonoDebugLocalsInfo*
836 mono_debug_lookup_locals (MonoMethod *method)
838 MonoDebugMethodInfo *minfo;
839 MonoDebugLocalsInfo *res;
841 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
842 return NULL;
844 mono_debugger_lock ();
845 minfo = lookup_method (method);
846 if (!minfo || !minfo->handle) {
847 mono_debugger_unlock ();
848 return NULL;
851 if (minfo->handle->ppdb) {
852 res = mono_ppdb_lookup_locals (minfo);
853 } else {
854 if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
855 res = NULL;
856 else
857 res = mono_debug_symfile_lookup_locals (minfo);
859 mono_debugger_unlock ();
861 return res;
865 * mono_debug_free_locals:
867 * Free all the data allocated by mono_debug_lookup_locals ().
869 void
870 mono_debug_free_locals (MonoDebugLocalsInfo *info)
872 int i;
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);
878 g_free (info);
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)
894 return NULL;
896 mono_debugger_lock ();
897 minfo = lookup_method (method);
898 if (!minfo || !minfo->handle) {
899 mono_debugger_unlock ();
900 return NULL;
903 if (minfo->handle->ppdb)
904 res = mono_ppdb_lookup_method_async_debug_info (minfo);
906 mono_debugger_unlock ();
908 return res;
912 * mono_debug_free_method_async_debug_info:
914 * Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
916 void
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);
924 g_free (info);
928 * mono_debug_free_source_location:
929 * \param location A \c MonoDebugSourceLocation
930 * Frees the \p location.
932 void
933 mono_debug_free_source_location (MonoDebugSourceLocation *location)
935 if (location) {
936 g_free (location->source_file);
937 g_free (location);
941 static int (*get_seq_point) (MonoDomain *domain, MonoMethod *method, gint32 native_offset);
943 void
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.
955 gchar *
956 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
958 MonoDebugSourceLocation *location;
959 gchar *fname, *ptr, *res;
960 int offset;
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);
969 if (!location) {
970 if (mono_debug_initialized) {
971 mono_debugger_lock ();
972 offset = il_offset_from_address (method, domain, native_offset);
973 mono_debugger_unlock ();
974 } else {
975 offset = -1;
978 if (offset < 0 && get_seq_point)
979 offset = get_seq_point (domain, method, native_offset);
981 if (offset < 0)
982 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
983 else {
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 ();
986 if (aotid)
987 res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
988 else
989 res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);
991 g_free (aotid);
992 g_free (mvid);
994 g_free (fname);
995 return res;
998 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
999 location->source_file, location->row);
1001 g_free (fname);
1002 mono_debug_free_source_location (location);
1003 return res;
1006 void
1007 mono_set_is_debugger_attached (gboolean attached)
1009 is_attached = attached;
1012 gboolean
1013 mono_is_debugger_attached (void)
1015 return is_attached;
1019 * Bundles
1022 typedef struct _BundledSymfile BundledSymfile;
1024 struct _BundledSymfile {
1025 BundledSymfile *next;
1026 const char *aname;
1027 const mono_byte *raw_contents;
1028 int size;
1031 static BundledSymfile *bundled_symfiles = NULL;
1034 * mono_register_symfile_for_assembly:
1036 void
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))
1056 continue;
1058 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
1061 return NULL;
1064 void
1065 mono_debugger_lock (void)
1067 g_assert (mono_debug_initialized);
1068 mono_os_mutex_lock (&debugger_lock_mutex);
1071 void
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.
1083 mono_bool
1084 mono_debug_enabled (void)
1086 return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
1089 void
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);
1094 else
1095 mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
1098 char*
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);
1105 else
1106 return NULL;