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, const guint8 *raw_contents, int size);
45 static void mono_debug_close_image (MonoDebugHandle *debug);
47 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
48 static void mono_debug_add_assembly (MonoAssembly *assembly,
50 static void mono_debug_start_add_type (MonoClass *klass);
51 static void mono_debug_add_type (MonoClass *klass);
53 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
54 extern void (*mono_debugger_start_class_init_func) (MonoClass *klass);
63 method_hash_hash (gconstpointer data)
65 const MethodHashEntry *entry = (const MethodHashEntry *) data;
66 return entry->symfile_id | (entry->domain_id << 16);
70 method_hash_equal (gconstpointer ka, gconstpointer kb)
72 const MethodHashEntry *a = (const MethodHashEntry *) ka;
73 const MethodHashEntry *b = (const MethodHashEntry *) kb;
75 if ((a->symfile_id != b->symfile_id) || (a->method_id != b->method_id) || (a->domain_id != b->domain_id))
81 * Initialize debugging support.
83 * This method must be called after loading corlib,
84 * but before opening the application's main assembly because we need to set some
88 mono_debug_init (MonoDebugFormat format)
90 g_assert (!mono_debug_initialized);
92 mono_debug_initialized = TRUE;
93 mono_debug_format = format;
94 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
96 mono_debugger_initialize (in_the_mono_debugger);
98 mono_debugger_lock ();
100 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
101 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
102 mono_symbol_table->version = MONO_DEBUGGER_VERSION;
103 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
105 mono_debug_handles = g_hash_table_new_full
106 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
107 method_hash = g_hash_table_new (method_hash_hash, method_hash_equal);
109 mono_debugger_start_class_init_func = mono_debug_start_add_type;
110 mono_debugger_class_init_func = mono_debug_add_type;
111 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
113 if (!in_the_mono_debugger)
114 mono_debugger_unlock ();
118 mono_debug_init_1 (MonoDomain *domain)
120 MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib (), NULL, 0);
122 mono_symbol_table->corlib = handle;
126 * Initialize debugging support - part 2.
128 * This method must be called after loading the application's main assembly.
131 mono_debug_init_2 (MonoAssembly *assembly)
133 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
137 * Initialize debugging support - part 2.
139 * This method must be called between loading the image and loading the assembly.
142 mono_debug_init_2_memory (MonoImage *image, const guint8 *raw_contents, int size)
144 mono_debug_open_image (image, raw_contents, size);
149 mono_debug_using_mono_debugger (void)
151 return in_the_mono_debugger;
155 mono_debug_cleanup (void)
157 mono_debugger_cleanup ();
159 if (mono_debug_handles)
160 g_hash_table_destroy (mono_debug_handles);
161 mono_debug_handles = NULL;
164 static MonoDebugHandle *
165 _mono_debug_get_image (MonoImage *image)
167 return g_hash_table_lookup (mono_debug_handles, image);
170 static MonoDebugHandle *
171 allocate_debug_handle (MonoSymbolTable *table)
173 MonoDebugHandle *handle;
175 if (!table->symbol_files)
176 table->symbol_files = g_new0 (MonoDebugHandle *, SYMFILE_TABLE_CHUNK_SIZE);
177 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
178 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
179 guint32 size = sizeof (MonoDebugHandle *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
181 table->symbol_files = g_realloc (table->symbol_files, size);
184 handle = g_new0 (MonoDebugHandle, 1);
185 handle->index = table->num_symbol_files;
186 table->symbol_files [table->num_symbol_files++] = handle;
190 static MonoDebugHandle *
191 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
193 MonoDebugHandle *handle;
195 if (mono_image_is_dynamic (image))
198 handle = _mono_debug_get_image (image);
202 handle = allocate_debug_handle (mono_symbol_table);
204 handle->image = image;
205 mono_image_addref (image);
206 handle->image_file = g_strdup (mono_image_get_filename (image));
208 g_hash_table_insert (mono_debug_handles, image, handle);
210 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, in_the_mono_debugger);
211 if (in_the_mono_debugger)
212 mono_debugger_add_symbol_file (handle);
218 mono_debug_close_image (MonoDebugHandle *handle)
221 mono_debug_close_mono_symbol_file (handle->symfile);
222 /* decrease the refcount added with mono_image_addref () */
223 mono_image_close (handle->image);
224 g_free (handle->image_file);
225 g_free (handle->_priv);
230 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
232 mono_debugger_lock ();
233 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
234 mono_debugger_unlock ();
238 * Allocate a new data item of size `size'.
239 * Returns the global offset which is to be used to reference this data item and
240 * a pointer (in the `ptr' argument) which is to be used to write it.
243 allocate_data_item (MonoDebugDataItemType type, guint32 size)
248 g_assert (mono_symbol_table);
250 size = ALIGN_TO (size, sizeof (gpointer));
252 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
253 chunk_size = DATA_TABLE_CHUNK_SIZE;
255 chunk_size = size + 16;
257 /* Initialize things if necessary. */
258 if (!mono_symbol_table->current_data_table) {
259 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
260 mono_symbol_table->current_data_table_size = chunk_size;
261 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
263 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
267 /* First let's check whether there's still enough room in the current_data_table. */
268 if (mono_symbol_table->current_data_table_offset + size + 8 < mono_symbol_table->current_data_table_size) {
269 data = ((guint8 *) mono_symbol_table->current_data_table) + mono_symbol_table->current_data_table_offset;
270 mono_symbol_table->current_data_table_offset += size + 8;
272 * ((guint32 *) data) = size;
274 * ((guint32 *) data) = type;
279 /* Add the current_data_table to the data_tables vector and ... */
280 if (!mono_symbol_table->data_tables) {
281 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE;
282 mono_symbol_table->data_tables = g_malloc0 (tsize);
285 if (!((mono_symbol_table->num_data_tables + 1) % DATA_TABLE_PTR_CHUNK_SIZE)) {
286 guint32 chunks = (mono_symbol_table->num_data_tables + 1) / DATA_TABLE_PTR_CHUNK_SIZE;
287 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
289 mono_symbol_table->data_tables = g_realloc (mono_symbol_table->data_tables, tsize);
292 mono_symbol_table->data_tables [mono_symbol_table->num_data_tables++] = mono_symbol_table->current_data_table;
294 /* .... allocate a new current_data_table. */
295 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
296 mono_symbol_table->current_data_table_size = chunk_size;
297 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
298 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
303 struct LookupMethodData
305 MonoDebugMethodInfo *minfo;
310 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
312 MonoDebugHandle *handle = (MonoDebugHandle *) value;
313 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
319 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
322 static MonoDebugMethodInfo *
323 _mono_debug_lookup_method (MonoMethod *method)
325 struct LookupMethodData data;
328 data.method = method;
330 if (!mono_debug_handles)
333 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
338 * mono_debug_lookup_method:
340 * Lookup symbol file information for the method @method. The returned
341 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
342 * mono_debug_symfile_lookup_location().
344 MonoDebugMethodInfo *
345 mono_debug_lookup_method (MonoMethod *method)
347 MonoDebugMethodInfo *minfo;
349 mono_debugger_lock ();
350 minfo = _mono_debug_lookup_method (method);
351 mono_debugger_unlock ();
356 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
359 guint8 byte = value & 0x7f;
370 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
375 guint8 byte = value & 0x7f;
378 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
389 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
391 write_leb128 (var->index, ptr, &ptr);
392 write_sleb128 (var->offset, ptr, &ptr);
393 write_leb128 (var->size, ptr, &ptr);
394 write_leb128 (var->begin_scope, ptr, &ptr);
395 write_leb128 (var->end_scope, ptr, &ptr);
399 static MonoDebugWrapperData *
400 mono_debug_add_wrapper (MonoMethod *method, MonoDebugMethodJitInfo *jit)
402 MonoMethodHeader *header;
403 MonoDebugWrapperData *wrapper;
404 guint8 buffer [BUFSIZ];
405 guint8 *ptr, *oldptr;
406 guint32 i, size, total_size, max_size;
407 gint32 last_il_offset = 0, last_native_offset = 0;
408 const unsigned char* il_code;
411 if (!in_the_mono_debugger)
414 mono_debugger_lock ();
416 header = mono_method_get_header (method);
418 max_size = 28 * jit->num_line_numbers;
419 if (max_size > BUFSIZ)
420 ptr = oldptr = g_malloc (max_size);
422 ptr = oldptr = buffer;
424 write_leb128 (jit->prologue_end, ptr, &ptr);
425 write_leb128 (jit->epilogue_begin, ptr, &ptr);
426 write_leb128 (jit->num_line_numbers, ptr, &ptr);
427 for (i = 0; i < jit->num_line_numbers; i++) {
428 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
430 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
431 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
433 last_il_offset = lne->il_offset;
434 last_native_offset = lne->native_offset;
437 write_leb128 (method->wrapper_type, ptr, &ptr);
440 g_assert (size < max_size);
441 total_size = size + sizeof (MonoDebugWrapperData);
443 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
444 // FIXME: Maybe we should print a warning here.
445 // This should only happen for very big methods, for instance
446 // with more than 40.000 line numbers and more than 5.000
448 mono_debugger_unlock ();
452 wrapper = (MonoDebugWrapperData *) allocate_data_item (MONO_DEBUG_DATA_ITEM_WRAPPER, total_size);
454 wrapper->method = method;
455 wrapper->size = total_size;
456 wrapper->code_start = jit->code_start;
457 wrapper->code_size = jit->code_size;
458 wrapper->name = mono_method_full_name (method, TRUE);
460 il_code = mono_method_header_get_code (header, &il_codesize, NULL);
461 wrapper->cil_code = mono_disasm_code (
462 NULL, method, il_code, il_code + il_codesize);
464 memcpy (&wrapper->data, oldptr, size);
466 if (max_size > BUFSIZ)
469 mono_debugger_unlock ();
475 * This is called by the JIT to tell the debugging code about a newly
478 MonoDebugMethodAddress *
479 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
481 MonoDebugMethodAddress *address;
482 guint8 buffer [BUFSIZ];
483 guint8 *ptr, *oldptr;
484 guint32 i, size, total_size, max_size;
485 gint32 last_il_offset = 0, last_native_offset = 0;
486 MonoDebugHandle *handle;
487 MonoDebugMethodInfo *minfo;
488 MethodHashEntry *hash;
490 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
491 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
492 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
493 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
494 (method->wrapper_type != MONO_WRAPPER_NONE)) {
495 mono_debug_add_wrapper (method, jit);
499 mono_debugger_lock ();
501 handle = _mono_debug_get_image (method->klass->image);
502 if (!handle || !handle->symfile || !handle->symfile->offset_table) {
503 mono_debug_add_wrapper (method, jit);
504 mono_debugger_unlock ();
508 minfo = _mono_debug_lookup_method (method);
510 mono_debugger_unlock ();
514 max_size = 24 + 8 * jit->num_line_numbers + 16 * minfo->num_lexical_blocks + 20 * (1 + jit->num_params + jit->num_locals);
515 if (max_size > BUFSIZ)
516 ptr = oldptr = g_malloc (max_size);
518 ptr = oldptr = buffer;
520 write_leb128 (jit->prologue_end, ptr, &ptr);
521 write_leb128 (jit->epilogue_begin, ptr, &ptr);
523 write_leb128 (jit->num_line_numbers, ptr, &ptr);
524 for (i = 0; i < jit->num_line_numbers; i++) {
525 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
527 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
528 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
530 last_il_offset = lne->il_offset;
531 last_native_offset = lne->native_offset;
534 jit->num_lexical_blocks = minfo->num_lexical_blocks;
535 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
536 for (i = 0; i < jit->num_lexical_blocks; i ++) {
537 MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
538 MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
539 jit_lbe->il_start_offset = read32 (&(minfo_lbe->_start_offset));
540 jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
542 jit_lbe->il_end_offset = read32 (&(minfo_lbe->_end_offset));
543 jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
547 last_native_offset = 0;
548 write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
549 for (i = 0; i < jit->num_lexical_blocks; i++) {
550 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
552 write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
553 write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
555 last_il_offset = lbe->il_start_offset;
556 last_native_offset = lbe->native_start_offset;
558 write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
559 write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
561 last_il_offset = lbe->il_end_offset;
562 last_native_offset = lbe->native_end_offset;
565 *ptr++ = jit->this_var ? 1 : 0;
567 write_variable (jit->this_var, ptr, &ptr);
569 write_leb128 (jit->num_params, ptr, &ptr);
570 for (i = 0; i < jit->num_params; i++)
571 write_variable (&jit->params [i], ptr, &ptr);
573 write_leb128 (jit->num_locals, ptr, &ptr);
574 for (i = 0; i < jit->num_locals; i++)
575 write_variable (&jit->locals [i], ptr, &ptr);
578 g_assert (size < max_size);
579 total_size = size + sizeof (MonoDebugMethodAddress);
581 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
582 // FIXME: Maybe we should print a warning here.
583 // This should only happen for very big methods, for instance
584 // with more than 40.000 line numbers and more than 5.000
586 mono_debugger_unlock ();
590 address = (MonoDebugMethodAddress *) allocate_data_item (MONO_DEBUG_DATA_ITEM_METHOD, total_size);
592 address->size = total_size;
593 address->symfile_id = handle->index;
594 address->domain_id = mono_domain_get_id (domain);
595 address->method_id = minfo->index;
596 address->code_start = jit->code_start;
597 address->code_size = jit->code_size;
598 address->wrapper_addr = jit->wrapper_addr;
600 memcpy (&address->data, oldptr, size);
602 if (max_size > BUFSIZ)
605 hash = g_new0 (MethodHashEntry, 1);
606 hash->symfile_id = address->symfile_id;
607 hash->domain_id = address->domain_id;
608 hash->method_id = address->method_id;
610 g_hash_table_insert (method_hash, hash, address);
612 mono_debugger_unlock ();
617 static inline guint32
618 read_leb128 (guint8 *ptr, guint8 **rptr)
620 guint32 result = 0, shift = 0;
623 guint8 byte = *ptr++;
625 result |= (byte & 0x7f) << shift;
626 if ((byte & 0x80) == 0)
636 read_sleb128 (guint8 *ptr, guint8 **rptr)
642 guint8 byte = *ptr++;
644 result |= (byte & 0x7f) << shift;
650 if ((shift < 32) && (byte & 0x40))
651 result |= - (1 << shift);
660 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
662 var->index = read_leb128 (ptr, &ptr);
663 var->offset = read_sleb128 (ptr, &ptr);
664 var->size = read_leb128 (ptr, &ptr);
665 var->begin_scope = read_leb128 (ptr, &ptr);
666 var->end_scope = read_leb128 (ptr, &ptr);
670 MonoDebugMethodJitInfo *
671 mono_debug_read_method (MonoDebugMethodAddress *address)
673 MonoDebugMethodJitInfo *jit;
674 guint32 i, il_offset = 0, native_offset = 0;
680 jit = address->jit = g_new0 (MonoDebugMethodJitInfo, 1);
681 jit->code_start = address->code_start;
682 jit->code_size = address->code_size;
683 jit->wrapper_addr = address->wrapper_addr;
685 ptr = (guint8 *) &address->data;
687 jit->prologue_end = read_leb128 (ptr, &ptr);
688 jit->epilogue_begin = read_leb128 (ptr, &ptr);
690 jit->num_line_numbers = read_leb128 (ptr, &ptr);
691 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
692 for (i = 0; i < jit->num_line_numbers; i++) {
693 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
695 il_offset += read_sleb128 (ptr, &ptr);
696 native_offset += read_sleb128 (ptr, &ptr);
698 lne->il_offset = il_offset;
699 lne->native_offset = native_offset;
704 jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
705 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
706 for (i = 0; i < jit->num_lexical_blocks; i ++) {
707 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
709 il_offset += read_sleb128 (ptr, &ptr);
710 native_offset += read_sleb128 (ptr, &ptr);
712 lbe->il_start_offset = il_offset;
713 lbe->native_start_offset = native_offset;
715 il_offset += read_sleb128 (ptr, &ptr);
716 native_offset += read_sleb128 (ptr, &ptr);
718 lbe->il_end_offset = il_offset;
719 lbe->native_end_offset = native_offset;
723 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
724 read_variable (jit->this_var, ptr, &ptr);
727 jit->num_params = read_leb128 (ptr, &ptr);
728 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
729 for (i = 0; i < jit->num_params; i++)
730 read_variable (&jit->params [i], ptr, &ptr);
732 jit->num_locals = read_leb128 (ptr, &ptr);
733 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
734 for (i = 0; i < jit->num_locals; i++)
735 read_variable (&jit->locals [i], ptr, &ptr);
741 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
744 jit->address->jit = NULL;
746 g_free (jit->line_numbers);
747 g_free (jit->this_var);
748 g_free (jit->params);
749 g_free (jit->locals);
754 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
755 * a new class is initialized.
758 mono_debug_start_add_type (MonoClass *klass)
760 MonoDebugHandle *handle;
762 handle = _mono_debug_get_image (klass->image);
768 mono_debug_add_type (MonoClass *klass)
770 MonoDebugHandle *handle;
771 MonoDebugClassEntry *entry;
772 guint8 buffer [BUFSIZ];
773 guint8 *ptr, *oldptr;
774 guint32 size, total_size, max_size;
777 handle = _mono_debug_get_image (klass->image);
781 if (klass->generic_class || klass->rank ||
782 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
785 max_size = 12 + sizeof (gpointer);
786 if (max_size > BUFSIZ)
787 ptr = oldptr = g_malloc (max_size);
789 ptr = oldptr = buffer;
791 if (klass->valuetype)
792 base_offset = - (int)(sizeof (MonoObject));
794 write_leb128 (klass->type_token, ptr, &ptr);
795 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
796 WRITE_UNALIGNED (gpointer, ptr, klass);
797 ptr += sizeof (gpointer);
800 g_assert (size < max_size);
801 total_size = size + sizeof (MonoDebugClassEntry);
803 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
805 entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
807 entry->size = total_size;
808 entry->symfile_id = handle->index;
810 memcpy (&entry->data, oldptr, size);
812 if (max_size > BUFSIZ)
815 mono_debugger_add_type (handle, klass);
818 static MonoDebugMethodJitInfo *
819 find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
821 MethodHashEntry lookup;
822 MonoDebugMethodAddress *address;
824 lookup.symfile_id = minfo->handle->index;
825 lookup.domain_id = mono_domain_get_id (domain);
826 lookup.method_id = minfo->index;
828 address = g_hash_table_lookup (method_hash, &lookup);
832 return mono_debug_read_method (address);
835 MonoDebugMethodJitInfo *
836 mono_debug_find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
838 MonoDebugMethodJitInfo *res;
839 mono_debugger_lock ();
840 res = find_method (minfo, domain);
841 mono_debugger_unlock ();
846 il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32 native_offset)
848 MonoDebugMethodJitInfo *jit;
851 jit = find_method (minfo, domain);
852 if (!jit || !jit->line_numbers)
855 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
856 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
858 if (lne.native_offset <= native_offset)
859 return lne.il_offset;
866 * mono_debug_lookup_source_location:
867 * @address: Native offset within the @method's machine code.
869 * Lookup the source code corresponding to the machine instruction located at
870 * native offset @address within @method.
872 * The returned `MonoDebugSourceLocation' contains both file / line number
873 * information and the corresponding IL offset. It must be freed by
874 * mono_debug_free_source_location().
876 MonoDebugSourceLocation *
877 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
879 MonoDebugMethodInfo *minfo;
880 MonoDebugSourceLocation *location;
883 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
886 mono_debugger_lock ();
887 minfo = _mono_debug_lookup_method (method);
888 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
889 mono_debugger_unlock ();
893 offset = il_offset_from_address (minfo, domain, address);
895 mono_debugger_unlock ();
899 location = mono_debug_symfile_lookup_location (minfo, offset);
900 mono_debugger_unlock ();
905 * mono_debug_free_source_location:
906 * @location: A `MonoDebugSourceLocation'.
908 * Frees the @location.
911 mono_debug_free_source_location (MonoDebugSourceLocation *location)
914 g_free (location->source_file);
920 * mono_debug_print_stack_frame:
921 * @native_offset: Native offset within the @method's machine code.
923 * Conventient wrapper around mono_debug_lookup_source_location() which can be
924 * used if you only want to use the location to print a stack frame.
927 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
929 MonoDebugSourceLocation *location;
930 gchar *fname, *ptr, *res;
932 fname = mono_method_full_name (method, TRUE);
933 for (ptr = fname; *ptr; ptr++) {
934 if (*ptr == ':') *ptr = '.';
937 location = mono_debug_lookup_source_location (method, native_offset, domain);
940 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
945 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
946 location->source_file, location->row);
949 mono_debug_free_source_location (location);