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 SYMFILE_TABLE_CHUNK_SIZE 16
13 #define DATA_TABLE_PTR_CHUNK_SIZE 256
14 #define DATA_TABLE_CHUNK_SIZE 32768
16 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
18 #if NO_UNALIGNED_ACCESS
19 #define RETURN_UNALIGNED(type, addr) \
22 memcpy(&val, p + offset, sizeof(val)); \
25 #define WRITE_UNALIGNED(type, addr, val) \
26 memcpy(addr, &val, sizeof(type))
28 #define RETURN_UNALIGNED(type, addr) \
29 return *(type*)(p + offset);
30 #define WRITE_UNALIGNED(type, addr, val) \
31 (*(type *)(addr) = (val))
34 MonoSymbolTable *mono_symbol_table = NULL;
35 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
37 static gboolean in_the_mono_debugger = FALSE;
38 static gboolean mono_debug_initialized = FALSE;
39 GHashTable *mono_debug_handles = NULL;
41 static GHashTable *method_hash = NULL;
43 static MonoDebugHandle *mono_debug_open_image (MonoImage *image);
44 static void mono_debug_close_image (MonoDebugHandle *debug);
46 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
47 static void mono_debug_add_assembly (MonoAssembly *assembly,
49 static void mono_debug_start_add_type (MonoClass *klass);
50 static void mono_debug_add_type (MonoClass *klass);
52 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
53 extern void (*mono_debugger_start_class_init_func) (MonoClass *klass);
62 method_hash_hash (gconstpointer data)
64 const MethodHashEntry *entry = (const MethodHashEntry *) data;
65 return entry->symfile_id | (entry->domain_id << 16);
69 method_hash_equal (gconstpointer ka, gconstpointer kb)
71 const MethodHashEntry *a = (const MethodHashEntry *) ka;
72 const MethodHashEntry *b = (const MethodHashEntry *) kb;
74 if ((a->symfile_id != b->symfile_id) || (a->method_id != b->method_id) || (a->domain_id != b->domain_id))
80 * Initialize debugging support.
82 * This method must be called after loading corlib,
83 * but before opening the application's main assembly because we need to set some
87 mono_debug_init (MonoDebugFormat format)
89 g_assert (!mono_debug_initialized);
91 mono_debug_initialized = TRUE;
92 mono_debug_format = format;
93 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
95 mono_debugger_initialize (in_the_mono_debugger);
97 mono_debugger_lock ();
99 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
100 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
101 mono_symbol_table->version = MONO_DEBUGGER_VERSION;
102 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
104 mono_debug_handles = g_hash_table_new_full
105 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
106 method_hash = g_hash_table_new (method_hash_hash, method_hash_equal);
108 mono_debugger_start_class_init_func = mono_debug_start_add_type;
109 mono_debugger_class_init_func = mono_debug_add_type;
110 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
112 if (!in_the_mono_debugger)
113 mono_debugger_unlock ();
117 mono_debug_init_1 (MonoDomain *domain)
119 MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib ());
121 mono_symbol_table->corlib = handle;
125 * Initialize debugging support - part 2.
127 * This method must be called after loading the application's main assembly.
130 mono_debug_init_2 (MonoAssembly *assembly)
132 mono_debug_open_image (mono_assembly_get_image (assembly));
136 mono_debug_using_mono_debugger (void)
138 return in_the_mono_debugger;
142 mono_debug_cleanup (void)
144 mono_debugger_cleanup ();
146 if (mono_debug_handles)
147 g_hash_table_destroy (mono_debug_handles);
148 mono_debug_handles = NULL;
151 static MonoDebugHandle *
152 _mono_debug_get_image (MonoImage *image)
154 return g_hash_table_lookup (mono_debug_handles, image);
157 static MonoDebugHandle *
158 allocate_debug_handle (MonoSymbolTable *table)
160 MonoDebugHandle *handle;
162 if (!table->symbol_files)
163 table->symbol_files = g_new0 (MonoDebugHandle *, SYMFILE_TABLE_CHUNK_SIZE);
164 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
165 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
166 guint32 size = sizeof (MonoDebugHandle *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
168 table->symbol_files = g_realloc (table->symbol_files, size);
171 handle = g_new0 (MonoDebugHandle, 1);
172 handle->index = table->num_symbol_files;
173 table->symbol_files [table->num_symbol_files++] = handle;
177 static MonoDebugHandle *
178 mono_debug_open_image (MonoImage *image)
180 MonoDebugHandle *handle;
182 if (mono_image_is_dynamic (image))
185 handle = _mono_debug_get_image (image);
189 handle = allocate_debug_handle (mono_symbol_table);
191 handle->image = image;
192 mono_image_addref (image);
193 handle->image_file = g_strdup (mono_image_get_filename (image));
195 g_hash_table_insert (mono_debug_handles, image, handle);
197 handle->symfile = mono_debug_open_mono_symbol_file (handle, in_the_mono_debugger);
198 if (in_the_mono_debugger)
199 mono_debugger_add_symbol_file (handle);
205 mono_debug_close_image (MonoDebugHandle *handle)
208 mono_debug_close_mono_symbol_file (handle->symfile);
209 /* decrease the refcount added with mono_image_addref () */
210 mono_image_close (handle->image);
211 g_free (handle->image_file);
212 g_free (handle->_priv);
217 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
219 mono_debugger_lock ();
220 mono_debug_open_image (mono_assembly_get_image (assembly));
221 mono_debugger_unlock ();
225 * Allocate a new data item of size `size'.
226 * Returns the global offset which is to be used to reference this data item and
227 * a pointer (in the `ptr' argument) which is to be used to write it.
230 allocate_data_item (MonoDebugDataItemType type, guint32 size)
235 g_assert (mono_symbol_table);
237 size = ALIGN_TO (size, sizeof (gpointer));
239 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
240 chunk_size = DATA_TABLE_CHUNK_SIZE;
242 chunk_size = size + 16;
244 /* Initialize things if necessary. */
245 if (!mono_symbol_table->current_data_table) {
246 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
247 mono_symbol_table->current_data_table_size = chunk_size;
248 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
250 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
254 /* First let's check whether there's still enough room in the current_data_table. */
255 if (mono_symbol_table->current_data_table_offset + size + 8 < mono_symbol_table->current_data_table_size) {
256 data = ((guint8 *) mono_symbol_table->current_data_table) + mono_symbol_table->current_data_table_offset;
257 mono_symbol_table->current_data_table_offset += size + 8;
259 * ((guint32 *) data) = size;
261 * ((guint32 *) data) = type;
266 /* Add the current_data_table to the data_tables vector and ... */
267 if (!mono_symbol_table->data_tables) {
268 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE;
269 mono_symbol_table->data_tables = g_malloc0 (tsize);
272 if (!((mono_symbol_table->num_data_tables + 1) % DATA_TABLE_PTR_CHUNK_SIZE)) {
273 guint32 chunks = (mono_symbol_table->num_data_tables + 1) / DATA_TABLE_PTR_CHUNK_SIZE;
274 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
276 mono_symbol_table->data_tables = g_realloc (mono_symbol_table->data_tables, tsize);
279 mono_symbol_table->data_tables [mono_symbol_table->num_data_tables++] = mono_symbol_table->current_data_table;
281 /* .... allocate a new current_data_table. */
282 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
283 mono_symbol_table->current_data_table_size = chunk_size;
284 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
285 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
290 struct LookupMethodData
292 MonoDebugMethodInfo *minfo;
297 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
299 MonoDebugHandle *handle = (MonoDebugHandle *) value;
300 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
306 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
309 static MonoDebugMethodInfo *
310 _mono_debug_lookup_method (MonoMethod *method)
312 struct LookupMethodData data;
315 data.method = method;
317 if (!mono_debug_handles)
320 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
325 * mono_debug_lookup_method:
327 * Lookup symbol file information for the method @method. The returned
328 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
329 * mono_debug_symfile_lookup_location().
331 MonoDebugMethodInfo *
332 mono_debug_lookup_method (MonoMethod *method)
334 MonoDebugMethodInfo *minfo;
336 mono_debugger_lock ();
337 minfo = _mono_debug_lookup_method (method);
338 mono_debugger_unlock ();
343 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
346 guint8 byte = value & 0x7f;
357 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
362 guint8 byte = value & 0x7f;
365 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
376 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
378 write_leb128 (var->index, ptr, &ptr);
379 write_sleb128 (var->offset, ptr, &ptr);
380 write_leb128 (var->size, ptr, &ptr);
381 write_leb128 (var->begin_scope, ptr, &ptr);
382 write_leb128 (var->end_scope, ptr, &ptr);
386 static MonoDebugWrapperData *
387 mono_debug_add_wrapper (MonoMethod *method, MonoDebugMethodJitInfo *jit)
389 MonoMethodHeader *header;
390 MonoDebugWrapperData *wrapper;
391 char buffer [BUFSIZ];
392 guint8 *ptr, *oldptr;
393 guint32 i, size, total_size, max_size;
394 gint32 last_il_offset = 0, last_native_offset = 0;
395 const unsigned char* il_code;
398 if (!in_the_mono_debugger)
401 mono_debugger_lock ();
403 header = mono_method_get_header (method);
405 max_size = 28 * jit->num_line_numbers;
406 if (max_size > BUFSIZ)
407 ptr = oldptr = g_malloc (max_size);
409 ptr = oldptr = buffer;
411 write_leb128 (jit->prologue_end, ptr, &ptr);
412 write_leb128 (jit->epilogue_begin, ptr, &ptr);
413 write_leb128 (jit->num_line_numbers, ptr, &ptr);
414 for (i = 0; i < jit->num_line_numbers; i++) {
415 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
417 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
418 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
420 last_il_offset = lne->il_offset;
421 last_native_offset = lne->native_offset;
424 write_leb128 (method->wrapper_type, ptr, &ptr);
427 g_assert (size < max_size);
428 total_size = size + sizeof (MonoDebugWrapperData);
430 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
431 // FIXME: Maybe we should print a warning here.
432 // This should only happen for very big methods, for instance
433 // with more than 40.000 line numbers and more than 5.000
435 mono_debugger_unlock ();
439 wrapper = (MonoDebugWrapperData *) allocate_data_item (MONO_DEBUG_DATA_ITEM_WRAPPER, total_size);
441 wrapper->method = method;
442 wrapper->size = total_size;
443 wrapper->code_start = jit->code_start;
444 wrapper->code_size = jit->code_size;
445 wrapper->name = mono_method_full_name (method, TRUE);
447 il_code = mono_method_header_get_code (header, &il_codesize, NULL);
448 wrapper->cil_code = mono_disasm_code (
449 NULL, method, il_code, il_code + il_codesize);
451 memcpy (&wrapper->data, oldptr, size);
453 if (max_size > BUFSIZ)
456 mono_debugger_unlock ();
462 * This is called by the JIT to tell the debugging code about a newly
465 MonoDebugMethodAddress *
466 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
468 MonoDebugMethodAddress *address;
469 char buffer [BUFSIZ];
470 guint8 *ptr, *oldptr;
471 guint32 i, size, total_size, max_size;
472 gint32 last_il_offset = 0, last_native_offset = 0;
473 MonoDebugHandle *handle;
474 MonoDebugMethodInfo *minfo;
475 MethodHashEntry *hash;
477 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
478 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
479 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
480 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
481 (method->wrapper_type != MONO_WRAPPER_NONE)) {
482 mono_debug_add_wrapper (method, jit);
486 mono_debugger_lock ();
488 handle = _mono_debug_get_image (method->klass->image);
489 if (!handle || !handle->symfile || !handle->symfile->offset_table) {
490 mono_debug_add_wrapper (method, jit);
491 mono_debugger_unlock ();
495 minfo = _mono_debug_lookup_method (method);
497 mono_debugger_unlock ();
501 max_size = 24 + 8 * jit->num_line_numbers + 16 * minfo->num_lexical_blocks + 20 * (1 + jit->num_params + jit->num_locals);
502 if (max_size > BUFSIZ)
503 ptr = oldptr = g_malloc (max_size);
505 ptr = oldptr = buffer;
507 write_leb128 (jit->prologue_end, ptr, &ptr);
508 write_leb128 (jit->epilogue_begin, ptr, &ptr);
510 write_leb128 (jit->num_line_numbers, ptr, &ptr);
511 for (i = 0; i < jit->num_line_numbers; i++) {
512 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
514 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
515 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
517 last_il_offset = lne->il_offset;
518 last_native_offset = lne->native_offset;
521 jit->num_lexical_blocks = minfo->num_lexical_blocks;
522 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
523 for (i = 0; i < jit->num_lexical_blocks; i ++) {
524 MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
525 MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
526 jit_lbe->il_start_offset = read32 (&(minfo_lbe->_start_offset));
527 jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
529 jit_lbe->il_end_offset = read32 (&(minfo_lbe->_end_offset));
530 jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
534 last_native_offset = 0;
535 write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
536 for (i = 0; i < jit->num_lexical_blocks; i++) {
537 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
539 write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
540 write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
542 last_il_offset = lbe->il_start_offset;
543 last_native_offset = lbe->native_start_offset;
545 write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
546 write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
548 last_il_offset = lbe->il_end_offset;
549 last_native_offset = lbe->native_end_offset;
552 *ptr++ = jit->this_var ? 1 : 0;
554 write_variable (jit->this_var, ptr, &ptr);
556 write_leb128 (jit->num_params, ptr, &ptr);
557 for (i = 0; i < jit->num_params; i++)
558 write_variable (&jit->params [i], ptr, &ptr);
560 write_leb128 (jit->num_locals, ptr, &ptr);
561 for (i = 0; i < jit->num_locals; i++)
562 write_variable (&jit->locals [i], ptr, &ptr);
565 g_assert (size < max_size);
566 total_size = size + sizeof (MonoDebugMethodAddress);
568 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
569 // FIXME: Maybe we should print a warning here.
570 // This should only happen for very big methods, for instance
571 // with more than 40.000 line numbers and more than 5.000
573 mono_debugger_unlock ();
577 address = (MonoDebugMethodAddress *) allocate_data_item (MONO_DEBUG_DATA_ITEM_METHOD, total_size);
579 address->size = total_size;
580 address->symfile_id = handle->index;
581 address->domain_id = mono_domain_get_id (domain);
582 address->method_id = minfo->index;
583 address->code_start = jit->code_start;
584 address->code_size = jit->code_size;
585 address->wrapper_addr = jit->wrapper_addr;
587 memcpy (&address->data, oldptr, size);
589 if (max_size > BUFSIZ)
592 hash = g_new0 (MethodHashEntry, 1);
593 hash->symfile_id = address->symfile_id;
594 hash->domain_id = address->domain_id;
595 hash->method_id = address->method_id;
597 g_hash_table_insert (method_hash, hash, address);
599 mono_debugger_unlock ();
604 static inline guint32
605 read_leb128 (guint8 *ptr, guint8 **rptr)
607 guint32 result = 0, shift = 0;
610 guint8 byte = *ptr++;
612 result |= (byte & 0x7f) << shift;
613 if ((byte & 0x80) == 0)
623 read_sleb128 (guint8 *ptr, guint8 **rptr)
629 guint8 byte = *ptr++;
631 result |= (byte & 0x7f) << shift;
637 if ((shift < 32) && (byte & 0x40))
638 result |= - (1 << shift);
647 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
649 var->index = read_leb128 (ptr, &ptr);
650 var->offset = read_sleb128 (ptr, &ptr);
651 var->size = read_leb128 (ptr, &ptr);
652 var->begin_scope = read_leb128 (ptr, &ptr);
653 var->end_scope = read_leb128 (ptr, &ptr);
657 MonoDebugMethodJitInfo *
658 mono_debug_read_method (MonoDebugMethodAddress *address)
660 MonoDebugMethodJitInfo *jit;
661 guint32 i, il_offset = 0, native_offset = 0;
667 jit = address->jit = g_new0 (MonoDebugMethodJitInfo, 1);
668 jit->code_start = address->code_start;
669 jit->code_size = address->code_size;
670 jit->wrapper_addr = address->wrapper_addr;
672 ptr = (guint8 *) &address->data;
674 jit->prologue_end = read_leb128 (ptr, &ptr);
675 jit->epilogue_begin = read_leb128 (ptr, &ptr);
677 jit->num_line_numbers = read_leb128 (ptr, &ptr);
678 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
679 for (i = 0; i < jit->num_line_numbers; i++) {
680 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
682 il_offset += read_sleb128 (ptr, &ptr);
683 native_offset += read_sleb128 (ptr, &ptr);
685 lne->il_offset = il_offset;
686 lne->native_offset = native_offset;
691 jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
692 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
693 for (i = 0; i < jit->num_lexical_blocks; i ++) {
694 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
696 il_offset += read_sleb128 (ptr, &ptr);
697 native_offset += read_sleb128 (ptr, &ptr);
699 lbe->il_start_offset = il_offset;
700 lbe->native_start_offset = native_offset;
702 il_offset += read_sleb128 (ptr, &ptr);
703 native_offset += read_sleb128 (ptr, &ptr);
705 lbe->il_end_offset = il_offset;
706 lbe->native_end_offset = native_offset;
710 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
711 read_variable (jit->this_var, ptr, &ptr);
714 jit->num_params = read_leb128 (ptr, &ptr);
715 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
716 for (i = 0; i < jit->num_params; i++)
717 read_variable (&jit->params [i], ptr, &ptr);
719 jit->num_locals = read_leb128 (ptr, &ptr);
720 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
721 for (i = 0; i < jit->num_locals; i++)
722 read_variable (&jit->locals [i], ptr, &ptr);
728 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
731 jit->address->jit = NULL;
733 g_free (jit->line_numbers);
734 g_free (jit->this_var);
735 g_free (jit->params);
736 g_free (jit->locals);
741 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
742 * a new class is initialized.
745 mono_debug_start_add_type (MonoClass *klass)
747 MonoDebugHandle *handle;
749 handle = _mono_debug_get_image (klass->image);
755 mono_debug_add_type (MonoClass *klass)
757 MonoDebugHandle *handle;
758 MonoDebugClassEntry *entry;
759 char buffer [BUFSIZ];
760 guint8 *ptr, *oldptr;
761 guint32 size, total_size, max_size;
764 handle = _mono_debug_get_image (klass->image);
768 if (klass->generic_class || klass->rank ||
769 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
772 max_size = 12 + sizeof (gpointer);
773 if (max_size > BUFSIZ)
774 ptr = oldptr = g_malloc (max_size);
776 ptr = oldptr = buffer;
778 if (klass->valuetype)
779 base_offset = - (int)(sizeof (MonoObject));
781 write_leb128 (klass->type_token, ptr, &ptr);
782 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
783 WRITE_UNALIGNED (gpointer, ptr, klass);
784 ptr += sizeof (gpointer);
787 g_assert (size < max_size);
788 total_size = size + sizeof (MonoDebugClassEntry);
790 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
792 entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
794 entry->size = total_size;
795 entry->symfile_id = handle->index;
797 memcpy (&entry->data, oldptr, size);
799 if (max_size > BUFSIZ)
802 mono_debugger_start_add_type (handle, klass);
805 static MonoDebugMethodJitInfo *
806 find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
808 MethodHashEntry lookup;
809 MonoDebugMethodAddress *address;
811 lookup.symfile_id = minfo->handle->index;
812 lookup.domain_id = mono_domain_get_id (domain);
813 lookup.method_id = minfo->index;
815 address = g_hash_table_lookup (method_hash, &lookup);
819 return mono_debug_read_method (address);
823 il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32 native_offset)
825 MonoDebugMethodJitInfo *jit;
828 jit = find_method (minfo, domain);
829 if (!jit || !jit->line_numbers)
832 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
833 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
835 if (lne.native_offset <= native_offset)
836 return lne.il_offset;
843 * mono_debug_lookup_source_location:
844 * @address: Native offset within the @method's machine code.
846 * Lookup the source code corresponding to the machine instruction located at
847 * native offset @address within @method.
849 * The returned `MonoDebugSourceLocation' contains both file / line number
850 * information and the corresponding IL offset. It must be freed by
851 * mono_debug_free_source_location().
853 MonoDebugSourceLocation *
854 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
856 MonoDebugMethodInfo *minfo;
857 MonoDebugSourceLocation *location;
860 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
863 mono_debugger_lock ();
864 minfo = _mono_debug_lookup_method (method);
865 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
866 mono_debugger_unlock ();
870 offset = il_offset_from_address (minfo, domain, address);
872 mono_debugger_unlock ();
876 location = mono_debug_symfile_lookup_location (minfo, offset);
877 mono_debugger_unlock ();
882 * mono_debug_free_source_location:
883 * @location: A `MonoDebugSourceLocation'.
885 * Frees the @location.
888 mono_debug_free_source_location (MonoDebugSourceLocation *location)
891 g_free (location->source_file);
897 * mono_debug_print_stack_frame:
898 * @native_offset: Native offset within the @method's machine code.
900 * Conventient wrapper around mono_debug_lookup_source_location() which can be
901 * used if you only want to use the location to print a stack frame.
904 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
906 MonoDebugSourceLocation *location;
909 fname = mono_method_full_name (method, TRUE);
910 location = mono_debug_lookup_source_location (method, native_offset, domain);
913 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
918 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
919 location->source_file, location->row);
922 mono_debug_free_source_location (location);