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);
206 free_debug_handle (MonoDebugHandle *handle)
209 mono_debug_close_mono_symbol_file (handle->symfile);
210 /* decrease the refcount added with mono_image_addref () */
211 free_data_table (handle->type_table);
212 mono_image_close (handle->image);
213 g_free (handle->image_file);
218 * Initialize debugging support.
220 * This method must be called after loading corlib,
221 * but before opening the application's main assembly because we need to set some
225 mono_debug_init (MonoDebugFormat format)
227 g_assert (!mono_debug_initialized);
229 if (_mono_debug_using_mono_debugger)
230 format = MONO_DEBUG_FORMAT_DEBUGGER;
232 mono_debug_initialized = TRUE;
233 mono_debug_format = format;
236 * This must be called before mono_debugger_initialize(), because the
237 * latter registers GC roots.
239 mono_gc_base_init ();
241 mono_debugger_initialize (_mono_debug_using_mono_debugger);
243 mono_debugger_lock ();
245 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
246 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
247 mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
248 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
250 mono_debug_handles = g_hash_table_new_full
251 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
253 data_table_hash = g_hash_table_new_full (
254 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
256 mono_debugger_class_init_func = mono_debug_add_type;
257 mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
258 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
260 mono_symbol_table->global_data_table = create_data_table (NULL);
262 mono_debugger_unlock ();
266 * INTERNAL USE ONLY !
269 _mono_debug_init_corlib (MonoDomain *domain)
271 if (!mono_debug_initialized)
274 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
275 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
276 (guint64) (gsize) mono_symbol_table->corlib, 0);
280 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
282 if (!mono_debug_initialized)
285 mono_debug_open_image (image, raw_contents, size);
290 mono_debug_using_mono_debugger (void)
292 return _mono_debug_using_mono_debugger;
296 mono_debug_cleanup (void)
298 if (mono_debug_handles)
299 g_hash_table_destroy (mono_debug_handles);
300 mono_debug_handles = NULL;
302 if (data_table_hash) {
303 g_hash_table_destroy (data_table_hash);
304 data_table_hash = NULL;
307 if (mono_symbol_table) {
308 if (mono_symbol_table->global_data_table)
309 free_data_table (mono_symbol_table->global_data_table);
311 g_free (mono_symbol_table);
312 mono_symbol_table = NULL;
317 mono_debug_domain_create (MonoDomain *domain)
319 MonoDebugDataTable *table;
321 if (!mono_debug_initialized)
324 mono_debugger_lock ();
326 table = create_data_table (domain);
328 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
329 mono_domain_get_id (domain));
331 mono_debugger_unlock ();
335 mono_debug_domain_unload (MonoDomain *domain)
337 MonoDebugDataTable *table;
339 if (!mono_debug_initialized)
342 mono_debugger_lock ();
344 table = g_hash_table_lookup (data_table_hash, domain);
346 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
347 domain, mono_domain_get_id (domain));
348 mono_debugger_unlock ();
352 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
353 mono_domain_get_id (domain));
355 g_hash_table_remove (data_table_hash, domain);
357 mono_debugger_unlock ();
361 * LOCKING: Assumes the debug lock is held.
363 static MonoDebugHandle *
364 _mono_debug_get_image (MonoImage *image)
366 return g_hash_table_lookup (mono_debug_handles, image);
370 mono_debug_close_image (MonoImage *image)
372 MonoDebugHandle *handle;
374 if (!mono_debug_initialized)
377 mono_debugger_lock ();
379 handle = _mono_debug_get_image (image);
381 mono_debugger_unlock ();
385 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
388 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
389 g_hash_table_remove (mono_debug_handles, image);
391 mono_debugger_unlock ();
394 static MonoDebugHandle *
395 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
397 MonoDebugHandle *handle;
399 if (mono_image_is_dynamic (image))
402 mono_debugger_lock ();
404 handle = _mono_debug_get_image (image);
405 if (handle != NULL) {
406 mono_debugger_unlock ();
410 handle = g_new0 (MonoDebugHandle, 1);
411 handle->index = ++next_symbol_file_id;
413 handle->image = image;
414 mono_image_addref (image);
415 handle->image_file = g_strdup (mono_image_get_filename (image));
417 handle->type_table = create_data_table (NULL);
419 handle->symfile = mono_debug_open_mono_symbols (
420 handle, raw_contents, size, _mono_debug_using_mono_debugger);
422 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
424 g_hash_table_insert (mono_debug_handles, image, handle);
426 if (mono_symbol_table->corlib)
427 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
428 (guint64) (gsize) handle, 0);
430 mono_debugger_unlock ();
436 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
438 MonoDebugHandle *handle;
441 mono_debugger_lock ();
442 image = mono_assembly_get_image (assembly);
443 handle = open_symfile_from_bundle (image);
445 mono_debug_open_image (image, NULL, 0);
446 mono_debugger_unlock ();
450 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
455 size = ALIGN_TO (size, sizeof (gpointer));
457 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
458 chunk_size = DATA_TABLE_CHUNK_SIZE;
460 chunk_size = size + 16;
462 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
464 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
465 MonoDebugDataChunk *new_chunk;
467 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
468 new_chunk->total_size = chunk_size;
470 table->current_chunk->next = new_chunk;
471 table->current_chunk = new_chunk;
474 data = &table->current_chunk->data [table->current_chunk->allocated_size];
475 table->current_chunk->allocated_size += size + 8;
477 * ((guint32 *) data) = size;
479 * ((guint32 *) data) = type;
485 write_data_item (MonoDebugDataTable *table, const guint8 *data)
487 MonoDebugDataChunk *current_chunk = table->current_chunk;
488 guint32 size = * ((guint32 *) (data - 8));
490 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
491 current_chunk->current_offset = current_chunk->allocated_size;
494 struct LookupMethodData
496 MonoDebugMethodInfo *minfo;
501 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
503 MonoDebugHandle *handle = (MonoDebugHandle *) value;
504 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
510 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
513 static MonoDebugMethodInfo *
514 _mono_debug_lookup_method (MonoMethod *method)
516 struct LookupMethodData data;
519 data.method = method;
521 if (!mono_debug_handles)
524 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
529 * mono_debug_lookup_method:
531 * Lookup symbol file information for the method @method. The returned
532 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
533 * mono_debug_symfile_lookup_location().
535 MonoDebugMethodInfo *
536 mono_debug_lookup_method (MonoMethod *method)
538 MonoDebugMethodInfo *minfo;
540 mono_debugger_lock ();
541 minfo = _mono_debug_lookup_method (method);
542 mono_debugger_unlock ();
547 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
550 guint8 byte = value & 0x7f;
561 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
566 guint8 byte = value & 0x7f;
569 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
580 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
582 write_leb128 (var->index, ptr, &ptr);
583 write_sleb128 (var->offset, ptr, &ptr);
584 write_leb128 (var->size, ptr, &ptr);
585 write_leb128 (var->begin_scope, ptr, &ptr);
586 write_leb128 (var->end_scope, ptr, &ptr);
587 WRITE_UNALIGNED (gpointer, ptr, var->type);
588 ptr += sizeof (gpointer);
592 MonoDebugMethodAddress *
593 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
595 MonoMethod *declaring;
596 MonoDebugDataTable *table;
597 MonoDebugMethodHeader *header;
598 MonoDebugMethodAddress *address;
599 MonoDebugMethodInfo *minfo;
600 MonoDebugHandle *handle;
601 guint8 buffer [BUFSIZ];
602 guint8 *ptr, *oldptr;
603 guint32 i, size, total_size, max_size;
604 gboolean is_wrapper = FALSE;
606 mono_debugger_lock ();
608 table = lookup_data_table (domain);
610 handle = _mono_debug_get_image (method->klass->image);
611 minfo = _mono_debug_lookup_method (method);
613 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
614 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
615 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
616 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
617 (method->wrapper_type != MONO_WRAPPER_NONE)) {
621 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
622 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
624 if (max_size > BUFSIZ)
625 ptr = oldptr = g_malloc (max_size);
627 ptr = oldptr = buffer;
629 write_leb128 (jit->prologue_end, ptr, &ptr);
630 write_leb128 (jit->epilogue_begin, ptr, &ptr);
632 write_leb128 (jit->num_line_numbers, ptr, &ptr);
633 for (i = 0; i < jit->num_line_numbers; i++) {
634 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
636 write_sleb128 (lne->il_offset, ptr, &ptr);
637 write_sleb128 (lne->native_offset, ptr, &ptr);
640 *ptr++ = jit->this_var ? 1 : 0;
642 write_variable (jit->this_var, ptr, &ptr);
644 write_leb128 (jit->num_params, ptr, &ptr);
645 for (i = 0; i < jit->num_params; i++)
646 write_variable (&jit->params [i], ptr, &ptr);
648 write_leb128 (jit->num_locals, ptr, &ptr);
649 for (i = 0; i < jit->num_locals; i++)
650 write_variable (&jit->locals [i], ptr, &ptr);
653 g_assert (size < max_size);
654 total_size = size + sizeof (MonoDebugMethodAddress);
656 if (method->dynamic) {
657 address = g_malloc0 (total_size);
659 address = (MonoDebugMethodAddress *) allocate_data_item (
660 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
663 address->header.size = total_size;
664 address->header.symfile_id = handle ? handle->index : 0;
665 address->header.domain_id = mono_domain_get_id (domain);
666 address->header.method_id = is_wrapper ? 0 : minfo->index;
667 address->header.method = method;
669 address->code_start = jit->code_start;
670 address->code_size = jit->code_size;
672 memcpy (&address->data, oldptr, size);
673 if (max_size > BUFSIZ)
676 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
677 header = g_hash_table_lookup (table->method_hash, declaring);
680 header = &address->header;
681 g_hash_table_insert (table->method_hash, declaring, header);
684 MonoDebugWrapperData *wrapper;
686 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
688 wrapper->wrapper_type = method->wrapper_type;
689 wrapper->method_name = mono_method_full_name (declaring, TRUE);
690 wrapper->obsolete_cil_code = "";
693 address->header.wrapper_data = header->wrapper_data;
694 header->address_list = g_slist_prepend (header->address_list, address);
697 g_hash_table_insert (table->method_address_hash, method, address);
699 if (!method->dynamic)
700 write_data_item (table, (guint8 *) address);
702 mono_debugger_unlock ();
707 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
709 MonoMethod *declaring;
710 MonoDebugDataTable *table;
711 MonoDebugMethodHeader *header;
712 MonoDebugMethodAddress *address;
714 if (!mono_debug_initialized)
717 g_assert (method->dynamic);
719 mono_debugger_lock ();
721 table = lookup_data_table (domain);
723 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
724 g_hash_table_remove (table->method_hash, declaring);
726 address = g_hash_table_lookup (table->method_address_hash, method);
728 header = &address->header;
730 if (header->wrapper_data) {
731 g_free ((char*)header->wrapper_data->method_name);
732 g_free (header->wrapper_data);
737 g_hash_table_remove (table->method_address_hash, method);
739 mono_debugger_unlock ();
743 mono_debug_add_delegate_trampoline (gpointer code, int size)
745 MonoDebugDelegateTrampolineEntry *entry;
747 if (!mono_debug_initialized)
750 mono_debugger_lock ();
752 entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
753 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
754 sizeof (MonoDebugDelegateTrampolineEntry));
758 write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
760 mono_debugger_unlock ();
763 static inline guint32
764 read_leb128 (guint8 *ptr, guint8 **rptr)
766 guint32 result = 0, shift = 0;
769 guint8 byte = *ptr++;
771 result |= (byte & 0x7f) << shift;
772 if ((byte & 0x80) == 0)
782 read_sleb128 (guint8 *ptr, guint8 **rptr)
788 guint8 byte = *ptr++;
790 result |= (byte & 0x7f) << shift;
796 if ((shift < 32) && (byte & 0x40))
797 result |= - (1 << shift);
806 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
808 var->index = read_leb128 (ptr, &ptr);
809 var->offset = read_sleb128 (ptr, &ptr);
810 var->size = read_leb128 (ptr, &ptr);
811 var->begin_scope = read_leb128 (ptr, &ptr);
812 var->end_scope = read_leb128 (ptr, &ptr);
813 READ_UNALIGNED (gpointer, ptr, var->type);
814 ptr += sizeof (gpointer);
819 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
823 g_free (jit->line_numbers);
824 g_free (jit->this_var);
825 g_free (jit->params);
826 g_free (jit->locals);
830 static MonoDebugMethodJitInfo *
831 mono_debug_read_method (MonoDebugMethodAddress *address)
833 MonoDebugMethodJitInfo *jit;
837 jit = g_new0 (MonoDebugMethodJitInfo, 1);
838 jit->code_start = address->code_start;
839 jit->code_size = address->code_size;
840 jit->wrapper_addr = address->wrapper_addr;
842 ptr = (guint8 *) &address->data;
844 jit->prologue_end = read_leb128 (ptr, &ptr);
845 jit->epilogue_begin = read_leb128 (ptr, &ptr);
847 jit->num_line_numbers = read_leb128 (ptr, &ptr);
848 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
849 for (i = 0; i < jit->num_line_numbers; i++) {
850 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
852 lne->il_offset = read_sleb128 (ptr, &ptr);
853 lne->native_offset = read_sleb128 (ptr, &ptr);
857 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
858 read_variable (jit->this_var, ptr, &ptr);
861 jit->num_params = read_leb128 (ptr, &ptr);
862 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
863 for (i = 0; i < jit->num_params; i++)
864 read_variable (&jit->params [i], ptr, &ptr);
866 jit->num_locals = read_leb128 (ptr, &ptr);
867 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
868 for (i = 0; i < jit->num_locals; i++)
869 read_variable (&jit->locals [i], ptr, &ptr);
875 mono_debug_add_type (MonoClass *klass)
877 MonoDebugHandle *handle;
878 MonoDebugClassEntry *entry;
879 guint8 buffer [BUFSIZ];
880 guint8 *ptr, *oldptr;
881 guint32 size, total_size, max_size;
884 if (klass->generic_class || klass->rank ||
885 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
888 mono_debugger_lock ();
890 handle = _mono_debug_get_image (klass->image);
892 mono_debugger_unlock ();
896 max_size = 12 + sizeof (gpointer);
897 if (max_size > BUFSIZ)
898 ptr = oldptr = g_malloc (max_size);
900 ptr = oldptr = buffer;
902 if (klass->valuetype)
903 base_offset = - (int)(sizeof (MonoObject));
905 write_leb128 (klass->type_token, ptr, &ptr);
906 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
907 WRITE_UNALIGNED (gpointer, ptr, klass);
908 ptr += sizeof (gpointer);
911 g_assert (size < max_size);
912 total_size = size + sizeof (MonoDebugClassEntry);
914 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
916 entry = (MonoDebugClassEntry *) allocate_data_item (
917 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
919 entry->size = total_size;
921 memcpy (&entry->data, oldptr, size);
923 write_data_item (handle->type_table, (guint8 *) entry);
925 if (max_size > BUFSIZ)
928 mono_debugger_unlock ();
931 static MonoDebugMethodJitInfo *
932 find_method (MonoMethod *method, MonoDomain *domain)
934 MonoDebugDataTable *table;
935 MonoDebugMethodAddress *address;
937 table = lookup_data_table (domain);
938 address = g_hash_table_lookup (table->method_address_hash, method);
943 return mono_debug_read_method (address);
946 MonoDebugMethodJitInfo *
947 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
949 MonoDebugMethodJitInfo *res;
951 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
954 mono_debugger_lock ();
955 res = find_method (method, domain);
956 mono_debugger_unlock ();
960 struct LookupMethodAddressData
963 MonoDebugMethodHeader *result;
967 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
969 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
970 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
971 MonoDebugMethodHeader *header;
973 header = g_hash_table_lookup (table->method_hash, data->method);
975 data->result = header;
978 MonoDebugMethodAddressList *
979 mono_debug_lookup_method_addresses (MonoMethod *method)
981 MonoDebugMethodAddressList *info;
982 MonoDebugMethodHeader *header = NULL;
983 struct LookupMethodAddressData data;
984 MonoMethod *declaring;
989 g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
991 mono_debugger_lock ();
993 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
995 data.method = declaring;
998 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
999 header = data.result;
1002 mono_debugger_unlock ();
1006 count = g_slist_length (header->address_list) + 1;
1007 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
1009 info = g_malloc0 (size);
1011 info->count = count;
1015 WRITE_UNALIGNED (gpointer, ptr, header);
1016 ptr += sizeof (gpointer);
1018 for (list = header->address_list; list; list = list->next) {
1019 WRITE_UNALIGNED (gpointer, ptr, list->data);
1020 ptr += sizeof (gpointer);
1023 mono_debugger_unlock ();
1028 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1030 MonoDebugMethodJitInfo *jit;
1033 jit = find_method (method, domain);
1034 if (!jit || !jit->line_numbers)
1035 goto cleanup_and_fail;
1037 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1038 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1040 if (lne.native_offset <= native_offset) {
1041 mono_debug_free_method_jit_info (jit);
1042 return lne.il_offset;
1047 mono_debug_free_method_jit_info (jit);
1052 * mono_debug_il_offset_from_address:
1054 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
1055 * code of METHOD in DOMAIN.
1058 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1062 mono_debugger_lock ();
1064 res = il_offset_from_address (method, domain, native_offset);
1066 mono_debugger_unlock ();
1072 * mono_debug_lookup_source_location:
1073 * @address: Native offset within the @method's machine code.
1075 * Lookup the source code corresponding to the machine instruction located at
1076 * native offset @address within @method.
1078 * The returned `MonoDebugSourceLocation' contains both file / line number
1079 * information and the corresponding IL offset. It must be freed by
1080 * mono_debug_free_source_location().
1082 MonoDebugSourceLocation *
1083 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1085 MonoDebugMethodInfo *minfo;
1086 MonoDebugSourceLocation *location;
1089 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1092 mono_debugger_lock ();
1093 minfo = _mono_debug_lookup_method (method);
1094 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1095 mono_debugger_unlock ();
1099 offset = il_offset_from_address (method, domain, address);
1101 mono_debugger_unlock ();
1105 location = mono_debug_symfile_lookup_location (minfo, offset);
1106 mono_debugger_unlock ();
1111 * mono_debug_lookup_locals:
1113 * Return information about the local variables of MINFO.
1114 * The result should be freed using mono_debug_symfile_free_locals ().
1116 MonoDebugLocalsInfo*
1117 mono_debug_lookup_locals (MonoMethod *method)
1119 MonoDebugMethodInfo *minfo;
1120 MonoDebugLocalsInfo *res;
1122 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1125 mono_debugger_lock ();
1126 minfo = _mono_debug_lookup_method (method);
1127 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1128 mono_debugger_unlock ();
1132 res = mono_debug_symfile_lookup_locals (minfo);
1133 mono_debugger_unlock ();
1139 * mono_debug_free_source_location:
1140 * @location: A `MonoDebugSourceLocation'.
1142 * Frees the @location.
1145 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1148 g_free (location->source_file);
1154 * mono_debug_print_stack_frame:
1155 * @native_offset: Native offset within the @method's machine code.
1157 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1158 * used if you only want to use the location to print a stack frame.
1161 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1163 MonoDebugSourceLocation *location;
1164 gchar *fname, *ptr, *res;
1167 fname = mono_method_full_name (method, TRUE);
1168 for (ptr = fname; *ptr; ptr++) {
1169 if (*ptr == ':') *ptr = '.';
1172 location = mono_debug_lookup_source_location (method, native_offset, domain);
1175 if (mono_debug_initialized) {
1176 mono_debugger_lock ();
1177 offset = il_offset_from_address (method, domain, native_offset);
1178 mono_debugger_unlock ();
1184 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1186 res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1191 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1192 location->source_file, location->row);
1195 mono_debug_free_source_location (location);
1200 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1202 MonoDebugList *element, **ptr;
1204 element = g_new0 (MonoDebugList, 1);
1205 element->data = data;
1207 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1214 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1216 MonoDebugList **ptr;
1217 MonoDebugList *next;
1219 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1220 if ((*ptr)->data != data)
1223 next = (*ptr)->next;
1230 static gboolean is_attached = FALSE;
1233 mono_set_is_debugger_attached (gboolean attached)
1235 is_attached = attached;
1239 mono_is_debugger_attached (void)
1248 typedef struct _BundledSymfile BundledSymfile;
1250 struct _BundledSymfile {
1251 BundledSymfile *next;
1253 const mono_byte *raw_contents;
1257 static BundledSymfile *bundled_symfiles = NULL;
1260 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1262 BundledSymfile *bsymfile;
1264 bsymfile = g_new0 (BundledSymfile, 1);
1265 bsymfile->aname = assembly_name;
1266 bsymfile->raw_contents = raw_contents;
1267 bsymfile->size = size;
1268 bsymfile->next = bundled_symfiles;
1269 bundled_symfiles = bsymfile;
1272 static MonoDebugHandle *
1273 open_symfile_from_bundle (MonoImage *image)
1275 BundledSymfile *bsymfile;
1277 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1278 if (strcmp (bsymfile->aname, image->module_name))
1281 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);