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>
22 #define DATA_TABLE_CHUNK_SIZE 16384
24 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
26 #if NO_UNALIGNED_ACCESS
27 #define RETURN_UNALIGNED(type, addr) \
30 memcpy(&val, p + offset, sizeof(val)); \
33 #define WRITE_UNALIGNED(type, addr, val) \
34 memcpy(addr, &val, sizeof(type))
35 #define READ_UNALIGNED(type, addr, val) \
36 memcpy(&val, addr, sizeof(type))
38 #define RETURN_UNALIGNED(type, addr) \
39 return *(type*)(p + offset);
40 #define WRITE_UNALIGNED(type, addr, val) \
41 (*(type *)(addr) = (val))
42 #define READ_UNALIGNED(type, addr, val) \
43 val = (*(type *)(addr))
47 MONO_DEBUG_DATA_ITEM_UNKNOWN = 0,
48 MONO_DEBUG_DATA_ITEM_CLASS,
49 MONO_DEBUG_DATA_ITEM_METHOD,
50 MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
51 } MonoDebugDataItemType;
53 typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
55 struct _MonoDebugDataChunk {
57 guint32 allocated_size;
58 guint32 current_offset;
60 MonoDebugDataChunk *next;
61 guint8 data [MONO_ZERO_LEN_ARRAY];
64 struct _MonoDebugDataTable {
66 gint32 _dummy; /* alignment for next field. */
67 MonoDebugDataChunk *first_chunk;
68 MonoDebugDataChunk *current_chunk;
69 GHashTable *method_hash;
70 GHashTable *method_address_hash;
74 const gchar *method_name;
75 const gchar *cil_code;
77 } MonoDebugWrapperData;
84 MonoDebugWrapperData *wrapper_data;
87 } MonoDebugMethodHeader;
89 struct _MonoDebugMethodAddress {
90 MonoDebugMethodHeader header;
91 const guint8 *code_start;
92 const guint8 *wrapper_addr;
94 guint8 data [MONO_ZERO_LEN_ARRAY];
97 struct _MonoDebugClassEntry {
99 guint8 data [MONO_ZERO_LEN_ARRAY];
105 } MonoDebugDelegateTrampolineEntry;
107 MonoSymbolTable *mono_symbol_table = NULL;
108 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
109 gint32 mono_debug_debugger_version = 5;
110 gint32 _mono_debug_using_mono_debugger = 0;
112 static gboolean mono_debug_initialized = FALSE;
113 GHashTable *mono_debug_handles = NULL;
115 static GHashTable *data_table_hash = NULL;
116 static int next_symbol_file_id = 0;
118 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
120 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
121 static void mono_debug_add_assembly (MonoAssembly *assembly,
123 static void mono_debug_add_type (MonoClass *klass);
125 void _mono_debug_init_corlib (MonoDomain *domain);
127 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
128 extern void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass);
130 static MonoDebugDataTable *
131 create_data_table (MonoDomain *domain)
133 MonoDebugDataTable *table;
134 MonoDebugDataChunk *chunk;
136 table = g_new0 (MonoDebugDataTable, 1);
137 table->domain = domain ? mono_domain_get_id (domain) : -1;
139 table->method_address_hash = g_hash_table_new (NULL, NULL);
140 table->method_hash = g_hash_table_new (NULL, NULL);
142 chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
143 chunk->total_size = DATA_TABLE_CHUNK_SIZE;
145 table->first_chunk = table->current_chunk = chunk;
148 mono_debug_list_add (&mono_symbol_table->data_tables, table);
149 g_hash_table_insert (data_table_hash, domain, table);
156 free_header_data (gpointer key, gpointer value, gpointer user_data)
158 MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
160 if (header->wrapper_data) {
161 g_free ((gpointer)header->wrapper_data->method_name);
162 g_free ((gpointer)header->wrapper_data->cil_code);
163 g_slist_free (header->address_list);
164 g_free (header->wrapper_data);
169 free_data_table (MonoDebugDataTable *table)
171 MonoDebugDataChunk *chunk, *next_chunk;
173 g_hash_table_foreach (table->method_hash, free_header_data, NULL);
174 g_hash_table_destroy (table->method_hash);
175 g_hash_table_destroy (table->method_address_hash);
177 table->method_hash = NULL;
178 table->method_address_hash = NULL;
180 chunk = table->first_chunk;
182 next_chunk = chunk->next;
187 table->first_chunk = table->current_chunk = NULL;
188 mono_debug_list_remove (&mono_symbol_table->data_tables, table);
192 static MonoDebugDataTable *
193 lookup_data_table (MonoDomain *domain)
195 MonoDebugDataTable *table;
197 table = g_hash_table_lookup (data_table_hash, domain);
203 free_debug_handle (MonoDebugHandle *handle)
206 mono_debug_close_mono_symbol_file (handle->symfile);
207 /* decrease the refcount added with mono_image_addref () */
208 free_data_table (handle->type_table);
209 mono_image_close (handle->image);
210 g_free (handle->image_file);
215 * Initialize debugging support.
217 * This method must be called after loading corlib,
218 * but before opening the application's main assembly because we need to set some
222 mono_debug_init (MonoDebugFormat format)
224 g_assert (!mono_debug_initialized);
226 if (_mono_debug_using_mono_debugger)
227 format = MONO_DEBUG_FORMAT_DEBUGGER;
229 mono_debug_initialized = TRUE;
230 mono_debug_format = format;
232 mono_debugger_initialize (_mono_debug_using_mono_debugger);
234 mono_debugger_lock ();
236 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
237 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
238 mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
239 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
241 mono_debug_handles = g_hash_table_new_full
242 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
244 data_table_hash = g_hash_table_new_full (
245 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
247 mono_debugger_class_init_func = mono_debug_add_type;
248 mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
249 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
251 mono_symbol_table->global_data_table = create_data_table (NULL);
253 mono_debugger_unlock ();
257 * INTERNAL USE ONLY !
260 _mono_debug_init_corlib (MonoDomain *domain)
262 if (!mono_debug_initialized)
265 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
266 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
267 (guint64) (gsize) mono_symbol_table->corlib, 0);
271 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
273 mono_debug_open_image (image, raw_contents, size);
278 mono_debug_using_mono_debugger (void)
280 return _mono_debug_using_mono_debugger;
284 mono_debug_cleanup (void)
286 if (mono_debug_handles)
287 g_hash_table_destroy (mono_debug_handles);
288 mono_debug_handles = NULL;
290 if (data_table_hash) {
291 g_hash_table_destroy (data_table_hash);
292 data_table_hash = NULL;
295 g_free (mono_symbol_table);
296 mono_symbol_table = NULL;
300 mono_debug_domain_create (MonoDomain *domain)
302 MonoDebugDataTable *table;
304 if (!mono_debug_initialized)
307 mono_debugger_lock ();
309 table = create_data_table (domain);
311 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
312 mono_domain_get_id (domain));
314 mono_debugger_unlock ();
318 mono_debug_domain_unload (MonoDomain *domain)
320 MonoDebugDataTable *table;
322 if (!mono_debug_initialized)
325 mono_debugger_lock ();
327 table = g_hash_table_lookup (data_table_hash, domain);
329 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
330 domain, mono_domain_get_id (domain));
331 mono_debugger_unlock ();
335 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
336 mono_domain_get_id (domain));
338 g_hash_table_remove (data_table_hash, domain);
340 mono_debugger_unlock ();
344 * LOCKING: Assumes the debug lock is held.
346 static MonoDebugHandle *
347 _mono_debug_get_image (MonoImage *image)
349 return g_hash_table_lookup (mono_debug_handles, image);
353 mono_debug_close_image (MonoImage *image)
355 MonoDebugHandle *handle;
357 if (!mono_debug_initialized)
360 mono_debugger_lock ();
362 handle = _mono_debug_get_image (image);
364 mono_debugger_unlock ();
368 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
371 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
372 g_hash_table_remove (mono_debug_handles, image);
374 mono_debugger_unlock ();
377 static MonoDebugHandle *
378 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
380 MonoDebugHandle *handle;
382 if (mono_image_is_dynamic (image))
385 mono_debugger_lock ();
387 handle = _mono_debug_get_image (image);
388 if (handle != NULL) {
389 mono_debugger_unlock ();
393 handle = g_new0 (MonoDebugHandle, 1);
394 handle->index = ++next_symbol_file_id;
396 handle->image = image;
397 mono_image_addref (image);
398 handle->image_file = g_strdup (mono_image_get_filename (image));
400 handle->type_table = create_data_table (NULL);
402 handle->symfile = mono_debug_open_mono_symbols (
403 handle, raw_contents, size, _mono_debug_using_mono_debugger);
405 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
407 g_hash_table_insert (mono_debug_handles, image, handle);
409 if (mono_symbol_table->corlib)
410 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
411 (guint64) (gsize) handle, 0);
413 mono_debugger_unlock ();
419 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
421 mono_debugger_lock ();
422 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
423 mono_debugger_unlock ();
427 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
432 size = ALIGN_TO (size, sizeof (gpointer));
434 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
435 chunk_size = DATA_TABLE_CHUNK_SIZE;
437 chunk_size = size + 16;
439 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
441 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
442 MonoDebugDataChunk *new_chunk;
444 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
445 new_chunk->total_size = chunk_size;
447 table->current_chunk->next = new_chunk;
448 table->current_chunk = new_chunk;
451 data = &table->current_chunk->data [table->current_chunk->allocated_size];
452 table->current_chunk->allocated_size += size + 8;
454 * ((guint32 *) data) = size;
456 * ((guint32 *) data) = type;
462 write_data_item (MonoDebugDataTable *table, const guint8 *data)
464 MonoDebugDataChunk *current_chunk = table->current_chunk;
465 guint32 size = * ((guint32 *) (data - 8));
467 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
468 current_chunk->current_offset = current_chunk->allocated_size;
471 struct LookupMethodData
473 MonoDebugMethodInfo *minfo;
478 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
480 MonoDebugHandle *handle = (MonoDebugHandle *) value;
481 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
487 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
490 static MonoDebugMethodInfo *
491 _mono_debug_lookup_method (MonoMethod *method)
493 struct LookupMethodData data;
496 data.method = method;
498 if (!mono_debug_handles)
501 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
506 * mono_debug_lookup_method:
508 * Lookup symbol file information for the method @method. The returned
509 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
510 * mono_debug_symfile_lookup_location().
512 MonoDebugMethodInfo *
513 mono_debug_lookup_method (MonoMethod *method)
515 MonoDebugMethodInfo *minfo;
517 mono_debugger_lock ();
518 minfo = _mono_debug_lookup_method (method);
519 mono_debugger_unlock ();
524 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
527 guint8 byte = value & 0x7f;
538 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
543 guint8 byte = value & 0x7f;
546 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
557 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
559 write_leb128 (var->index, ptr, &ptr);
560 write_sleb128 (var->offset, ptr, &ptr);
561 write_leb128 (var->size, ptr, &ptr);
562 write_leb128 (var->begin_scope, ptr, &ptr);
563 write_leb128 (var->end_scope, ptr, &ptr);
564 WRITE_UNALIGNED (gpointer, ptr, var->type);
565 ptr += sizeof (gpointer);
569 MonoDebugMethodAddress *
570 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
572 MonoMethod *declaring;
573 MonoDebugDataTable *table;
574 MonoDebugMethodHeader *header;
575 MonoDebugMethodAddress *address;
576 MonoDebugMethodInfo *minfo;
577 MonoDebugHandle *handle;
578 guint8 buffer [BUFSIZ];
579 guint8 *ptr, *oldptr;
580 guint32 i, size, total_size, max_size;
581 gboolean is_wrapper = FALSE;
583 mono_debugger_lock ();
585 table = lookup_data_table (domain);
587 handle = _mono_debug_get_image (method->klass->image);
588 minfo = _mono_debug_lookup_method (method);
590 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
591 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
592 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
593 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
594 (method->wrapper_type != MONO_WRAPPER_NONE)) {
598 max_size = 24 + 8 * jit->num_line_numbers +
599 (20 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
601 if (max_size > BUFSIZ)
602 ptr = oldptr = g_malloc (max_size);
604 ptr = oldptr = buffer;
606 write_leb128 (jit->prologue_end, ptr, &ptr);
607 write_leb128 (jit->epilogue_begin, ptr, &ptr);
609 write_leb128 (jit->num_line_numbers, ptr, &ptr);
610 for (i = 0; i < jit->num_line_numbers; i++) {
611 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
613 write_sleb128 (lne->il_offset, ptr, &ptr);
614 write_sleb128 (lne->native_offset, ptr, &ptr);
617 *ptr++ = jit->this_var ? 1 : 0;
619 write_variable (jit->this_var, ptr, &ptr);
621 write_leb128 (jit->num_params, ptr, &ptr);
622 for (i = 0; i < jit->num_params; i++)
623 write_variable (&jit->params [i], ptr, &ptr);
625 write_leb128 (jit->num_locals, ptr, &ptr);
626 for (i = 0; i < jit->num_locals; i++)
627 write_variable (&jit->locals [i], ptr, &ptr);
630 g_assert (size < max_size);
631 total_size = size + sizeof (MonoDebugMethodAddress);
633 address = (MonoDebugMethodAddress *) allocate_data_item (
634 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
636 address->header.size = total_size;
637 address->header.symfile_id = handle ? handle->index : 0;
638 address->header.domain_id = mono_domain_get_id (domain);
639 address->header.method_id = is_wrapper ? 0 : minfo->index;
640 address->header.method = method;
642 address->code_start = jit->code_start;
643 address->code_size = jit->code_size;
645 memcpy (&address->data, oldptr, size);
646 if (max_size > BUFSIZ)
649 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
650 header = g_hash_table_lookup (table->method_hash, declaring);
653 header = &address->header;
654 g_hash_table_insert (table->method_hash, declaring, header);
657 const unsigned char* il_code;
658 MonoMethodHeader *mheader;
659 MonoDebugWrapperData *wrapper;
662 mheader = mono_method_get_header (declaring);
663 il_code = mono_method_header_get_code (mheader, &il_codesize, NULL);
665 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
667 wrapper->wrapper_type = method->wrapper_type;
668 wrapper->method_name = mono_method_full_name (declaring, TRUE);
669 wrapper->cil_code = mono_disasm_code (
670 NULL, declaring, il_code, il_code + il_codesize);
673 address->header.wrapper_data = header->wrapper_data;
674 header->address_list = g_slist_prepend (header->address_list, address);
677 g_hash_table_insert (table->method_address_hash, method, address);
679 write_data_item (table, (guint8 *) address);
681 mono_debugger_unlock ();
686 mono_debug_add_delegate_trampoline (gpointer code, int size)
688 MonoDebugDelegateTrampolineEntry *entry;
690 if (!mono_debug_initialized)
693 mono_debugger_lock ();
695 entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
696 mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
697 sizeof (MonoDebugDelegateTrampolineEntry));
701 write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
703 mono_debugger_unlock ();
706 static inline guint32
707 read_leb128 (guint8 *ptr, guint8 **rptr)
709 guint32 result = 0, shift = 0;
712 guint8 byte = *ptr++;
714 result |= (byte & 0x7f) << shift;
715 if ((byte & 0x80) == 0)
725 read_sleb128 (guint8 *ptr, guint8 **rptr)
731 guint8 byte = *ptr++;
733 result |= (byte & 0x7f) << shift;
739 if ((shift < 32) && (byte & 0x40))
740 result |= - (1 << shift);
749 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
751 var->index = read_leb128 (ptr, &ptr);
752 var->offset = read_sleb128 (ptr, &ptr);
753 var->size = read_leb128 (ptr, &ptr);
754 var->begin_scope = read_leb128 (ptr, &ptr);
755 var->end_scope = read_leb128 (ptr, &ptr);
756 READ_UNALIGNED (gpointer, ptr, var->type);
757 ptr += sizeof (gpointer);
762 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
766 g_free (jit->line_numbers);
767 g_free (jit->this_var);
768 g_free (jit->params);
769 g_free (jit->locals);
773 static MonoDebugMethodJitInfo *
774 mono_debug_read_method (MonoDebugMethodAddress *address)
776 MonoDebugMethodJitInfo *jit;
780 jit = g_new0 (MonoDebugMethodJitInfo, 1);
781 jit->code_start = address->code_start;
782 jit->code_size = address->code_size;
783 jit->wrapper_addr = address->wrapper_addr;
785 ptr = (guint8 *) &address->data;
787 jit->prologue_end = read_leb128 (ptr, &ptr);
788 jit->epilogue_begin = read_leb128 (ptr, &ptr);
790 jit->num_line_numbers = read_leb128 (ptr, &ptr);
791 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
792 for (i = 0; i < jit->num_line_numbers; i++) {
793 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
795 lne->il_offset = read_sleb128 (ptr, &ptr);
796 lne->native_offset = read_sleb128 (ptr, &ptr);
800 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
801 read_variable (jit->this_var, ptr, &ptr);
804 jit->num_params = read_leb128 (ptr, &ptr);
805 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
806 for (i = 0; i < jit->num_params; i++)
807 read_variable (&jit->params [i], ptr, &ptr);
809 jit->num_locals = read_leb128 (ptr, &ptr);
810 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
811 for (i = 0; i < jit->num_locals; i++)
812 read_variable (&jit->locals [i], ptr, &ptr);
818 mono_debug_add_type (MonoClass *klass)
820 MonoDebugHandle *handle;
821 MonoDebugClassEntry *entry;
822 guint8 buffer [BUFSIZ];
823 guint8 *ptr, *oldptr;
824 guint32 size, total_size, max_size;
827 if (klass->generic_class || klass->rank ||
828 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
831 mono_debugger_lock ();
833 handle = _mono_debug_get_image (klass->image);
835 mono_debugger_unlock ();
839 max_size = 12 + sizeof (gpointer);
840 if (max_size > BUFSIZ)
841 ptr = oldptr = g_malloc (max_size);
843 ptr = oldptr = buffer;
845 if (klass->valuetype)
846 base_offset = - (int)(sizeof (MonoObject));
848 write_leb128 (klass->type_token, ptr, &ptr);
849 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
850 WRITE_UNALIGNED (gpointer, ptr, klass);
851 ptr += sizeof (gpointer);
854 g_assert (size < max_size);
855 total_size = size + sizeof (MonoDebugClassEntry);
857 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
859 entry = (MonoDebugClassEntry *) allocate_data_item (
860 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
862 entry->size = total_size;
864 memcpy (&entry->data, oldptr, size);
866 write_data_item (handle->type_table, (guint8 *) entry);
868 if (max_size > BUFSIZ)
871 mono_debugger_unlock ();
874 static MonoDebugMethodJitInfo *
875 find_method (MonoMethod *method, MonoDomain *domain)
877 MonoDebugDataTable *table;
878 MonoDebugMethodAddress *address;
880 table = lookup_data_table (domain);
881 address = g_hash_table_lookup (table->method_address_hash, method);
886 return mono_debug_read_method (address);
889 MonoDebugMethodJitInfo *
890 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
892 MonoDebugMethodJitInfo *res;
894 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
897 mono_debugger_lock ();
898 res = find_method (method, domain);
899 mono_debugger_unlock ();
903 struct LookupMethodAddressData
906 MonoDebugMethodHeader *result;
910 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
912 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
913 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
914 MonoDebugMethodHeader *header;
916 header = g_hash_table_lookup (table->method_hash, data->method);
918 data->result = header;
921 MonoDebugMethodAddressList *
922 mono_debug_lookup_method_addresses (MonoMethod *method)
924 MonoDebugMethodAddressList *info;
925 MonoDebugMethodHeader *header = NULL;
926 struct LookupMethodAddressData data;
927 MonoMethod *declaring;
932 g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
934 mono_debugger_lock ();
936 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
938 data.method = declaring;
941 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
942 header = data.result;
945 mono_debugger_unlock ();
949 count = g_slist_length (header->address_list) + 1;
950 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
952 info = g_malloc0 (size);
958 WRITE_UNALIGNED (gpointer, ptr, header);
959 ptr += sizeof (gpointer);
961 for (list = header->address_list; list; list = list->next) {
962 WRITE_UNALIGNED (gpointer, ptr, list->data);
963 ptr += sizeof (gpointer);
966 mono_debugger_unlock ();
971 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
973 MonoDebugMethodJitInfo *jit;
976 jit = find_method (method, domain);
977 if (!jit || !jit->line_numbers)
978 goto cleanup_and_fail;
980 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
981 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
983 if (lne.native_offset <= native_offset) {
984 mono_debug_free_method_jit_info (jit);
985 return lne.il_offset;
990 mono_debug_free_method_jit_info (jit);
995 * mono_debug_lookup_source_location:
996 * @address: Native offset within the @method's machine code.
998 * Lookup the source code corresponding to the machine instruction located at
999 * native offset @address within @method.
1001 * The returned `MonoDebugSourceLocation' contains both file / line number
1002 * information and the corresponding IL offset. It must be freed by
1003 * mono_debug_free_source_location().
1005 MonoDebugSourceLocation *
1006 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1008 MonoDebugMethodInfo *minfo;
1009 MonoDebugSourceLocation *location;
1012 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1015 mono_debugger_lock ();
1016 minfo = _mono_debug_lookup_method (method);
1017 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
1018 mono_debugger_unlock ();
1022 offset = il_offset_from_address (method, domain, address);
1024 mono_debugger_unlock ();
1028 location = mono_debug_symfile_lookup_location (minfo, offset);
1029 mono_debugger_unlock ();
1034 * mono_debug_lookup_locals:
1036 * Return information about the local variables of MINFO.
1037 * NAMES and INDEXES are set to g_malloc-ed arrays containing the local names and
1039 * Returns: the number of elements placed into the arrays, or -1 if there is no
1040 * local variable info.
1043 mono_debug_lookup_locals (MonoMethod *method, char ***names, int **indexes)
1045 MonoDebugMethodInfo *minfo;
1051 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1054 mono_debugger_lock ();
1055 minfo = _mono_debug_lookup_method (method);
1056 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
1057 mono_debugger_unlock ();
1061 res = mono_debug_symfile_lookup_locals (minfo, names, indexes);
1062 mono_debugger_unlock ();
1068 * mono_debug_free_source_location:
1069 * @location: A `MonoDebugSourceLocation'.
1071 * Frees the @location.
1074 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1077 g_free (location->source_file);
1083 * mono_debug_print_stack_frame:
1084 * @native_offset: Native offset within the @method's machine code.
1086 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1087 * used if you only want to use the location to print a stack frame.
1090 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1092 MonoDebugSourceLocation *location;
1093 gchar *fname, *ptr, *res;
1096 fname = mono_method_full_name (method, TRUE);
1097 for (ptr = fname; *ptr; ptr++) {
1098 if (*ptr == ':') *ptr = '.';
1101 location = mono_debug_lookup_source_location (method, native_offset, domain);
1104 if (mono_debug_initialized) {
1105 mono_debugger_lock ();
1106 offset = il_offset_from_address (method, domain, native_offset);
1107 mono_debugger_unlock ();
1113 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1115 res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
1120 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1121 location->source_file, location->row);
1124 mono_debug_free_source_location (location);
1129 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1131 MonoDebugList *element, **ptr;
1133 element = g_new0 (MonoDebugList, 1);
1134 element->data = data;
1136 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1143 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1145 MonoDebugList **ptr;
1146 MonoDebugList *next;
1148 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1149 if ((*ptr)->data != data)
1152 next = (*ptr)->next;