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)
13 #include <mono/metadata/assembly.h>
14 #include <mono/metadata/tabledefs.h>
15 #include <mono/metadata/tokentype.h>
16 #include <mono/metadata/appdomain.h>
17 #include <mono/metadata/class-internals.h>
18 #include <mono/metadata/mono-debug.h>
19 #include <mono/metadata/mono-debug-debugger.h>
20 #include <mono/metadata/mono-endian.h>
21 #include <mono/metadata/gc-internal.h>
24 #define DATA_TABLE_CHUNK_SIZE (16384-sizeof (MonoDebugDataChunk))
26 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
28 #if NO_UNALIGNED_ACCESS
29 #define RETURN_UNALIGNED(type, addr) \
32 memcpy(&val, p + offset, sizeof(val)); \
35 #define WRITE_UNALIGNED(type, addr, val) \
36 memcpy(addr, &val, sizeof(type))
37 #define READ_UNALIGNED(type, addr, val) \
38 memcpy(&val, addr, sizeof(type))
40 #define RETURN_UNALIGNED(type, addr) \
41 return *(type*)(p + offset);
42 #define WRITE_UNALIGNED(type, addr, val) \
43 (*(type *)(addr) = (val))
44 #define READ_UNALIGNED(type, addr, val) \
45 val = (*(type *)(addr))
49 MONO_DEBUG_DATA_ITEM_UNKNOWN = 0,
50 MONO_DEBUG_DATA_ITEM_CLASS,
51 MONO_DEBUG_DATA_ITEM_METHOD,
52 MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
53 } MonoDebugDataItemType;
55 typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
57 struct _MonoDebugDataChunk {
59 guint32 allocated_size;
60 guint32 current_offset;
62 MonoDebugDataChunk *next;
63 guint8 data [MONO_ZERO_LEN_ARRAY];
66 struct _MonoDebugDataTable {
68 gint32 _dummy; /* alignment for next field. */
69 MonoDebugDataChunk *first_chunk;
70 MonoDebugDataChunk *current_chunk;
71 GHashTable *method_hash;
72 GHashTable *method_address_hash;
76 const gchar *method_name;
77 const gchar *obsolete_cil_code;
79 } MonoDebugWrapperData;
86 MonoDebugWrapperData *wrapper_data;
89 } MonoDebugMethodHeader;
91 struct _MonoDebugMethodAddress {
92 MonoDebugMethodHeader header;
93 const guint8 *code_start;
94 const guint8 *wrapper_addr;
96 guint8 data [MONO_ZERO_LEN_ARRAY];
99 struct _MonoDebugClassEntry {
101 guint8 data [MONO_ZERO_LEN_ARRAY];
107 } MonoDebugDelegateTrampolineEntry;
109 MonoSymbolTable *mono_symbol_table = NULL;
110 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
111 gint32 mono_debug_debugger_version = 5;
112 gint32 _mono_debug_using_mono_debugger = 0;
114 static gboolean mono_debug_initialized = FALSE;
115 static GHashTable *mono_debug_handles = NULL;
117 static GHashTable *data_table_hash = NULL;
118 static int next_symbol_file_id = 0;
120 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
122 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
123 static void mono_debug_add_assembly (MonoAssembly *assembly,
125 static void mono_debug_add_type (MonoClass *klass);
127 static MonoDebugHandle *open_symfile_from_bundle (MonoImage *image);
129 void _mono_debug_init_corlib (MonoDomain *domain);
131 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
132 extern void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass);
134 static MonoDebugDataTable *
135 create_data_table (MonoDomain *domain)
137 MonoDebugDataTable *table;
138 MonoDebugDataChunk *chunk;
140 table = g_new0 (MonoDebugDataTable, 1);
141 table->domain = domain ? mono_domain_get_id (domain) : -1;
143 table->method_address_hash = g_hash_table_new (NULL, NULL);
144 table->method_hash = g_hash_table_new (NULL, NULL);
146 chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
147 chunk->total_size = DATA_TABLE_CHUNK_SIZE;
149 table->first_chunk = table->current_chunk = chunk;
152 mono_debug_list_add (&mono_symbol_table->data_tables, table);
153 g_hash_table_insert (data_table_hash, domain, table);
160 free_header_data (gpointer key, gpointer value, gpointer user_data)
162 MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
164 if (header->wrapper_data) {
165 g_free ((gpointer)header->wrapper_data->method_name);
166 g_free (header->wrapper_data);
168 g_slist_free (header->address_list);
172 free_data_table (MonoDebugDataTable *table)
174 MonoDebugDataChunk *chunk, *next_chunk;
176 g_hash_table_foreach (table->method_hash, free_header_data, NULL);
177 g_hash_table_destroy (table->method_hash);
178 g_hash_table_destroy (table->method_address_hash);
180 table->method_hash = NULL;
181 table->method_address_hash = NULL;
183 chunk = table->first_chunk;
185 next_chunk = chunk->next;
190 table->first_chunk = table->current_chunk = NULL;
191 mono_debug_list_remove (&mono_symbol_table->data_tables, table);
195 static MonoDebugDataTable *
196 lookup_data_table (MonoDomain *domain)
198 MonoDebugDataTable *table;
200 table = g_hash_table_lookup (data_table_hash, domain);
202 g_error ("lookup_data_table () failed for %p\n", domain);
209 free_debug_handle (MonoDebugHandle *handle)
212 mono_debug_close_mono_symbol_file (handle->symfile);
213 /* decrease the refcount added with mono_image_addref () */
214 free_data_table (handle->type_table);
215 mono_image_close (handle->image);
216 g_free (handle->image_file);
221 * Initialize debugging support.
223 * This method must be called after loading corlib,
224 * but before opening the application's main assembly because we need to set some
228 mono_debug_init (MonoDebugFormat format)
230 g_assert (!mono_debug_initialized);
232 if (_mono_debug_using_mono_debugger)
233 format = MONO_DEBUG_FORMAT_DEBUGGER;
235 mono_debug_initialized = TRUE;
236 mono_debug_format = format;
239 * This must be called before mono_debugger_initialize(), because the
240 * latter registers GC roots.
242 mono_gc_base_init ();
244 mono_debugger_initialize (_mono_debug_using_mono_debugger);
246 mono_debugger_lock ();
248 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
249 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
250 mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
251 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
253 mono_debug_handles = g_hash_table_new_full
254 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
256 data_table_hash = g_hash_table_new_full (
257 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
259 mono_debugger_class_init_func = mono_debug_add_type;
260 mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
261 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
263 mono_symbol_table->global_data_table = create_data_table (NULL);
265 mono_debugger_unlock ();
269 * INTERNAL USE ONLY !
272 _mono_debug_init_corlib (MonoDomain *domain)
274 if (!mono_debug_initialized)
277 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
278 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
279 (guint64) (gsize) mono_symbol_table->corlib, 0);
283 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
285 if (!mono_debug_initialized)
288 mono_debug_open_image (image, raw_contents, size);
293 mono_debug_using_mono_debugger (void)
295 return _mono_debug_using_mono_debugger;
299 mono_debug_cleanup (void)
301 if (mono_debug_handles)
302 g_hash_table_destroy (mono_debug_handles);
303 mono_debug_handles = NULL;
305 if (data_table_hash) {
306 g_hash_table_destroy (data_table_hash);
307 data_table_hash = NULL;
310 if (mono_symbol_table) {
311 if (mono_symbol_table->global_data_table)
312 free_data_table (mono_symbol_table->global_data_table);
314 g_free (mono_symbol_table);
315 mono_symbol_table = NULL;
320 mono_debug_domain_create (MonoDomain *domain)
322 MonoDebugDataTable *table;
324 if (!mono_debug_initialized)
327 mono_debugger_lock ();
329 table = create_data_table (domain);
331 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
332 mono_domain_get_id (domain));
334 mono_debugger_unlock ();
338 mono_debug_domain_unload (MonoDomain *domain)
340 MonoDebugDataTable *table;
342 if (!mono_debug_initialized)
345 mono_debugger_lock ();
347 table = g_hash_table_lookup (data_table_hash, domain);
349 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
350 domain, mono_domain_get_id (domain));
351 mono_debugger_unlock ();
355 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
356 mono_domain_get_id (domain));
358 g_hash_table_remove (data_table_hash, domain);
360 mono_debugger_unlock ();
364 * LOCKING: Assumes the debug lock is held.
366 static MonoDebugHandle *
367 _mono_debug_get_image (MonoImage *image)
369 return g_hash_table_lookup (mono_debug_handles, image);
373 mono_debug_close_image (MonoImage *image)
375 MonoDebugHandle *handle;
377 if (!mono_debug_initialized)
380 mono_debugger_lock ();
382 handle = _mono_debug_get_image (image);
384 mono_debugger_unlock ();
388 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
391 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
392 g_hash_table_remove (mono_debug_handles, image);
394 mono_debugger_unlock ();
397 static MonoDebugHandle *
398 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
400 MonoDebugHandle *handle;
402 if (mono_image_is_dynamic (image))
405 mono_debugger_lock ();
407 handle = _mono_debug_get_image (image);
408 if (handle != NULL) {
409 mono_debugger_unlock ();
413 handle = g_new0 (MonoDebugHandle, 1);
414 handle->index = ++next_symbol_file_id;
416 handle->image = image;
417 mono_image_addref (image);
418 handle->image_file = g_strdup (mono_image_get_filename (image));
420 handle->type_table = create_data_table (NULL);
422 handle->symfile = mono_debug_open_mono_symbols (
423 handle, raw_contents, size, _mono_debug_using_mono_debugger);
425 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
427 g_hash_table_insert (mono_debug_handles, image, handle);
429 if (mono_symbol_table->corlib)
430 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
431 (guint64) (gsize) handle, 0);
433 mono_debugger_unlock ();
439 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
441 MonoDebugHandle *handle;
444 mono_debugger_lock ();
445 image = mono_assembly_get_image (assembly);
446 handle = open_symfile_from_bundle (image);
448 mono_debug_open_image (image, NULL, 0);
449 mono_debugger_unlock ();
453 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
458 size = ALIGN_TO (size, sizeof (gpointer));
460 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
461 chunk_size = DATA_TABLE_CHUNK_SIZE;
463 chunk_size = size + 16;
465 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
467 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
468 MonoDebugDataChunk *new_chunk;
470 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
471 new_chunk->total_size = chunk_size;
473 table->current_chunk->next = new_chunk;
474 table->current_chunk = new_chunk;
477 data = &table->current_chunk->data [table->current_chunk->allocated_size];
478 table->current_chunk->allocated_size += size + 8;
480 * ((guint32 *) data) = size;
482 * ((guint32 *) data) = type;
488 write_data_item (MonoDebugDataTable *table, const guint8 *data)
490 MonoDebugDataChunk *current_chunk = table->current_chunk;
491 guint32 size = * ((guint32 *) (data - 8));
493 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
494 current_chunk->current_offset = current_chunk->allocated_size;
497 struct LookupMethodData
499 MonoDebugMethodInfo *minfo;
504 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
506 MonoDebugHandle *handle = (MonoDebugHandle *) value;
507 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
513 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
516 static MonoDebugMethodInfo *
517 _mono_debug_lookup_method (MonoMethod *method)
519 struct LookupMethodData data;
522 data.method = method;
524 if (!mono_debug_handles)
527 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
532 * mono_debug_lookup_method:
534 * Lookup symbol file information for the method @method. The returned
535 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
536 * mono_debug_symfile_lookup_location().
538 MonoDebugMethodInfo *
539 mono_debug_lookup_method (MonoMethod *method)
541 MonoDebugMethodInfo *minfo;
543 mono_debugger_lock ();
544 minfo = _mono_debug_lookup_method (method);
545 mono_debugger_unlock ();
550 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
553 guint8 byte = value & 0x7f;
564 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
569 guint8 byte = value & 0x7f;
572 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
583 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
585 write_leb128 (var->index, ptr, &ptr);
586 write_sleb128 (var->offset, ptr, &ptr);
587 write_leb128 (var->size, ptr, &ptr);
588 write_leb128 (var->begin_scope, ptr, &ptr);
589 write_leb128 (var->end_scope, ptr, &ptr);
590 WRITE_UNALIGNED (gpointer, ptr, var->type);
591 ptr += sizeof (gpointer);
595 MonoDebugMethodAddress *
596 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
598 MonoMethod *declaring;
599 MonoDebugDataTable *table;
600 MonoDebugMethodHeader *header;
601 MonoDebugMethodAddress *address;
602 MonoDebugMethodInfo *minfo;
603 MonoDebugHandle *handle;
604 guint8 buffer [BUFSIZ];
605 guint8 *ptr, *oldptr;
606 guint32 i, size, total_size, max_size;
607 gboolean is_wrapper = FALSE;
609 mono_debugger_lock ();
611 table = lookup_data_table (domain);
613 handle = _mono_debug_get_image (method->klass->image);
614 minfo = _mono_debug_lookup_method (method);
616 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
617 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
618 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
619 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
620 (method->wrapper_type != MONO_WRAPPER_NONE)) {
624 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
625 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
627 if (max_size > BUFSIZ)
628 ptr = oldptr = g_malloc (max_size);
630 ptr = oldptr = buffer;
632 write_leb128 (jit->prologue_end, ptr, &ptr);
633 write_leb128 (jit->epilogue_begin, ptr, &ptr);
635 write_leb128 (jit->num_line_numbers, ptr, &ptr);
636 for (i = 0; i < jit->num_line_numbers; i++) {
637 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
639 write_sleb128 (lne->il_offset, ptr, &ptr);
640 write_sleb128 (lne->native_offset, ptr, &ptr);
643 *ptr++ = jit->this_var ? 1 : 0;
645 write_variable (jit->this_var, ptr, &ptr);
647 write_leb128 (jit->num_params, ptr, &ptr);
648 for (i = 0; i < jit->num_params; i++)
649 write_variable (&jit->params [i], ptr, &ptr);
651 write_leb128 (jit->num_locals, ptr, &ptr);
652 for (i = 0; i < jit->num_locals; i++)
653 write_variable (&jit->locals [i], ptr, &ptr);
655 *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
656 if (jit->gsharedvt_info_var) {
657 write_variable (jit->gsharedvt_info_var, ptr, &ptr);
658 write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
662 g_assert (size < max_size);
663 total_size = size + sizeof (MonoDebugMethodAddress);
665 if (method->dynamic) {
666 address = g_malloc0 (total_size);
668 address = (MonoDebugMethodAddress *) allocate_data_item (
669 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
672 address->header.size = total_size;
673 address->header.symfile_id = handle ? handle->index : 0;
674 address->header.domain_id = mono_domain_get_id (domain);
675 address->header.method_id = is_wrapper ? 0 : minfo->index;
676 address->header.method = method;
678 address->code_start = jit->code_start;
679 address->code_size = jit->code_size;
681 memcpy (&address->data, oldptr, size);
682 if (max_size > BUFSIZ)
685 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
686 header = g_hash_table_lookup (table->method_hash, declaring);
689 header = &address->header;
690 g_hash_table_insert (table->method_hash, declaring, header);
693 MonoDebugWrapperData *wrapper;
695 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
697 wrapper->wrapper_type = method->wrapper_type;
698 wrapper->method_name = mono_method_full_name (declaring, TRUE);
699 wrapper->obsolete_cil_code = "";
702 address->header.wrapper_data = header->wrapper_data;
703 header->address_list = g_slist_prepend (header->address_list, address);
706 g_hash_table_insert (table->method_address_hash, method, address);
708 if (!method->dynamic)
709 write_data_item (table, (guint8 *) address);
711 mono_debugger_unlock ();
716 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
718 MonoMethod *declaring;
719 MonoDebugDataTable *table;
720 MonoDebugMethodHeader *header;
721 MonoDebugMethodAddress *address;
723 if (!mono_debug_initialized)
726 g_assert (method->dynamic);
728 mono_debugger_lock ();
730 table = lookup_data_table (domain);
732 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
733 g_hash_table_remove (table->method_hash, declaring);
735 address = g_hash_table_lookup (table->method_address_hash, method);
737 header = &address->header;
739 if (header->wrapper_data) {
740 g_free ((char*)header->wrapper_data->method_name);
741 g_free (header->wrapper_data);
746 g_hash_table_remove (table->method_address_hash, method);
748 mono_debugger_unlock ();
752 mono_debug_add_delegate_trampoline (gpointer code, int size)
754 MonoDebugDelegateTrampolineEntry *entry;
756 if (!mono_debug_initialized)
759 mono_debugger_lock ();
761 entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
762 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
763 sizeof (MonoDebugDelegateTrampolineEntry));
767 write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
769 mono_debugger_unlock ();
772 static inline guint32
773 read_leb128 (guint8 *ptr, guint8 **rptr)
775 guint32 result = 0, shift = 0;
778 guint8 byte = *ptr++;
780 result |= (byte & 0x7f) << shift;
781 if ((byte & 0x80) == 0)
791 read_sleb128 (guint8 *ptr, guint8 **rptr)
797 guint8 byte = *ptr++;
799 result |= (byte & 0x7f) << shift;
805 if ((shift < 32) && (byte & 0x40))
806 result |= - (1 << shift);
815 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
817 var->index = read_leb128 (ptr, &ptr);
818 var->offset = read_sleb128 (ptr, &ptr);
819 var->size = read_leb128 (ptr, &ptr);
820 var->begin_scope = read_leb128 (ptr, &ptr);
821 var->end_scope = read_leb128 (ptr, &ptr);
822 READ_UNALIGNED (gpointer, ptr, var->type);
823 ptr += sizeof (gpointer);
828 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
832 g_free (jit->line_numbers);
833 g_free (jit->this_var);
834 g_free (jit->params);
835 g_free (jit->locals);
836 g_free (jit->gsharedvt_info_var);
837 g_free (jit->gsharedvt_locals_var);
841 static MonoDebugMethodJitInfo *
842 mono_debug_read_method (MonoDebugMethodAddress *address)
844 MonoDebugMethodJitInfo *jit;
848 jit = g_new0 (MonoDebugMethodJitInfo, 1);
849 jit->code_start = address->code_start;
850 jit->code_size = address->code_size;
851 jit->wrapper_addr = address->wrapper_addr;
853 ptr = (guint8 *) &address->data;
855 jit->prologue_end = read_leb128 (ptr, &ptr);
856 jit->epilogue_begin = read_leb128 (ptr, &ptr);
858 jit->num_line_numbers = read_leb128 (ptr, &ptr);
859 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
860 for (i = 0; i < jit->num_line_numbers; i++) {
861 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
863 lne->il_offset = read_sleb128 (ptr, &ptr);
864 lne->native_offset = read_sleb128 (ptr, &ptr);
868 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
869 read_variable (jit->this_var, ptr, &ptr);
872 jit->num_params = read_leb128 (ptr, &ptr);
873 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
874 for (i = 0; i < jit->num_params; i++)
875 read_variable (&jit->params [i], ptr, &ptr);
877 jit->num_locals = read_leb128 (ptr, &ptr);
878 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
879 for (i = 0; i < jit->num_locals; i++)
880 read_variable (&jit->locals [i], ptr, &ptr);
883 jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
884 jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
885 read_variable (jit->gsharedvt_info_var, ptr, &ptr);
886 read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
893 mono_debug_add_type (MonoClass *klass)
895 MonoDebugHandle *handle;
896 MonoDebugClassEntry *entry;
897 guint8 buffer [BUFSIZ];
898 guint8 *ptr, *oldptr;
899 guint32 size, total_size, max_size;
902 if (klass->generic_class || klass->rank ||
903 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
906 mono_debugger_lock ();
908 handle = _mono_debug_get_image (klass->image);
910 mono_debugger_unlock ();
914 max_size = 12 + sizeof (gpointer);
915 if (max_size > BUFSIZ)
916 ptr = oldptr = g_malloc (max_size);
918 ptr = oldptr = buffer;
920 if (klass->valuetype)
921 base_offset = - (int)(sizeof (MonoObject));
923 write_leb128 (klass->type_token, ptr, &ptr);
924 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
925 WRITE_UNALIGNED (gpointer, ptr, klass);
926 ptr += sizeof (gpointer);
929 g_assert (size < max_size);
930 total_size = size + sizeof (MonoDebugClassEntry);
932 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
934 entry = (MonoDebugClassEntry *) allocate_data_item (
935 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
937 entry->size = total_size;
939 memcpy (&entry->data, oldptr, size);
941 write_data_item (handle->type_table, (guint8 *) entry);
943 if (max_size > BUFSIZ)
946 mono_debugger_unlock ();
949 static MonoDebugMethodJitInfo *
950 find_method (MonoMethod *method, MonoDomain *domain)
952 MonoDebugDataTable *table;
953 MonoDebugMethodAddress *address;
955 table = lookup_data_table (domain);
956 address = g_hash_table_lookup (table->method_address_hash, method);
961 return mono_debug_read_method (address);
964 MonoDebugMethodJitInfo *
965 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
967 MonoDebugMethodJitInfo *res;
969 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
972 mono_debugger_lock ();
973 res = find_method (method, domain);
974 mono_debugger_unlock ();
978 struct LookupMethodAddressData
981 MonoDebugMethodHeader *result;
985 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
987 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
988 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
989 MonoDebugMethodHeader *header;
991 header = g_hash_table_lookup (table->method_hash, data->method);
993 data->result = header;
996 MonoDebugMethodAddressList *
997 mono_debug_lookup_method_addresses (MonoMethod *method)
999 MonoDebugMethodAddressList *info;
1000 MonoDebugMethodHeader *header = NULL;
1001 struct LookupMethodAddressData data;
1002 MonoMethod *declaring;
1007 g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
1009 mono_debugger_lock ();
1011 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
1013 data.method = declaring;
1016 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
1017 header = data.result;
1020 mono_debugger_unlock ();
1024 count = g_slist_length (header->address_list) + 1;
1025 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
1027 info = g_malloc0 (size);
1029 info->count = count;
1033 WRITE_UNALIGNED (gpointer, ptr, header);
1034 ptr += sizeof (gpointer);
1036 for (list = header->address_list; list; list = list->next) {
1037 WRITE_UNALIGNED (gpointer, ptr, list->data);
1038 ptr += sizeof (gpointer);
1041 mono_debugger_unlock ();
1046 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1048 MonoDebugMethodJitInfo *jit;
1051 jit = find_method (method, domain);
1052 if (!jit || !jit->line_numbers)
1053 goto cleanup_and_fail;
1055 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1056 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1058 if (lne.native_offset <= native_offset) {
1059 mono_debug_free_method_jit_info (jit);
1060 return lne.il_offset;
1065 mono_debug_free_method_jit_info (jit);
1070 * mono_debug_il_offset_from_address:
1072 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
1073 * code of METHOD in DOMAIN.
1076 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1080 mono_debugger_lock ();
1082 res = il_offset_from_address (method, domain, native_offset);
1084 mono_debugger_unlock ();
1090 * mono_debug_lookup_source_location:
1091 * @address: Native offset within the @method's machine code.
1093 * Lookup the source code corresponding to the machine instruction located at
1094 * native offset @address within @method.
1096 * The returned `MonoDebugSourceLocation' contains both file / line number
1097 * information and the corresponding IL offset. It must be freed by
1098 * mono_debug_free_source_location().
1100 MonoDebugSourceLocation *
1101 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1103 MonoDebugMethodInfo *minfo;
1104 MonoDebugSourceLocation *location;
1107 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1110 mono_debugger_lock ();
1111 minfo = _mono_debug_lookup_method (method);
1112 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1113 mono_debugger_unlock ();
1117 offset = il_offset_from_address (method, domain, address);
1119 mono_debugger_unlock ();
1123 location = mono_debug_symfile_lookup_location (minfo, offset);
1124 mono_debugger_unlock ();
1129 * mono_debug_lookup_locals:
1131 * Return information about the local variables of MINFO.
1132 * The result should be freed using mono_debug_symfile_free_locals ().
1134 MonoDebugLocalsInfo*
1135 mono_debug_lookup_locals (MonoMethod *method)
1137 MonoDebugMethodInfo *minfo;
1138 MonoDebugLocalsInfo *res;
1140 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1143 mono_debugger_lock ();
1144 minfo = _mono_debug_lookup_method (method);
1145 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1146 mono_debugger_unlock ();
1150 res = mono_debug_symfile_lookup_locals (minfo);
1151 mono_debugger_unlock ();
1157 * mono_debug_free_source_location:
1158 * @location: A `MonoDebugSourceLocation'.
1160 * Frees the @location.
1163 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1166 g_free (location->source_file);
1172 * mono_debug_print_stack_frame:
1173 * @native_offset: Native offset within the @method's machine code.
1175 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1176 * used if you only want to use the location to print a stack frame.
1179 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1181 MonoDebugSourceLocation *location;
1182 gchar *fname, *ptr, *res;
1185 fname = mono_method_full_name (method, TRUE);
1186 for (ptr = fname; *ptr; ptr++) {
1187 if (*ptr == ':') *ptr = '.';
1190 location = mono_debug_lookup_source_location (method, native_offset, domain);
1193 if (mono_debug_initialized) {
1194 mono_debugger_lock ();
1195 offset = il_offset_from_address (method, domain, native_offset);
1196 mono_debugger_unlock ();
1202 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1204 res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1209 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1210 location->source_file, location->row);
1213 mono_debug_free_source_location (location);
1218 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1220 MonoDebugList *element, **ptr;
1222 element = g_new0 (MonoDebugList, 1);
1223 element->data = data;
1225 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1232 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1234 MonoDebugList **ptr;
1235 MonoDebugList *next;
1237 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1238 if ((*ptr)->data != data)
1241 next = (*ptr)->next;
1248 static gboolean is_attached = FALSE;
1251 mono_set_is_debugger_attached (gboolean attached)
1253 is_attached = attached;
1257 mono_is_debugger_attached (void)
1266 typedef struct _BundledSymfile BundledSymfile;
1268 struct _BundledSymfile {
1269 BundledSymfile *next;
1271 const mono_byte *raw_contents;
1275 static BundledSymfile *bundled_symfiles = NULL;
1278 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1280 BundledSymfile *bsymfile;
1282 bsymfile = g_new0 (BundledSymfile, 1);
1283 bsymfile->aname = assembly_name;
1284 bsymfile->raw_contents = raw_contents;
1285 bsymfile->size = size;
1286 bsymfile->next = bundled_symfiles;
1287 bundled_symfiles = bsymfile;
1290 static MonoDebugHandle *
1291 open_symfile_from_bundle (MonoImage *image)
1293 BundledSymfile *bsymfile;
1295 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1296 if (strcmp (bsymfile->aname, image->module_name))
1299 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);