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 static MonoSymbolTable *mono_symbol_table = NULL;
110 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
111 static gint32 mono_debug_debugger_version = 5;
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);
132 static MonoDebugDataTable *
133 create_data_table (MonoDomain *domain)
135 MonoDebugDataTable *table;
136 MonoDebugDataChunk *chunk;
138 table = g_new0 (MonoDebugDataTable, 1);
139 table->domain = domain ? mono_domain_get_id (domain) : -1;
141 table->method_address_hash = g_hash_table_new (NULL, NULL);
142 table->method_hash = g_hash_table_new (NULL, NULL);
144 chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
145 chunk->total_size = DATA_TABLE_CHUNK_SIZE;
147 table->first_chunk = table->current_chunk = chunk;
150 mono_debug_list_add (&mono_symbol_table->data_tables, table);
151 g_hash_table_insert (data_table_hash, domain, table);
158 free_header_data (gpointer key, gpointer value, gpointer user_data)
160 MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
162 if (header->wrapper_data) {
163 g_free ((gpointer)header->wrapper_data->method_name);
164 g_free (header->wrapper_data);
166 g_slist_free (header->address_list);
170 free_data_table (MonoDebugDataTable *table)
172 MonoDebugDataChunk *chunk, *next_chunk;
174 g_hash_table_foreach (table->method_hash, free_header_data, NULL);
175 g_hash_table_destroy (table->method_hash);
176 g_hash_table_destroy (table->method_address_hash);
178 table->method_hash = NULL;
179 table->method_address_hash = NULL;
181 chunk = table->first_chunk;
183 next_chunk = chunk->next;
188 table->first_chunk = table->current_chunk = NULL;
189 mono_debug_list_remove (&mono_symbol_table->data_tables, table);
193 static MonoDebugDataTable *
194 lookup_data_table (MonoDomain *domain)
196 MonoDebugDataTable *table;
198 table = g_hash_table_lookup (data_table_hash, domain);
200 g_error ("lookup_data_table () failed for %p\n", domain);
207 free_debug_handle (MonoDebugHandle *handle)
210 mono_debug_close_mono_symbol_file (handle->symfile);
211 /* decrease the refcount added with mono_image_addref () */
212 free_data_table (handle->type_table);
213 mono_image_close (handle->image);
214 g_free (handle->image_file);
219 * Initialize debugging support.
221 * This method must be called after loading corlib,
222 * but before opening the application's main assembly because we need to set some
226 mono_debug_init (MonoDebugFormat format)
228 g_assert (!mono_debug_initialized);
229 if (format == MONO_DEBUG_FORMAT_DEBUGGER)
230 g_error ("The mdb debugger is no longer supported.");
233 mono_debug_initialized = TRUE;
234 mono_debug_format = format;
237 * This must be called before mono_debugger_initialize(), because the
238 * latter registers GC roots.
240 mono_gc_base_init ();
242 mono_debugger_initialize ();
244 mono_debugger_lock ();
246 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
247 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
248 mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
249 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
251 mono_debug_handles = g_hash_table_new_full
252 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
254 data_table_hash = g_hash_table_new_full (
255 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
257 /* FIXME this is a disgusting hack. Kill it */
258 mono_debugger_class_init_func = mono_debug_add_type;
259 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
261 mono_symbol_table->global_data_table = create_data_table (NULL);
263 mono_debugger_unlock ();
267 * INTERNAL USE ONLY !
268 * FIXME this can have a decent name and exist in an internal header
271 _mono_debug_init_corlib (MonoDomain *domain)
273 if (!mono_debug_initialized)
276 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 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);
289 mono_debug_cleanup (void)
291 if (mono_debug_handles)
292 g_hash_table_destroy (mono_debug_handles);
293 mono_debug_handles = NULL;
295 if (data_table_hash) {
296 g_hash_table_destroy (data_table_hash);
297 data_table_hash = NULL;
300 if (mono_symbol_table) {
301 if (mono_symbol_table->global_data_table)
302 free_data_table (mono_symbol_table->global_data_table);
304 g_free (mono_symbol_table);
305 mono_symbol_table = NULL;
310 mono_debug_domain_create (MonoDomain *domain)
312 MonoDebugDataTable *table;
314 if (!mono_debug_initialized)
317 mono_debugger_lock ();
319 table = create_data_table (domain);
321 mono_debugger_unlock ();
325 mono_debug_domain_unload (MonoDomain *domain)
327 MonoDebugDataTable *table;
329 if (!mono_debug_initialized)
332 mono_debugger_lock ();
334 table = g_hash_table_lookup (data_table_hash, domain);
336 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
337 domain, mono_domain_get_id (domain));
338 mono_debugger_unlock ();
342 g_hash_table_remove (data_table_hash, domain);
344 mono_debugger_unlock ();
348 * LOCKING: Assumes the debug lock is held.
350 static MonoDebugHandle *
351 _mono_debug_get_image (MonoImage *image)
353 return g_hash_table_lookup (mono_debug_handles, image);
357 mono_debug_close_image (MonoImage *image)
359 MonoDebugHandle *handle;
361 if (!mono_debug_initialized)
364 mono_debugger_lock ();
366 handle = _mono_debug_get_image (image);
368 mono_debugger_unlock ();
372 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
373 g_hash_table_remove (mono_debug_handles, image);
375 mono_debugger_unlock ();
378 static MonoDebugHandle *
379 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
381 MonoDebugHandle *handle;
383 if (mono_image_is_dynamic (image))
386 mono_debugger_lock ();
388 handle = _mono_debug_get_image (image);
389 if (handle != NULL) {
390 mono_debugger_unlock ();
394 handle = g_new0 (MonoDebugHandle, 1);
395 handle->index = ++next_symbol_file_id;
397 handle->image = image;
398 mono_image_addref (image);
399 handle->image_file = g_strdup (mono_image_get_filename (image));
401 handle->type_table = create_data_table (NULL);
403 handle->symfile = mono_debug_open_mono_symbols (
404 handle, raw_contents, size, FALSE);
406 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
408 g_hash_table_insert (mono_debug_handles, image, handle);
410 mono_debugger_unlock ();
416 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
418 MonoDebugHandle *handle;
421 mono_debugger_lock ();
422 image = mono_assembly_get_image (assembly);
423 handle = open_symfile_from_bundle (image);
425 mono_debug_open_image (image, NULL, 0);
426 mono_debugger_unlock ();
430 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
435 size = ALIGN_TO (size, sizeof (gpointer));
437 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
438 chunk_size = DATA_TABLE_CHUNK_SIZE;
440 chunk_size = size + 16;
442 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
444 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
445 MonoDebugDataChunk *new_chunk;
447 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
448 new_chunk->total_size = chunk_size;
450 table->current_chunk->next = new_chunk;
451 table->current_chunk = new_chunk;
454 data = &table->current_chunk->data [table->current_chunk->allocated_size];
455 table->current_chunk->allocated_size += size + 8;
457 * ((guint32 *) data) = size;
459 * ((guint32 *) data) = type;
465 write_data_item (MonoDebugDataTable *table, const guint8 *data)
467 MonoDebugDataChunk *current_chunk = table->current_chunk;
468 guint32 size = * ((guint32 *) (data - 8));
470 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
471 current_chunk->current_offset = current_chunk->allocated_size;
474 struct LookupMethodData
476 MonoDebugMethodInfo *minfo;
481 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
483 MonoDebugHandle *handle = (MonoDebugHandle *) value;
484 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
490 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
493 static MonoDebugMethodInfo *
494 _mono_debug_lookup_method (MonoMethod *method)
496 struct LookupMethodData data;
499 data.method = method;
501 if (!mono_debug_handles)
504 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
509 * mono_debug_lookup_method:
511 * Lookup symbol file information for the method @method. The returned
512 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
513 * mono_debug_symfile_lookup_location().
515 MonoDebugMethodInfo *
516 mono_debug_lookup_method (MonoMethod *method)
518 MonoDebugMethodInfo *minfo;
520 mono_debugger_lock ();
521 minfo = _mono_debug_lookup_method (method);
522 mono_debugger_unlock ();
527 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
530 guint8 byte = value & 0x7f;
541 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
546 guint8 byte = value & 0x7f;
549 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
560 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
562 write_leb128 (var->index, ptr, &ptr);
563 write_sleb128 (var->offset, ptr, &ptr);
564 write_leb128 (var->size, ptr, &ptr);
565 write_leb128 (var->begin_scope, ptr, &ptr);
566 write_leb128 (var->end_scope, ptr, &ptr);
567 WRITE_UNALIGNED (gpointer, ptr, var->type);
568 ptr += sizeof (gpointer);
572 MonoDebugMethodAddress *
573 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
575 MonoMethod *declaring;
576 MonoDebugDataTable *table;
577 MonoDebugMethodHeader *header;
578 MonoDebugMethodAddress *address;
579 MonoDebugMethodInfo *minfo;
580 MonoDebugHandle *handle;
581 guint8 buffer [BUFSIZ];
582 guint8 *ptr, *oldptr;
583 guint32 i, size, total_size, max_size;
584 gboolean is_wrapper = FALSE;
586 mono_debugger_lock ();
588 table = lookup_data_table (domain);
590 handle = _mono_debug_get_image (method->klass->image);
591 minfo = _mono_debug_lookup_method (method);
593 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
594 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
595 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
596 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
597 (method->wrapper_type != MONO_WRAPPER_NONE)) {
601 max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
602 (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
604 if (max_size > BUFSIZ)
605 ptr = oldptr = g_malloc (max_size);
607 ptr = oldptr = buffer;
609 write_leb128 (jit->prologue_end, ptr, &ptr);
610 write_leb128 (jit->epilogue_begin, ptr, &ptr);
612 write_leb128 (jit->num_line_numbers, ptr, &ptr);
613 for (i = 0; i < jit->num_line_numbers; i++) {
614 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
616 write_sleb128 (lne->il_offset, ptr, &ptr);
617 write_sleb128 (lne->native_offset, ptr, &ptr);
620 *ptr++ = jit->this_var ? 1 : 0;
622 write_variable (jit->this_var, ptr, &ptr);
624 write_leb128 (jit->num_params, ptr, &ptr);
625 for (i = 0; i < jit->num_params; i++)
626 write_variable (&jit->params [i], ptr, &ptr);
628 write_leb128 (jit->num_locals, ptr, &ptr);
629 for (i = 0; i < jit->num_locals; i++)
630 write_variable (&jit->locals [i], ptr, &ptr);
632 *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
633 if (jit->gsharedvt_info_var) {
634 write_variable (jit->gsharedvt_info_var, ptr, &ptr);
635 write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
639 g_assert (size < max_size);
640 total_size = size + sizeof (MonoDebugMethodAddress);
642 if (method_is_dynamic (method)) {
643 address = g_malloc0 (total_size);
645 address = (MonoDebugMethodAddress *) allocate_data_item (
646 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
649 address->header.size = total_size;
650 address->header.symfile_id = handle ? handle->index : 0;
651 address->header.domain_id = mono_domain_get_id (domain);
652 address->header.method_id = is_wrapper ? 0 : minfo->index;
653 address->header.method = method;
655 address->code_start = jit->code_start;
656 address->code_size = jit->code_size;
658 memcpy (&address->data, oldptr, size);
659 if (max_size > BUFSIZ)
662 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
663 header = g_hash_table_lookup (table->method_hash, declaring);
666 header = &address->header;
667 g_hash_table_insert (table->method_hash, declaring, header);
670 MonoDebugWrapperData *wrapper;
672 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
674 wrapper->wrapper_type = method->wrapper_type;
675 wrapper->method_name = mono_method_full_name (declaring, TRUE);
676 wrapper->obsolete_cil_code = "";
679 address->header.wrapper_data = header->wrapper_data;
680 header->address_list = g_slist_prepend (header->address_list, address);
683 g_hash_table_insert (table->method_address_hash, method, address);
685 if (!method_is_dynamic (method))
686 write_data_item (table, (guint8 *) address);
688 mono_debugger_unlock ();
693 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
695 MonoMethod *declaring;
696 MonoDebugDataTable *table;
697 MonoDebugMethodHeader *header;
698 MonoDebugMethodAddress *address;
700 if (!mono_debug_initialized)
703 g_assert (method_is_dynamic (method));
705 mono_debugger_lock ();
707 table = lookup_data_table (domain);
709 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
710 g_hash_table_remove (table->method_hash, declaring);
712 address = g_hash_table_lookup (table->method_address_hash, method);
714 header = &address->header;
716 if (header->wrapper_data) {
717 g_free ((char*)header->wrapper_data->method_name);
718 g_free (header->wrapper_data);
723 g_hash_table_remove (table->method_address_hash, method);
725 mono_debugger_unlock ();
729 mono_debug_add_delegate_trampoline (gpointer code, int size)
731 MonoDebugDelegateTrampolineEntry *entry;
733 if (!mono_debug_initialized)
736 mono_debugger_lock ();
738 entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
739 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
740 sizeof (MonoDebugDelegateTrampolineEntry));
744 write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
746 mono_debugger_unlock ();
749 static inline guint32
750 read_leb128 (guint8 *ptr, guint8 **rptr)
752 guint32 result = 0, shift = 0;
755 guint8 byte = *ptr++;
757 result |= (byte & 0x7f) << shift;
758 if ((byte & 0x80) == 0)
768 read_sleb128 (guint8 *ptr, guint8 **rptr)
774 guint8 byte = *ptr++;
776 result |= (byte & 0x7f) << shift;
782 if ((shift < 32) && (byte & 0x40))
783 result |= - (1 << shift);
792 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
794 var->index = read_leb128 (ptr, &ptr);
795 var->offset = read_sleb128 (ptr, &ptr);
796 var->size = read_leb128 (ptr, &ptr);
797 var->begin_scope = read_leb128 (ptr, &ptr);
798 var->end_scope = read_leb128 (ptr, &ptr);
799 READ_UNALIGNED (gpointer, ptr, var->type);
800 ptr += sizeof (gpointer);
805 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
809 g_free (jit->line_numbers);
810 g_free (jit->this_var);
811 g_free (jit->params);
812 g_free (jit->locals);
813 g_free (jit->gsharedvt_info_var);
814 g_free (jit->gsharedvt_locals_var);
818 static MonoDebugMethodJitInfo *
819 mono_debug_read_method (MonoDebugMethodAddress *address)
821 MonoDebugMethodJitInfo *jit;
825 jit = g_new0 (MonoDebugMethodJitInfo, 1);
826 jit->code_start = address->code_start;
827 jit->code_size = address->code_size;
828 jit->wrapper_addr = address->wrapper_addr;
830 ptr = (guint8 *) &address->data;
832 jit->prologue_end = read_leb128 (ptr, &ptr);
833 jit->epilogue_begin = read_leb128 (ptr, &ptr);
835 jit->num_line_numbers = read_leb128 (ptr, &ptr);
836 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
837 for (i = 0; i < jit->num_line_numbers; i++) {
838 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
840 lne->il_offset = read_sleb128 (ptr, &ptr);
841 lne->native_offset = read_sleb128 (ptr, &ptr);
845 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
846 read_variable (jit->this_var, ptr, &ptr);
849 jit->num_params = read_leb128 (ptr, &ptr);
850 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
851 for (i = 0; i < jit->num_params; i++)
852 read_variable (&jit->params [i], ptr, &ptr);
854 jit->num_locals = read_leb128 (ptr, &ptr);
855 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
856 for (i = 0; i < jit->num_locals; i++)
857 read_variable (&jit->locals [i], ptr, &ptr);
860 jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
861 jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
862 read_variable (jit->gsharedvt_info_var, ptr, &ptr);
863 read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
870 mono_debug_add_type (MonoClass *klass)
872 MonoDebugHandle *handle;
873 MonoDebugClassEntry *entry;
874 guint8 buffer [BUFSIZ];
875 guint8 *ptr, *oldptr;
876 guint32 size, total_size, max_size;
879 if (klass->generic_class || klass->rank ||
880 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
883 mono_debugger_lock ();
885 handle = _mono_debug_get_image (klass->image);
887 mono_debugger_unlock ();
891 max_size = 12 + sizeof (gpointer);
892 if (max_size > BUFSIZ)
893 ptr = oldptr = g_malloc (max_size);
895 ptr = oldptr = buffer;
897 if (klass->valuetype)
898 base_offset = - (int)(sizeof (MonoObject));
900 write_leb128 (klass->type_token, ptr, &ptr);
901 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
902 WRITE_UNALIGNED (gpointer, ptr, klass);
903 ptr += sizeof (gpointer);
906 g_assert (size < max_size);
907 total_size = size + sizeof (MonoDebugClassEntry);
909 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
911 entry = (MonoDebugClassEntry *) allocate_data_item (
912 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
914 entry->size = total_size;
916 memcpy (&entry->data, oldptr, size);
918 write_data_item (handle->type_table, (guint8 *) entry);
920 if (max_size > BUFSIZ)
923 mono_debugger_unlock ();
926 static MonoDebugMethodJitInfo *
927 find_method (MonoMethod *method, MonoDomain *domain)
929 MonoDebugDataTable *table;
930 MonoDebugMethodAddress *address;
932 table = lookup_data_table (domain);
933 address = g_hash_table_lookup (table->method_address_hash, method);
938 return mono_debug_read_method (address);
941 MonoDebugMethodJitInfo *
942 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
944 MonoDebugMethodJitInfo *res;
946 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
949 mono_debugger_lock ();
950 res = find_method (method, domain);
951 mono_debugger_unlock ();
955 struct LookupMethodAddressData
958 MonoDebugMethodHeader *result;
962 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
964 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
965 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
966 MonoDebugMethodHeader *header;
968 header = g_hash_table_lookup (table->method_hash, data->method);
970 data->result = header;
973 MonoDebugMethodAddressList *
974 mono_debug_lookup_method_addresses (MonoMethod *method)
976 MonoDebugMethodAddressList *info;
977 MonoDebugMethodHeader *header = NULL;
978 struct LookupMethodAddressData data;
979 MonoMethod *declaring;
984 g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
986 mono_debugger_lock ();
988 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
990 data.method = declaring;
993 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
994 header = data.result;
997 mono_debugger_unlock ();
1001 count = g_slist_length (header->address_list) + 1;
1002 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
1004 info = g_malloc0 (size);
1006 info->count = count;
1010 WRITE_UNALIGNED (gpointer, ptr, header);
1011 ptr += sizeof (gpointer);
1013 for (list = header->address_list; list; list = list->next) {
1014 WRITE_UNALIGNED (gpointer, ptr, list->data);
1015 ptr += sizeof (gpointer);
1018 mono_debugger_unlock ();
1023 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1025 MonoDebugMethodJitInfo *jit;
1028 jit = find_method (method, domain);
1029 if (!jit || !jit->line_numbers)
1030 goto cleanup_and_fail;
1032 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1033 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1035 if (lne.native_offset <= native_offset) {
1036 mono_debug_free_method_jit_info (jit);
1037 return lne.il_offset;
1042 mono_debug_free_method_jit_info (jit);
1047 * mono_debug_il_offset_from_address:
1049 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
1050 * code of METHOD in DOMAIN.
1053 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
1057 mono_debugger_lock ();
1059 res = il_offset_from_address (method, domain, native_offset);
1061 mono_debugger_unlock ();
1067 * mono_debug_lookup_source_location:
1068 * @address: Native offset within the @method's machine code.
1070 * Lookup the source code corresponding to the machine instruction located at
1071 * native offset @address within @method.
1073 * The returned `MonoDebugSourceLocation' contains both file / line number
1074 * information and the corresponding IL offset. It must be freed by
1075 * mono_debug_free_source_location().
1077 MonoDebugSourceLocation *
1078 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1080 MonoDebugMethodInfo *minfo;
1081 MonoDebugSourceLocation *location;
1084 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1087 mono_debugger_lock ();
1088 minfo = _mono_debug_lookup_method (method);
1089 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1090 mono_debugger_unlock ();
1094 offset = il_offset_from_address (method, domain, address);
1096 mono_debugger_unlock ();
1100 location = mono_debug_symfile_lookup_location (minfo, offset);
1101 mono_debugger_unlock ();
1106 * mono_debug_lookup_locals:
1108 * Return information about the local variables of MINFO.
1109 * The result should be freed using mono_debug_symfile_free_locals ().
1111 MonoDebugLocalsInfo*
1112 mono_debug_lookup_locals (MonoMethod *method)
1114 MonoDebugMethodInfo *minfo;
1115 MonoDebugLocalsInfo *res;
1117 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1120 mono_debugger_lock ();
1121 minfo = _mono_debug_lookup_method (method);
1122 if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
1123 mono_debugger_unlock ();
1127 res = mono_debug_symfile_lookup_locals (minfo);
1128 mono_debugger_unlock ();
1134 * mono_debug_free_source_location:
1135 * @location: A `MonoDebugSourceLocation'.
1137 * Frees the @location.
1140 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1143 g_free (location->source_file);
1149 * mono_debug_print_stack_frame:
1150 * @native_offset: Native offset within the @method's machine code.
1152 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1153 * used if you only want to use the location to print a stack frame.
1156 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1158 MonoDebugSourceLocation *location;
1159 gchar *fname, *ptr, *res;
1162 fname = mono_method_full_name (method, TRUE);
1163 for (ptr = fname; *ptr; ptr++) {
1164 if (*ptr == ':') *ptr = '.';
1167 location = mono_debug_lookup_source_location (method, native_offset, domain);
1170 if (mono_debug_initialized) {
1171 mono_debugger_lock ();
1172 offset = il_offset_from_address (method, domain, native_offset);
1173 mono_debugger_unlock ();
1179 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1181 res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1186 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1187 location->source_file, location->row);
1190 mono_debug_free_source_location (location);
1195 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1197 MonoDebugList *element, **ptr;
1199 element = g_new0 (MonoDebugList, 1);
1200 element->data = data;
1202 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1209 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1211 MonoDebugList **ptr;
1212 MonoDebugList *next;
1214 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1215 if ((*ptr)->data != data)
1218 next = (*ptr)->next;
1225 static gboolean is_attached = FALSE;
1228 mono_set_is_debugger_attached (gboolean attached)
1230 is_attached = attached;
1234 mono_is_debugger_attached (void)
1243 typedef struct _BundledSymfile BundledSymfile;
1245 struct _BundledSymfile {
1246 BundledSymfile *next;
1248 const mono_byte *raw_contents;
1252 static BundledSymfile *bundled_symfiles = NULL;
1255 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
1257 BundledSymfile *bsymfile;
1259 bsymfile = g_new0 (BundledSymfile, 1);
1260 bsymfile->aname = assembly_name;
1261 bsymfile->raw_contents = raw_contents;
1262 bsymfile->size = size;
1263 bsymfile->next = bundled_symfiles;
1264 bundled_symfiles = bsymfile;
1267 static MonoDebugHandle *
1268 open_symfile_from_bundle (MonoImage *image)
1270 BundledSymfile *bsymfile;
1272 for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) {
1273 if (strcmp (bsymfile->aname, image->module_name))
1276 return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size);
1283 * mono_debug_enabled:
1285 * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
1288 mono_debug_enabled (void)
1290 return mono_debug_format != MONO_DEBUG_FORMAT_NONE;