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)
12 #include <mono/metadata/assembly.h>
13 #include <mono/metadata/tabledefs.h>
14 #include <mono/metadata/tokentype.h>
15 #include <mono/metadata/appdomain.h>
16 #include <mono/metadata/class-internals.h>
17 #include <mono/metadata/mono-debug.h>
18 #include <mono/metadata/mono-debug-debugger.h>
19 #include <mono/metadata/mono-endian.h>
20 #include <mono/metadata/gc-internal.h>
23 #define DATA_TABLE_CHUNK_SIZE 16384
25 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
27 #if NO_UNALIGNED_ACCESS
28 #define RETURN_UNALIGNED(type, addr) \
31 memcpy(&val, p + offset, sizeof(val)); \
34 #define WRITE_UNALIGNED(type, addr, val) \
35 memcpy(addr, &val, sizeof(type))
36 #define READ_UNALIGNED(type, addr, val) \
37 memcpy(&val, addr, sizeof(type))
39 #define RETURN_UNALIGNED(type, addr) \
40 return *(type*)(p + offset);
41 #define WRITE_UNALIGNED(type, addr, val) \
42 (*(type *)(addr) = (val))
43 #define READ_UNALIGNED(type, addr, val) \
44 val = (*(type *)(addr))
48 MONO_DEBUG_DATA_ITEM_UNKNOWN = 0,
49 MONO_DEBUG_DATA_ITEM_CLASS,
50 MONO_DEBUG_DATA_ITEM_METHOD,
51 MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
52 } MonoDebugDataItemType;
54 typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
56 struct _MonoDebugDataChunk {
58 guint32 allocated_size;
59 guint32 current_offset;
61 MonoDebugDataChunk *next;
62 guint8 data [MONO_ZERO_LEN_ARRAY];
65 struct _MonoDebugDataTable {
67 gint32 _dummy; /* alignment for next field. */
68 MonoDebugDataChunk *first_chunk;
69 MonoDebugDataChunk *current_chunk;
70 GHashTable *method_hash;
71 GHashTable *method_address_hash;
75 const gchar *method_name;
76 const gchar *obsolete_cil_code;
78 } MonoDebugWrapperData;
85 MonoDebugWrapperData *wrapper_data;
88 } MonoDebugMethodHeader;
90 struct _MonoDebugMethodAddress {
91 MonoDebugMethodHeader header;
92 const guint8 *code_start;
93 const guint8 *wrapper_addr;
95 guint8 data [MONO_ZERO_LEN_ARRAY];
98 struct _MonoDebugClassEntry {
100 guint8 data [MONO_ZERO_LEN_ARRAY];
106 } MonoDebugDelegateTrampolineEntry;
108 MonoSymbolTable *mono_symbol_table = NULL;
109 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
110 gint32 mono_debug_debugger_version = 5;
111 gint32 _mono_debug_using_mono_debugger = 0;
113 static gboolean mono_debug_initialized = FALSE;
114 static GHashTable *mono_debug_handles = NULL;
116 static GHashTable *data_table_hash = NULL;
117 static int next_symbol_file_id = 0;
119 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
121 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
122 static void mono_debug_add_assembly (MonoAssembly *assembly,
124 static void mono_debug_add_type (MonoClass *klass);
126 static MonoDebugHandle *open_symfile_from_bundle (MonoImage *image);
128 void _mono_debug_init_corlib (MonoDomain *domain);
130 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
131 extern void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass);
133 static MonoDebugDataTable *
134 create_data_table (MonoDomain *domain)
136 MonoDebugDataTable *table;
137 MonoDebugDataChunk *chunk;
139 table = g_new0 (MonoDebugDataTable, 1);
140 table->domain = domain ? mono_domain_get_id (domain) : -1;
142 table->method_address_hash = g_hash_table_new (NULL, NULL);
143 table->method_hash = g_hash_table_new (NULL, NULL);
145 chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
146 chunk->total_size = DATA_TABLE_CHUNK_SIZE;
148 table->first_chunk = table->current_chunk = chunk;
151 mono_debug_list_add (&mono_symbol_table->data_tables, table);
152 g_hash_table_insert (data_table_hash, domain, table);
159 free_header_data (gpointer key, gpointer value, gpointer user_data)
161 MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
163 if (header->wrapper_data) {
164 g_free ((gpointer)header->wrapper_data->method_name);
165 g_slist_free (header->address_list);
166 g_free (header->wrapper_data);
171 free_data_table (MonoDebugDataTable *table)
173 MonoDebugDataChunk *chunk, *next_chunk;
175 g_hash_table_foreach (table->method_hash, free_header_data, NULL);
176 g_hash_table_destroy (table->method_hash);
177 g_hash_table_destroy (table->method_address_hash);
179 table->method_hash = NULL;
180 table->method_address_hash = NULL;
182 chunk = table->first_chunk;
184 next_chunk = chunk->next;
189 table->first_chunk = table->current_chunk = NULL;
190 mono_debug_list_remove (&mono_symbol_table->data_tables, table);
194 static MonoDebugDataTable *
195 lookup_data_table (MonoDomain *domain)
197 MonoDebugDataTable *table;
199 table = g_hash_table_lookup (data_table_hash, domain);
205 free_debug_handle (MonoDebugHandle *handle)
208 mono_debug_close_mono_symbol_file (handle->symfile);
209 /* decrease the refcount added with mono_image_addref () */
210 free_data_table (handle->type_table);
211 mono_image_close (handle->image);
212 g_free (handle->image_file);
217 * Initialize debugging support.
219 * This method must be called after loading corlib,
220 * but before opening the application's main assembly because we need to set some
224 mono_debug_init (MonoDebugFormat format)
226 g_assert (!mono_debug_initialized);
228 if (_mono_debug_using_mono_debugger)
229 format = MONO_DEBUG_FORMAT_DEBUGGER;
231 mono_debug_initialized = TRUE;
232 mono_debug_format = format;
235 * This must be called before mono_debugger_initialize(), because the
236 * latter registers GC roots.
238 mono_gc_base_init ();
240 mono_debugger_initialize (_mono_debug_using_mono_debugger);
242 mono_debugger_lock ();
244 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
245 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
246 mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
247 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
249 mono_debug_handles = g_hash_table_new_full
250 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
252 data_table_hash = g_hash_table_new_full (
253 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
255 mono_debugger_class_init_func = mono_debug_add_type;
256 mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
257 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
259 mono_symbol_table->global_data_table = create_data_table (NULL);
261 mono_debugger_unlock ();
265 * INTERNAL USE ONLY !
268 _mono_debug_init_corlib (MonoDomain *domain)
270 if (!mono_debug_initialized)
273 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
274 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
275 (guint64) (gsize) mono_symbol_table->corlib, 0);
279 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
281 mono_debug_open_image (image, raw_contents, size);
286 mono_debug_using_mono_debugger (void)
288 return _mono_debug_using_mono_debugger;
292 mono_debug_cleanup (void)
294 if (mono_debug_handles)
295 g_hash_table_destroy (mono_debug_handles);
296 mono_debug_handles = NULL;
298 if (data_table_hash) {
299 g_hash_table_destroy (data_table_hash);
300 data_table_hash = NULL;
303 if (mono_symbol_table) {
304 if (mono_symbol_table->global_data_table)
305 free_data_table (mono_symbol_table->global_data_table);
307 g_free (mono_symbol_table);
308 mono_symbol_table = NULL;
313 mono_debug_domain_create (MonoDomain *domain)
315 MonoDebugDataTable *table;
317 if (!mono_debug_initialized)
320 mono_debugger_lock ();
322 table = create_data_table (domain);
324 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
325 mono_domain_get_id (domain));
327 mono_debugger_unlock ();
331 mono_debug_domain_unload (MonoDomain *domain)
333 MonoDebugDataTable *table;
335 if (!mono_debug_initialized)
338 mono_debugger_lock ();
340 table = g_hash_table_lookup (data_table_hash, domain);
342 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
343 domain, mono_domain_get_id (domain));
344 mono_debugger_unlock ();
348 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
349 mono_domain_get_id (domain));
351 g_hash_table_remove (data_table_hash, domain);
353 mono_debugger_unlock ();
357 * LOCKING: Assumes the debug lock is held.
359 static MonoDebugHandle *
360 _mono_debug_get_image (MonoImage *image)
362 return g_hash_table_lookup (mono_debug_handles, image);
366 mono_debug_close_image (MonoImage *image)
368 MonoDebugHandle *handle;
370 if (!mono_debug_initialized)
373 mono_debugger_lock ();
375 handle = _mono_debug_get_image (image);
377 mono_debugger_unlock ();
381 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
384 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
385 g_hash_table_remove (mono_debug_handles, image);
387 mono_debugger_unlock ();
390 static MonoDebugHandle *
391 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
393 MonoDebugHandle *handle;
395 if (mono_image_is_dynamic (image))
398 mono_debugger_lock ();
400 handle = _mono_debug_get_image (image);
401 if (handle != NULL) {
402 mono_debugger_unlock ();
406 handle = g_new0 (MonoDebugHandle, 1);
407 handle->index = ++next_symbol_file_id;
409 handle->image = image;
410 mono_image_addref (image);
411 handle->image_file = g_strdup (mono_image_get_filename (image));
413 handle->type_table = create_data_table (NULL);
415 handle->symfile = mono_debug_open_mono_symbols (
416 handle, raw_contents, size, _mono_debug_using_mono_debugger);
418 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
420 g_hash_table_insert (mono_debug_handles, image, handle);
422 if (mono_symbol_table->corlib)
423 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
424 (guint64) (gsize) handle, 0);
426 mono_debugger_unlock ();
432 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
434 MonoDebugHandle *handle;
437 mono_debugger_lock ();
438 image = mono_assembly_get_image (assembly);
439 handle = open_symfile_from_bundle (image);
441 mono_debug_open_image (image, NULL, 0);
442 mono_debugger_unlock ();
446 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
451 size = ALIGN_TO (size, sizeof (gpointer));
453 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
454 chunk_size = DATA_TABLE_CHUNK_SIZE;
456 chunk_size = size + 16;
458 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
460 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
461 MonoDebugDataChunk *new_chunk;
463 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
464 new_chunk->total_size = chunk_size;
466 table->current_chunk->next = new_chunk;
467 table->current_chunk = new_chunk;
470 data = &table->current_chunk->data [table->current_chunk->allocated_size];
471 table->current_chunk->allocated_size += size + 8;
473 * ((guint32 *) data) = size;
475 * ((guint32 *) data) = type;
481 write_data_item (MonoDebugDataTable *table, const guint8 *data)
483 MonoDebugDataChunk *current_chunk = table->current_chunk;
484 guint32 size = * ((guint32 *) (data - 8));
486 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
487 current_chunk->current_offset = current_chunk->allocated_size;
490 struct LookupMethodData
492 MonoDebugMethodInfo *minfo;
497 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
499 MonoDebugHandle *handle = (MonoDebugHandle *) value;
500 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
506 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
509 static MonoDebugMethodInfo *
510 _mono_debug_lookup_method (MonoMethod *method)
512 struct LookupMethodData data;
515 data.method = method;
517 if (!mono_debug_handles)
520 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
525 * mono_debug_lookup_method:
527 * Lookup symbol file information for the method @method. The returned
528 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
529 * mono_debug_symfile_lookup_location().
531 MonoDebugMethodInfo *
532 mono_debug_lookup_method (MonoMethod *method)
534 MonoDebugMethodInfo *minfo;
536 mono_debugger_lock ();
537 minfo = _mono_debug_lookup_method (method);
538 mono_debugger_unlock ();
543 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
546 guint8 byte = value & 0x7f;
557 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
562 guint8 byte = value & 0x7f;
565 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
576 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
578 write_leb128 (var->index, ptr, &ptr);
579 write_sleb128 (var->offset, ptr, &ptr);
580 write_leb128 (var->size, ptr, &ptr);
581 write_leb128 (var->begin_scope, ptr, &ptr);
582 write_leb128 (var->end_scope, ptr, &ptr);
583 WRITE_UNALIGNED (gpointer, ptr, var->type);
584 ptr += sizeof (gpointer);
588 MonoDebugMethodAddress *
589 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
591 MonoMethod *declaring;
592 MonoDebugDataTable *table;
593 MonoDebugMethodHeader *header;
594 MonoDebugMethodAddress *address;
595 MonoDebugMethodInfo *minfo;
596 MonoDebugHandle *handle;
597 guint8 buffer [BUFSIZ];
598 guint8 *ptr, *oldptr;
599 guint32 i, size, total_size, max_size;
600 gboolean is_wrapper = FALSE;
602 mono_debugger_lock ();
604 table = lookup_data_table (domain);
606 handle = _mono_debug_get_image (method->klass->image);
607 minfo = _mono_debug_lookup_method (method);
609 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
610 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
611 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
612 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
613 (method->wrapper_type != MONO_WRAPPER_NONE)) {
617 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
618 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
620 if (max_size > BUFSIZ)
621 ptr = oldptr = g_malloc (max_size);
623 ptr = oldptr = buffer;
625 write_leb128 (jit->prologue_end, ptr, &ptr);
626 write_leb128 (jit->epilogue_begin, ptr, &ptr);
628 write_leb128 (jit->num_line_numbers, ptr, &ptr);
629 for (i = 0; i < jit->num_line_numbers; i++) {
630 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
632 write_sleb128 (lne->il_offset, ptr, &ptr);
633 write_sleb128 (lne->native_offset, ptr, &ptr);
636 *ptr++ = jit->this_var ? 1 : 0;
638 write_variable (jit->this_var, ptr, &ptr);
640 write_leb128 (jit->num_params, ptr, &ptr);
641 for (i = 0; i < jit->num_params; i++)
642 write_variable (&jit->params [i], ptr, &ptr);
644 write_leb128 (jit->num_locals, ptr, &ptr);
645 for (i = 0; i < jit->num_locals; i++)
646 write_variable (&jit->locals [i], ptr, &ptr);
649 g_assert (size < max_size);
650 total_size = size + sizeof (MonoDebugMethodAddress);
652 address = (MonoDebugMethodAddress *) allocate_data_item (
653 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
655 address->header.size = total_size;
656 address->header.symfile_id = handle ? handle->index : 0;
657 address->header.domain_id = mono_domain_get_id (domain);
658 address->header.method_id = is_wrapper ? 0 : minfo->index;
659 address->header.method = method;
661 address->code_start = jit->code_start;
662 address->code_size = jit->code_size;
664 memcpy (&address->data, oldptr, size);
665 if (max_size > BUFSIZ)
668 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
669 header = g_hash_table_lookup (table->method_hash, declaring);
672 header = &address->header;
673 g_hash_table_insert (table->method_hash, declaring, header);
676 MonoDebugWrapperData *wrapper;
678 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
680 wrapper->wrapper_type = method->wrapper_type;
681 wrapper->method_name = mono_method_full_name (declaring, TRUE);
682 wrapper->obsolete_cil_code = "";
685 address->header.wrapper_data = header->wrapper_data;
686 header->address_list = g_slist_prepend (header->address_list, address);
689 g_hash_table_insert (table->method_address_hash, method, address);
691 write_data_item (table, (guint8 *) address);
693 mono_debugger_unlock ();
698 mono_debug_add_delegate_trampoline (gpointer code, int size)
700 MonoDebugDelegateTrampolineEntry *entry;
702 if (!mono_debug_initialized)
705 mono_debugger_lock ();
707 entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
708 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
709 sizeof (MonoDebugDelegateTrampolineEntry));
713 write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
715 mono_debugger_unlock ();
718 static inline guint32
719 read_leb128 (guint8 *ptr, guint8 **rptr)
721 guint32 result = 0, shift = 0;
724 guint8 byte = *ptr++;
726 result |= (byte & 0x7f) << shift;
727 if ((byte & 0x80) == 0)
737 read_sleb128 (guint8 *ptr, guint8 **rptr)
743 guint8 byte = *ptr++;
745 result |= (byte & 0x7f) << shift;
751 if ((shift < 32) && (byte & 0x40))
752 result |= - (1 << shift);
761 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
763 var->index = read_leb128 (ptr, &ptr);
764 var->offset = read_sleb128 (ptr, &ptr);
765 var->size = read_leb128 (ptr, &ptr);
766 var->begin_scope = read_leb128 (ptr, &ptr);
767 var->end_scope = read_leb128 (ptr, &ptr);
768 READ_UNALIGNED (gpointer, ptr, var->type);
769 ptr += sizeof (gpointer);
774 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
778 g_free (jit->line_numbers);
779 g_free (jit->this_var);
780 g_free (jit->params);
781 g_free (jit->locals);
785 static MonoDebugMethodJitInfo *
786 mono_debug_read_method (MonoDebugMethodAddress *address)
788 MonoDebugMethodJitInfo *jit;
792 jit = g_new0 (MonoDebugMethodJitInfo, 1);
793 jit->code_start = address->code_start;
794 jit->code_size = address->code_size;
795 jit->wrapper_addr = address->wrapper_addr;
797 ptr = (guint8 *) &address->data;
799 jit->prologue_end = read_leb128 (ptr, &ptr);
800 jit->epilogue_begin = read_leb128 (ptr, &ptr);
802 jit->num_line_numbers = read_leb128 (ptr, &ptr);
803 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
804 for (i = 0; i < jit->num_line_numbers; i++) {
805 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
807 lne->il_offset = read_sleb128 (ptr, &ptr);
808 lne->native_offset = read_sleb128 (ptr, &ptr);
812 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
813 read_variable (jit->this_var, ptr, &ptr);
816 jit->num_params = read_leb128 (ptr, &ptr);
817 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
818 for (i = 0; i < jit->num_params; i++)
819 read_variable (&jit->params [i], ptr, &ptr);
821 jit->num_locals = read_leb128 (ptr, &ptr);
822 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
823 for (i = 0; i < jit->num_locals; i++)
824 read_variable (&jit->locals [i], ptr, &ptr);
830 mono_debug_add_type (MonoClass *klass)
832 MonoDebugHandle *handle;
833 MonoDebugClassEntry *entry;
834 guint8 buffer [BUFSIZ];
835 guint8 *ptr, *oldptr;
836 guint32 size, total_size, max_size;
839 if (klass->generic_class || klass->rank ||
840 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
843 mono_debugger_lock ();
845 handle = _mono_debug_get_image (klass->image);
847 mono_debugger_unlock ();
851 max_size = 12 + sizeof (gpointer);
852 if (max_size > BUFSIZ)
853 ptr = oldptr = g_malloc (max_size);
855 ptr = oldptr = buffer;
857 if (klass->valuetype)
858 base_offset = - (int)(sizeof (MonoObject));
860 write_leb128 (klass->type_token, ptr, &ptr);
861 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
862 WRITE_UNALIGNED (gpointer, ptr, klass);
863 ptr += sizeof (gpointer);
866 g_assert (size < max_size);
867 total_size = size + sizeof (MonoDebugClassEntry);
869 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
871 entry = (MonoDebugClassEntry *) allocate_data_item (
872 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
874 entry->size = total_size;
876 memcpy (&entry->data, oldptr, size);
878 write_data_item (handle->type_table, (guint8 *) entry);
880 if (max_size > BUFSIZ)
883 mono_debugger_unlock ();
886 static MonoDebugMethodJitInfo *
887 find_method (MonoMethod *method, MonoDomain *domain)
889 MonoDebugDataTable *table;
890 MonoDebugMethodAddress *address;
892 table = lookup_data_table (domain);
893 address = g_hash_table_lookup (table->method_address_hash, method);
898 return mono_debug_read_method (address);
901 MonoDebugMethodJitInfo *
902 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
904 MonoDebugMethodJitInfo *res;
906 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
909 mono_debugger_lock ();
910 res = find_method (method, domain);
911 mono_debugger_unlock ();
915 struct LookupMethodAddressData
918 MonoDebugMethodHeader *result;
922 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
924 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
925 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
926 MonoDebugMethodHeader *header;
928 header = g_hash_table_lookup (table->method_hash, data->method);
930 data->result = header;
933 MonoDebugMethodAddressList *
934 mono_debug_lookup_method_addresses (MonoMethod *method)
936 MonoDebugMethodAddressList *info;
937 MonoDebugMethodHeader *header = NULL;
938 struct LookupMethodAddressData data;
939 MonoMethod *declaring;
944 g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
946 mono_debugger_lock ();
948 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
950 data.method = declaring;
953 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
954 header = data.result;
957 mono_debugger_unlock ();
961 count = g_slist_length (header->address_list) + 1;
962 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
964 info = g_malloc0 (size);
970 WRITE_UNALIGNED (gpointer, ptr, header);
971 ptr += sizeof (gpointer);
973 for (list = header->address_list; list; list = list->next) {
974 WRITE_UNALIGNED (gpointer, ptr, list->data);
975 ptr += sizeof (gpointer);
978 mono_debugger_unlock ();
983 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
985 MonoDebugMethodJitInfo *jit;
988 jit = find_method (method, domain);
989 if (!jit || !jit->line_numbers)
990 goto cleanup_and_fail;
992 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
993 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
995 if (lne.native_offset <= native_offset) {
996 mono_debug_free_method_jit_info (jit);
997 return lne.il_offset;
1002 mono_debug_free_method_jit_info (jit);
1007 * mono_debug_il_offset_from_address:
1009 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
1010 * code of METHOD in DOMAIN.
1013 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1017 mono_debugger_lock ();
1019 res = il_offset_from_address (method, domain, native_offset);
1021 mono_debugger_unlock ();
1027 * mono_debug_lookup_source_location:
1028 * @address: Native offset within the @method's machine code.
1030 * Lookup the source code corresponding to the machine instruction located at
1031 * native offset @address within @method.
1033 * The returned `MonoDebugSourceLocation' contains both file / line number
1034 * information and the corresponding IL offset. It must be freed by
1035 * mono_debug_free_source_location().
1037 MonoDebugSourceLocation *
1038 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1040 MonoDebugMethodInfo *minfo;
1041 MonoDebugSourceLocation *location;
1044 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1047 mono_debugger_lock ();
1048 minfo = _mono_debug_lookup_method (method);
1049 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1050 mono_debugger_unlock ();
1054 offset = il_offset_from_address (method, domain, address);
1056 mono_debugger_unlock ();
1060 location = mono_debug_symfile_lookup_location (minfo, offset);
1061 mono_debugger_unlock ();
1066 * mono_debug_lookup_locals:
1068 * Return information about the local variables of MINFO.
1069 * The result should be freed using mono_debug_symfile_free_locals ().
1071 MonoDebugLocalsInfo*
1072 mono_debug_lookup_locals (MonoMethod *method)
1074 MonoDebugMethodInfo *minfo;
1075 MonoDebugLocalsInfo *res;
1077 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1080 mono_debugger_lock ();
1081 minfo = _mono_debug_lookup_method (method);
1082 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1083 mono_debugger_unlock ();
1087 res = mono_debug_symfile_lookup_locals (minfo);
1088 mono_debugger_unlock ();
1094 * mono_debug_free_source_location:
1095 * @location: A `MonoDebugSourceLocation'.
1097 * Frees the @location.
1100 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1103 g_free (location->source_file);
1109 * mono_debug_print_stack_frame:
1110 * @native_offset: Native offset within the @method's machine code.
1112 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1113 * used if you only want to use the location to print a stack frame.
1116 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1118 MonoDebugSourceLocation *location;
1119 gchar *fname, *ptr, *res;
1122 fname = mono_method_full_name (method, TRUE);
1123 for (ptr = fname; *ptr; ptr++) {
1124 if (*ptr == ':') *ptr = '.';
1127 location = mono_debug_lookup_source_location (method, native_offset, domain);
1130 if (mono_debug_initialized) {
1131 mono_debugger_lock ();
1132 offset = il_offset_from_address (method, domain, native_offset);
1133 mono_debugger_unlock ();
1139 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1141 res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1146 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1147 location->source_file, location->row);
1150 mono_debug_free_source_location (location);
1155 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1157 MonoDebugList *element, **ptr;
1159 element = g_new0 (MonoDebugList, 1);
1160 element->data = data;
1162 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1169 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1171 MonoDebugList **ptr;
1172 MonoDebugList *next;
1174 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1175 if ((*ptr)->data != data)
1178 next = (*ptr)->next;
1185 static gboolean is_attached = FALSE;
1188 mono_set_is_debugger_attached (gboolean attached)
1190 is_attached = attached;
1194 mono_is_debugger_attached (void)
1203 typedef struct _BundledSymfile BundledSymfile;
1205 struct _BundledSymfile {
1206 BundledSymfile *next;
1208 const mono_byte *raw_contents;
1212 static BundledSymfile *bundled_symfiles = NULL;
1215 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1217 BundledSymfile *bsymfile;
1219 bsymfile = g_new0 (BundledSymfile, 1);
1220 bsymfile->aname = assembly_name;
1221 bsymfile->raw_contents = raw_contents;
1222 bsymfile->size = size;
1223 bsymfile->next = bundled_symfiles;
1224 bundled_symfiles = bsymfile;
1227 static MonoDebugHandle *
1228 open_symfile_from_bundle (MonoImage *image)
1230 BundledSymfile *bsymfile;
1232 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1233 if (strcmp (bsymfile->aname, image->module_name))
1236 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);