2 #include <mono/metadata/assembly.h>
3 #include <mono/metadata/tabledefs.h>
4 #include <mono/metadata/tokentype.h>
5 #include <mono/metadata/appdomain.h>
6 #include <mono/metadata/class-internals.h>
7 #include <mono/metadata/mono-debug.h>
8 #include <mono/metadata/mono-debug-debugger.h>
9 #include <mono/metadata/mono-endian.h>
12 #define DATA_TABLE_CHUNK_SIZE 16384
14 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
16 #if NO_UNALIGNED_ACCESS
17 #define RETURN_UNALIGNED(type, addr) \
20 memcpy(&val, p + offset, sizeof(val)); \
23 #define WRITE_UNALIGNED(type, addr, val) \
24 memcpy(addr, &val, sizeof(type))
25 #define READ_UNALIGNED(type, addr, val) \
26 memcpy(&val, addr, sizeof(type))
28 #define RETURN_UNALIGNED(type, addr) \
29 return *(type*)(p + offset);
30 #define WRITE_UNALIGNED(type, addr, val) \
31 (*(type *)(addr) = (val))
32 #define READ_UNALIGNED(type, addr, val) \
33 val = (*(type *)(addr))
37 MONO_DEBUG_DATA_ITEM_UNKNOWN = 0,
38 MONO_DEBUG_DATA_ITEM_CLASS,
39 MONO_DEBUG_DATA_ITEM_METHOD
40 } MonoDebugDataItemType;
42 typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
44 struct _MonoDebugDataChunk {
46 guint32 allocated_size;
47 guint32 current_offset;
49 MonoDebugDataChunk *next;
50 guint8 data [MONO_ZERO_LEN_ARRAY];
53 struct _MonoDebugDataTable {
55 gint32 _dummy; /* alignment for next field. */
56 MonoDebugDataChunk *first_chunk;
57 MonoDebugDataChunk *current_chunk;
58 GHashTable *method_hash;
59 GHashTable *method_address_hash;
63 const gchar *method_name;
64 const gchar *cil_code;
66 } MonoDebugWrapperData;
73 MonoDebugWrapperData *wrapper_data;
76 } MonoDebugMethodHeader;
78 struct _MonoDebugMethodAddress {
79 MonoDebugMethodHeader header;
80 const guint8 *code_start;
81 const guint8 *wrapper_addr;
83 guint8 data [MONO_ZERO_LEN_ARRAY];
86 struct _MonoDebugClassEntry {
88 guint8 data [MONO_ZERO_LEN_ARRAY];
91 MonoSymbolTable *mono_symbol_table = NULL;
92 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
93 gint32 mono_debug_debugger_version = 2;
95 static gboolean in_the_mono_debugger = FALSE;
96 static gboolean mono_debug_initialized = FALSE;
97 GHashTable *mono_debug_handles = NULL;
99 static GHashTable *data_table_hash = NULL;
100 static int next_symbol_file_id = 0;
102 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
104 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
105 static void mono_debug_add_assembly (MonoAssembly *assembly,
107 static void mono_debug_start_add_type (MonoClass *klass);
108 static void mono_debug_add_type (MonoClass *klass);
110 void _mono_debug_init_corlib (MonoDomain *domain);
112 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
113 extern void (*mono_debugger_start_class_init_func) (MonoClass *klass);
115 static MonoDebugDataTable *
116 create_data_table (MonoDomain *domain)
118 MonoDebugDataTable *table;
119 MonoDebugDataChunk *chunk;
121 table = g_new0 (MonoDebugDataTable, 1);
122 table->domain = domain ? mono_domain_get_id (domain) : -1;
124 table->method_address_hash = g_hash_table_new (NULL, NULL);
125 table->method_hash = g_hash_table_new (NULL, NULL);
127 chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
128 chunk->total_size = DATA_TABLE_CHUNK_SIZE;
130 table->first_chunk = table->current_chunk = chunk;
133 mono_debug_list_add (&mono_symbol_table->data_tables, table);
134 g_hash_table_insert (data_table_hash, domain, table);
141 free_header_data (gpointer key, gpointer value, gpointer user_data)
143 MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
145 if (header->wrapper_data) {
146 g_free ((gpointer)header->wrapper_data->method_name);
147 g_free ((gpointer)header->wrapper_data->cil_code);
148 g_slist_free (header->address_list);
149 g_free (header->wrapper_data);
154 free_data_table (MonoDebugDataTable *table)
156 MonoDebugDataChunk *chunk, *next_chunk;
158 g_hash_table_foreach (table->method_hash, free_header_data, NULL);
159 g_hash_table_destroy (table->method_hash);
160 g_hash_table_destroy (table->method_address_hash);
162 table->method_hash = NULL;
163 table->method_address_hash = NULL;
165 chunk = table->first_chunk;
167 next_chunk = chunk->next;
172 table->first_chunk = table->current_chunk = NULL;
173 mono_debug_list_remove (&mono_symbol_table->data_tables, table);
177 static MonoDebugDataTable *
178 lookup_data_table (MonoDomain *domain)
180 MonoDebugDataTable *table;
182 table = g_hash_table_lookup (data_table_hash, domain);
188 free_debug_handle (MonoDebugHandle *handle)
191 mono_debug_close_mono_symbol_file (handle->symfile);
192 /* decrease the refcount added with mono_image_addref () */
193 free_data_table (handle->type_table);
194 mono_image_close (handle->image);
195 g_free (handle->image_file);
200 * Initialize debugging support.
202 * This method must be called after loading corlib,
203 * but before opening the application's main assembly because we need to set some
207 mono_debug_init (MonoDebugFormat format)
209 g_assert (!mono_debug_initialized);
211 mono_debug_initialized = TRUE;
212 mono_debug_format = format;
213 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
215 mono_debugger_initialize (in_the_mono_debugger);
217 mono_debugger_lock ();
219 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
220 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
221 mono_symbol_table->version = MONO_DEBUGGER_VERSION;
222 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
224 mono_debug_handles = g_hash_table_new_full
225 (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
227 data_table_hash = g_hash_table_new_full (
228 NULL, NULL, NULL, (GDestroyNotify) free_data_table);
230 mono_debugger_start_class_init_func = mono_debug_start_add_type;
231 mono_debugger_class_init_func = mono_debug_add_type;
232 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
234 mono_debugger_unlock ();
238 * INTERNAL USE ONLY !
241 _mono_debug_init_corlib (MonoDomain *domain)
243 if (!mono_debug_initialized)
246 mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
247 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
248 (guint64) (gsize) mono_symbol_table->corlib, 0);
252 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
254 mono_debug_open_image (image, raw_contents, size);
259 mono_debug_using_mono_debugger (void)
261 return in_the_mono_debugger;
265 mono_debug_cleanup (void)
267 if (mono_debug_handles)
268 g_hash_table_destroy (mono_debug_handles);
269 mono_debug_handles = NULL;
271 if (data_table_hash) {
272 g_hash_table_destroy (data_table_hash);
273 data_table_hash = NULL;
276 g_free (mono_symbol_table);
277 mono_symbol_table = NULL;
281 mono_debug_domain_create (MonoDomain *domain)
283 MonoDebugDataTable *table;
285 if (!mono_debug_initialized)
288 mono_debugger_lock ();
290 table = create_data_table (domain);
292 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
293 mono_domain_get_id (domain));
295 mono_debugger_unlock ();
299 mono_debug_domain_unload (MonoDomain *domain)
301 MonoDebugDataTable *table;
303 if (!mono_debug_initialized)
306 mono_debugger_lock ();
308 table = g_hash_table_lookup (data_table_hash, domain);
310 g_warning (G_STRLOC ": unloading unknown domain %p / %d",
311 domain, mono_domain_get_id (domain));
312 mono_debugger_unlock ();
316 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
317 mono_domain_get_id (domain));
319 g_hash_table_remove (data_table_hash, domain);
321 mono_debugger_unlock ();
324 static MonoDebugHandle *
325 _mono_debug_get_image (MonoImage *image)
327 return g_hash_table_lookup (mono_debug_handles, image);
331 mono_debug_close_image (MonoImage *image)
333 MonoDebugHandle *handle;
335 if (!mono_debug_initialized)
338 handle = _mono_debug_get_image (image);
342 mono_debugger_lock ();
344 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
347 mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
348 g_hash_table_remove (mono_debug_handles, image);
350 mono_debugger_unlock ();
353 static MonoDebugHandle *
354 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
356 MonoDebugHandle *handle;
358 if (mono_image_is_dynamic (image))
361 handle = _mono_debug_get_image (image);
365 mono_debugger_lock ();
367 handle = g_new0 (MonoDebugHandle, 1);
368 handle->index = ++next_symbol_file_id;
370 handle->image = image;
371 mono_image_addref (image);
372 handle->image_file = g_strdup (mono_image_get_filename (image));
374 handle->type_table = create_data_table (NULL);
376 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, in_the_mono_debugger);
378 mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
380 g_hash_table_insert (mono_debug_handles, image, handle);
382 if (mono_symbol_table->corlib)
383 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
384 (guint64) (gsize) handle, 0);
386 mono_debugger_unlock ();
392 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
394 mono_debugger_lock ();
395 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
396 mono_debugger_unlock ();
400 allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
405 size = ALIGN_TO (size, sizeof (gpointer));
407 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
408 chunk_size = DATA_TABLE_CHUNK_SIZE;
410 chunk_size = size + 16;
412 g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
414 if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
415 MonoDebugDataChunk *new_chunk;
417 new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
418 new_chunk->total_size = chunk_size;
420 table->current_chunk->next = new_chunk;
421 table->current_chunk = new_chunk;
424 data = &table->current_chunk->data [table->current_chunk->allocated_size];
425 table->current_chunk->allocated_size += size + 8;
427 * ((guint32 *) data) = size;
429 * ((guint32 *) data) = type;
435 write_data_item (MonoDebugDataTable *table, const guint8 *data)
437 MonoDebugDataChunk *current_chunk = table->current_chunk;
438 guint32 size = * ((guint32 *) (data - 8));
440 g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
441 current_chunk->current_offset = current_chunk->allocated_size;
444 struct LookupMethodData
446 MonoDebugMethodInfo *minfo;
451 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
453 MonoDebugHandle *handle = (MonoDebugHandle *) value;
454 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
460 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
463 static MonoDebugMethodInfo *
464 _mono_debug_lookup_method (MonoMethod *method)
466 struct LookupMethodData data;
469 data.method = method;
471 if (!mono_debug_handles)
474 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
479 * mono_debug_lookup_method:
481 * Lookup symbol file information for the method @method. The returned
482 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
483 * mono_debug_symfile_lookup_location().
485 MonoDebugMethodInfo *
486 mono_debug_lookup_method (MonoMethod *method)
488 MonoDebugMethodInfo *minfo;
490 mono_debugger_lock ();
491 minfo = _mono_debug_lookup_method (method);
492 mono_debugger_unlock ();
497 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
500 guint8 byte = value & 0x7f;
511 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
516 guint8 byte = value & 0x7f;
519 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
530 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
532 write_leb128 (var->index, ptr, &ptr);
533 write_sleb128 (var->offset, ptr, &ptr);
534 write_leb128 (var->size, ptr, &ptr);
535 write_leb128 (var->begin_scope, ptr, &ptr);
536 write_leb128 (var->end_scope, ptr, &ptr);
537 WRITE_UNALIGNED (gpointer, ptr, var->type);
538 ptr += sizeof (gpointer);
542 MonoDebugMethodAddress *
543 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
545 MonoMethod *declaring;
546 MonoDebugDataTable *table;
547 MonoDebugMethodHeader *header;
548 MonoDebugMethodAddress *address;
549 MonoDebugMethodInfo *minfo;
550 MonoDebugHandle *handle;
551 guint8 buffer [BUFSIZ];
552 guint8 *ptr, *oldptr;
553 guint32 i, size, total_size, max_size;
554 gint32 last_il_offset = 0, last_native_offset = 0;
555 gboolean is_wrapper = FALSE;
557 mono_debugger_lock ();
559 table = lookup_data_table (domain);
561 handle = _mono_debug_get_image (method->klass->image);
562 minfo = _mono_debug_lookup_method (method);
564 if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
565 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
566 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
567 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
568 (method->wrapper_type != MONO_WRAPPER_NONE)) {
572 jit->num_lexical_blocks = minfo ? minfo->num_lexical_blocks : 0;
574 max_size = 24 + 8 * jit->num_line_numbers + 16 * jit->num_lexical_blocks +
575 (20 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
577 if (max_size > BUFSIZ)
578 ptr = oldptr = g_malloc (max_size);
580 ptr = oldptr = buffer;
582 write_leb128 (jit->prologue_end, ptr, &ptr);
583 write_leb128 (jit->epilogue_begin, ptr, &ptr);
585 write_leb128 (jit->num_line_numbers, ptr, &ptr);
586 for (i = 0; i < jit->num_line_numbers; i++) {
587 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
589 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
590 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
592 last_il_offset = lne->il_offset;
593 last_native_offset = lne->native_offset;
596 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
597 for (i = 0; i < jit->num_lexical_blocks; i ++) {
598 MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
599 MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
600 jit_lbe->il_start_offset = read32 (&(minfo_lbe->_start_offset));
601 jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
603 jit_lbe->il_end_offset = read32 (&(minfo_lbe->_end_offset));
604 jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
608 last_native_offset = 0;
609 write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
610 for (i = 0; i < jit->num_lexical_blocks; i++) {
611 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
613 write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
614 write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
616 last_il_offset = lbe->il_start_offset;
617 last_native_offset = lbe->native_start_offset;
619 write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
620 write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
622 last_il_offset = lbe->il_end_offset;
623 last_native_offset = lbe->native_end_offset;
626 *ptr++ = jit->this_var ? 1 : 0;
628 write_variable (jit->this_var, ptr, &ptr);
630 write_leb128 (jit->num_params, ptr, &ptr);
631 for (i = 0; i < jit->num_params; i++)
632 write_variable (&jit->params [i], ptr, &ptr);
634 write_leb128 (jit->num_locals, ptr, &ptr);
635 for (i = 0; i < jit->num_locals; i++)
636 write_variable (&jit->locals [i], ptr, &ptr);
639 g_assert (size < max_size);
640 total_size = size + sizeof (MonoDebugMethodAddress);
642 address = (MonoDebugMethodAddress *) allocate_data_item (
643 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
645 address->header.size = total_size;
646 address->header.symfile_id = handle ? handle->index : 0;
647 address->header.domain_id = mono_domain_get_id (domain);
648 address->header.method_id = is_wrapper ? 0 : minfo->index;
649 address->header.method = method;
651 address->code_start = jit->code_start;
652 address->code_size = jit->code_size;
654 memcpy (&address->data, oldptr, size);
655 if (max_size > BUFSIZ)
658 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
659 header = g_hash_table_lookup (table->method_hash, declaring);
662 header = &address->header;
663 g_hash_table_insert (table->method_hash, declaring, header);
666 const unsigned char* il_code;
667 MonoMethodHeader *mheader;
668 MonoDebugWrapperData *wrapper;
671 mheader = mono_method_get_header (declaring);
672 il_code = mono_method_header_get_code (mheader, &il_codesize, NULL);
674 header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
676 wrapper->wrapper_type = method->wrapper_type;
677 wrapper->method_name = mono_method_full_name (declaring, TRUE);
678 wrapper->cil_code = mono_disasm_code (
679 NULL, declaring, il_code, il_code + il_codesize);
682 address->header.wrapper_data = header->wrapper_data;
683 header->address_list = g_slist_prepend (header->address_list, address);
686 g_hash_table_insert (table->method_address_hash, method, address);
688 write_data_item (table, (guint8 *) address);
690 mono_debugger_unlock ();
694 static inline guint32
695 read_leb128 (guint8 *ptr, guint8 **rptr)
697 guint32 result = 0, shift = 0;
700 guint8 byte = *ptr++;
702 result |= (byte & 0x7f) << shift;
703 if ((byte & 0x80) == 0)
713 read_sleb128 (guint8 *ptr, guint8 **rptr)
719 guint8 byte = *ptr++;
721 result |= (byte & 0x7f) << shift;
727 if ((shift < 32) && (byte & 0x40))
728 result |= - (1 << shift);
737 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
739 var->index = read_leb128 (ptr, &ptr);
740 var->offset = read_sleb128 (ptr, &ptr);
741 var->size = read_leb128 (ptr, &ptr);
742 var->begin_scope = read_leb128 (ptr, &ptr);
743 var->end_scope = read_leb128 (ptr, &ptr);
744 READ_UNALIGNED (gpointer, ptr, var->type);
745 ptr += sizeof (gpointer);
749 static MonoDebugMethodJitInfo *
750 mono_debug_read_method (MonoDebugMethodAddress *address)
752 MonoDebugMethodJitInfo *jit;
753 guint32 i, il_offset = 0, native_offset = 0;
756 jit = g_new0 (MonoDebugMethodJitInfo, 1);
757 jit->code_start = address->code_start;
758 jit->code_size = address->code_size;
759 jit->wrapper_addr = address->wrapper_addr;
761 ptr = (guint8 *) &address->data;
763 jit->prologue_end = read_leb128 (ptr, &ptr);
764 jit->epilogue_begin = read_leb128 (ptr, &ptr);
766 jit->num_line_numbers = read_leb128 (ptr, &ptr);
767 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
768 for (i = 0; i < jit->num_line_numbers; i++) {
769 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
771 il_offset += read_sleb128 (ptr, &ptr);
772 native_offset += read_sleb128 (ptr, &ptr);
774 lne->il_offset = il_offset;
775 lne->native_offset = native_offset;
780 jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
781 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
782 for (i = 0; i < jit->num_lexical_blocks; i ++) {
783 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
785 il_offset += read_sleb128 (ptr, &ptr);
786 native_offset += read_sleb128 (ptr, &ptr);
788 lbe->il_start_offset = il_offset;
789 lbe->native_start_offset = native_offset;
791 il_offset += read_sleb128 (ptr, &ptr);
792 native_offset += read_sleb128 (ptr, &ptr);
794 lbe->il_end_offset = il_offset;
795 lbe->native_end_offset = native_offset;
799 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
800 read_variable (jit->this_var, ptr, &ptr);
803 jit->num_params = read_leb128 (ptr, &ptr);
804 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
805 for (i = 0; i < jit->num_params; i++)
806 read_variable (&jit->params [i], ptr, &ptr);
808 jit->num_locals = read_leb128 (ptr, &ptr);
809 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
810 for (i = 0; i < jit->num_locals; i++)
811 read_variable (&jit->locals [i], ptr, &ptr);
817 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
818 * a new class is initialized.
821 mono_debug_start_add_type (MonoClass *klass)
823 MonoDebugHandle *handle;
825 handle = _mono_debug_get_image (klass->image);
831 mono_debug_add_type (MonoClass *klass)
833 MonoDebugHandle *handle;
834 MonoDebugClassEntry *entry;
835 guint8 buffer [BUFSIZ];
836 guint8 *ptr, *oldptr;
837 guint32 size, total_size, max_size;
840 handle = _mono_debug_get_image (klass->image);
844 if (klass->generic_class || klass->rank ||
845 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
848 mono_debugger_lock ();
850 max_size = 12 + sizeof (gpointer);
851 if (max_size > BUFSIZ)
852 ptr = oldptr = g_malloc (max_size);
854 ptr = oldptr = buffer;
856 if (klass->valuetype)
857 base_offset = - (int)(sizeof (MonoObject));
859 write_leb128 (klass->type_token, ptr, &ptr);
860 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
861 WRITE_UNALIGNED (gpointer, ptr, klass);
862 ptr += sizeof (gpointer);
865 g_assert (size < max_size);
866 total_size = size + sizeof (MonoDebugClassEntry);
868 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
870 entry = (MonoDebugClassEntry *) allocate_data_item (
871 handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
873 entry->size = total_size;
875 memcpy (&entry->data, oldptr, size);
877 write_data_item (handle->type_table, (guint8 *) entry);
879 if (max_size > BUFSIZ)
882 mono_debugger_unlock ();
885 static MonoDebugMethodJitInfo *
886 find_method (MonoMethod *method, MonoDomain *domain)
888 MonoDebugDataTable *table;
889 MonoDebugMethodAddress *address;
891 table = lookup_data_table (domain);
892 address = g_hash_table_lookup (table->method_address_hash, method);
897 return mono_debug_read_method (address);
900 MonoDebugMethodJitInfo *
901 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
903 MonoDebugMethodJitInfo *res;
904 mono_debugger_lock ();
905 res = find_method (method, domain);
906 mono_debugger_unlock ();
910 struct LookupMethodAddressData
913 MonoDebugMethodHeader *result;
917 lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
919 MonoDebugDataTable *table = (MonoDebugDataTable *) value;
920 struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
921 MonoDebugMethodHeader *header;
923 header = g_hash_table_lookup (table->method_hash, data->method);
925 data->result = header;
928 MonoDebugMethodAddressList *
929 mono_debug_lookup_method_addresses (MonoMethod *method)
931 MonoDebugMethodAddressList *info;
932 MonoDebugMethodHeader *header = NULL;
933 struct LookupMethodAddressData data;
934 MonoMethod *declaring;
939 g_assert (mono_debug_debugger_version == 2);
941 mono_debugger_lock ();
943 declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
945 data.method = declaring;
948 g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
949 header = data.result;
952 mono_debugger_unlock ();
956 count = g_slist_length (header->address_list) + 1;
957 size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
959 info = g_malloc0 (size);
965 WRITE_UNALIGNED (gpointer, ptr, header);
966 ptr += sizeof (gpointer);
968 for (list = header->address_list; list; list = list->next) {
969 WRITE_UNALIGNED (gpointer, ptr, list->data);
970 ptr += sizeof (gpointer);
973 mono_debugger_unlock ();
978 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
980 MonoDebugMethodJitInfo *jit;
983 jit = find_method (method, domain);
984 if (!jit || !jit->line_numbers)
987 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
988 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
990 if (lne.native_offset <= native_offset)
991 return lne.il_offset;
998 * mono_debug_lookup_source_location:
999 * @address: Native offset within the @method's machine code.
1001 * Lookup the source code corresponding to the machine instruction located at
1002 * native offset @address within @method.
1004 * The returned `MonoDebugSourceLocation' contains both file / line number
1005 * information and the corresponding IL offset. It must be freed by
1006 * mono_debug_free_source_location().
1008 MonoDebugSourceLocation *
1009 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
1011 MonoDebugMethodInfo *minfo;
1012 MonoDebugSourceLocation *location;
1015 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
1018 mono_debugger_lock ();
1019 minfo = _mono_debug_lookup_method (method);
1020 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
1021 mono_debugger_unlock ();
1025 offset = il_offset_from_address (method, domain, address);
1027 mono_debugger_unlock ();
1031 location = mono_debug_symfile_lookup_location (minfo, offset);
1032 mono_debugger_unlock ();
1037 * mono_debug_free_source_location:
1038 * @location: A `MonoDebugSourceLocation'.
1040 * Frees the @location.
1043 mono_debug_free_source_location (MonoDebugSourceLocation *location)
1046 g_free (location->source_file);
1052 * mono_debug_print_stack_frame:
1053 * @native_offset: Native offset within the @method's machine code.
1055 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1056 * used if you only want to use the location to print a stack frame.
1059 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
1061 MonoDebugSourceLocation *location;
1062 gchar *fname, *ptr, *res;
1064 fname = mono_method_full_name (method, TRUE);
1065 for (ptr = fname; *ptr; ptr++) {
1066 if (*ptr == ':') *ptr = '.';
1069 location = mono_debug_lookup_source_location (method, native_offset, domain);
1072 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
1077 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
1078 location->source_file, location->row);
1081 mono_debug_free_source_location (location);
1086 mono_debug_list_add (MonoDebugList **list, gconstpointer data)
1088 MonoDebugList *element, **ptr;
1090 element = g_new0 (MonoDebugList, 1);
1091 element->data = data;
1093 for (ptr = list; *ptr; ptr = &(*ptr)->next)
1100 mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
1102 MonoDebugList **ptr;
1103 MonoDebugList *next;
1105 for (ptr = list; *ptr; ptr = &(*ptr)->next) {
1106 if ((*ptr)->data != data)
1109 next = (*ptr)->next;