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;
36 guint32 mono_debug_debugger_version = -1;
38 static gboolean in_the_mono_debugger = FALSE;
39 static gboolean mono_debug_initialized = FALSE;
40 GHashTable *mono_debug_handles = NULL;
42 static GHashTable *method_hash = NULL;
44 static MonoDebugHandle *mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size);
46 static void mono_debug_close_image (MonoDebugHandle *debug);
48 static MonoDebugHandle *_mono_debug_get_image (MonoImage *image);
49 static void mono_debug_add_assembly (MonoAssembly *assembly,
51 static void mono_debug_start_add_type (MonoClass *klass);
52 static void mono_debug_add_type (MonoClass *klass);
54 extern void (*mono_debugger_class_init_func) (MonoClass *klass);
55 extern void (*mono_debugger_start_class_init_func) (MonoClass *klass);
64 method_hash_hash (gconstpointer data)
66 const MethodHashEntry *entry = (const MethodHashEntry *) data;
67 return entry->symfile_id | (entry->domain_id << 16);
71 method_hash_equal (gconstpointer ka, gconstpointer kb)
73 const MethodHashEntry *a = (const MethodHashEntry *) ka;
74 const MethodHashEntry *b = (const MethodHashEntry *) kb;
76 if ((a->symfile_id != b->symfile_id) || (a->method_id != b->method_id) || (a->domain_id != b->domain_id))
82 * Initialize debugging support.
84 * This method must be called after loading corlib,
85 * but before opening the application's main assembly because we need to set some
89 mono_debug_init (MonoDebugFormat format)
91 g_assert (!mono_debug_initialized);
93 mono_debug_initialized = TRUE;
94 mono_debug_format = format;
95 in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER;
97 mono_debugger_initialize (in_the_mono_debugger);
99 mono_debugger_lock ();
101 mono_symbol_table = g_new0 (MonoSymbolTable, 1);
102 mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
103 mono_symbol_table->version = MONO_DEBUGGER_VERSION;
104 mono_symbol_table->total_size = sizeof (MonoSymbolTable);
106 mono_debug_handles = g_hash_table_new_full
107 (NULL, NULL, NULL, (GDestroyNotify) mono_debug_close_image);
108 method_hash = g_hash_table_new (method_hash_hash, method_hash_equal);
110 mono_debugger_start_class_init_func = mono_debug_start_add_type;
111 mono_debugger_class_init_func = mono_debug_add_type;
112 mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
114 if (!in_the_mono_debugger)
115 mono_debugger_unlock ();
119 mono_debug_init_1 (MonoDomain *domain)
121 MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib (), NULL, 0);
123 mono_symbol_table->corlib = handle;
127 * Initialize debugging support - part 2.
129 * This method must be called after loading the application's main assembly.
132 mono_debug_init_2 (MonoAssembly *assembly)
134 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
138 * Initialize debugging support - part 2.
140 * This method must be called between loading the image and loading the assembly.
143 mono_debug_init_2_memory (MonoImage *image, const guint8 *raw_contents, int size)
145 mono_debug_open_image (image, raw_contents, size);
150 mono_debug_using_mono_debugger (void)
152 return in_the_mono_debugger;
156 mono_debug_cleanup (void)
158 mono_debugger_cleanup ();
160 if (mono_debug_handles)
161 g_hash_table_destroy (mono_debug_handles);
162 mono_debug_handles = NULL;
165 static MonoDebugHandle *
166 _mono_debug_get_image (MonoImage *image)
168 return g_hash_table_lookup (mono_debug_handles, image);
171 static MonoDebugHandle *
172 allocate_debug_handle (MonoSymbolTable *table)
174 MonoDebugHandle *handle;
176 if (!table->symbol_files)
177 table->symbol_files = g_new0 (MonoDebugHandle *, SYMFILE_TABLE_CHUNK_SIZE);
178 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
179 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
180 guint32 size = sizeof (MonoDebugHandle *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
182 table->symbol_files = g_realloc (table->symbol_files, size);
185 handle = g_new0 (MonoDebugHandle, 1);
186 handle->index = table->num_symbol_files;
187 table->symbol_files [table->num_symbol_files++] = handle;
191 static MonoDebugHandle *
192 mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
194 MonoDebugHandle *handle;
196 if (mono_image_is_dynamic (image))
199 handle = _mono_debug_get_image (image);
203 handle = allocate_debug_handle (mono_symbol_table);
205 handle->image = image;
206 mono_image_addref (image);
207 handle->image_file = g_strdup (mono_image_get_filename (image));
209 g_hash_table_insert (mono_debug_handles, image, handle);
211 handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, in_the_mono_debugger);
212 if (in_the_mono_debugger)
213 mono_debugger_add_symbol_file (handle);
219 mono_debug_close_image (MonoDebugHandle *handle)
222 mono_debug_close_mono_symbol_file (handle->symfile);
223 /* decrease the refcount added with mono_image_addref () */
224 mono_image_close (handle->image);
225 g_free (handle->image_file);
226 g_free (handle->_priv);
231 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
233 mono_debugger_lock ();
234 mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
235 mono_debugger_unlock ();
239 * Allocate a new data item of size `size'.
240 * Returns the global offset which is to be used to reference this data item and
241 * a pointer (in the `ptr' argument) which is to be used to write it.
244 allocate_data_item (MonoDebugDataItemType type, guint32 size)
249 g_assert (mono_symbol_table);
251 size = ALIGN_TO (size, sizeof (gpointer));
253 if (size + 16 < DATA_TABLE_CHUNK_SIZE)
254 chunk_size = DATA_TABLE_CHUNK_SIZE;
256 chunk_size = size + 16;
258 /* Initialize things if necessary. */
259 if (!mono_symbol_table->current_data_table) {
260 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
261 mono_symbol_table->current_data_table_size = chunk_size;
262 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
264 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
268 /* First let's check whether there's still enough room in the current_data_table. */
269 if (mono_symbol_table->current_data_table_offset + size + 8 < mono_symbol_table->current_data_table_size) {
270 data = ((guint8 *) mono_symbol_table->current_data_table) + mono_symbol_table->current_data_table_offset;
271 mono_symbol_table->current_data_table_offset += size + 8;
273 * ((guint32 *) data) = size;
275 * ((guint32 *) data) = type;
280 /* Add the current_data_table to the data_tables vector and ... */
281 if (!mono_symbol_table->data_tables) {
282 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE;
283 mono_symbol_table->data_tables = g_malloc0 (tsize);
286 if (!((mono_symbol_table->num_data_tables + 1) % DATA_TABLE_PTR_CHUNK_SIZE)) {
287 guint32 chunks = (mono_symbol_table->num_data_tables + 1) / DATA_TABLE_PTR_CHUNK_SIZE;
288 guint32 tsize = sizeof (gpointer) * DATA_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
290 mono_symbol_table->data_tables = g_realloc (mono_symbol_table->data_tables, tsize);
293 mono_symbol_table->data_tables [mono_symbol_table->num_data_tables++] = mono_symbol_table->current_data_table;
295 /* .... allocate a new current_data_table. */
296 mono_symbol_table->current_data_table = g_malloc0 (chunk_size);
297 mono_symbol_table->current_data_table_size = chunk_size;
298 mono_symbol_table->current_data_table_offset = sizeof (gpointer);
299 * ((guint32 *) mono_symbol_table->current_data_table) = chunk_size;
304 struct LookupMethodData
306 MonoDebugMethodInfo *minfo;
311 lookup_method_func (gpointer key, gpointer value, gpointer user_data)
313 MonoDebugHandle *handle = (MonoDebugHandle *) value;
314 struct LookupMethodData *data = (struct LookupMethodData *) user_data;
320 data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
323 static MonoDebugMethodInfo *
324 _mono_debug_lookup_method (MonoMethod *method)
326 struct LookupMethodData data;
329 data.method = method;
331 if (!mono_debug_handles)
334 g_hash_table_foreach (mono_debug_handles, lookup_method_func, &data);
339 * mono_debug_lookup_method:
341 * Lookup symbol file information for the method @method. The returned
342 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
343 * mono_debug_symfile_lookup_location().
345 MonoDebugMethodInfo *
346 mono_debug_lookup_method (MonoMethod *method)
348 MonoDebugMethodInfo *minfo;
350 mono_debugger_lock ();
351 minfo = _mono_debug_lookup_method (method);
352 mono_debugger_unlock ();
357 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
360 guint8 byte = value & 0x7f;
371 write_sleb128 (gint32 value, guint8 *ptr, guint8 **rptr)
376 guint8 byte = value & 0x7f;
379 if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && (byte & 0x40)))
390 write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
392 write_leb128 (var->index, ptr, &ptr);
393 write_sleb128 (var->offset, ptr, &ptr);
394 write_leb128 (var->size, ptr, &ptr);
395 write_leb128 (var->begin_scope, ptr, &ptr);
396 write_leb128 (var->end_scope, ptr, &ptr);
400 static MonoDebugWrapperData *
401 mono_debug_add_wrapper (MonoMethod *method, MonoDebugMethodJitInfo *jit)
403 MonoMethodHeader *header;
404 MonoDebugWrapperData *wrapper;
405 guint8 buffer [BUFSIZ];
406 guint8 *ptr, *oldptr;
407 guint32 i, size, total_size, max_size;
408 gint32 last_il_offset = 0, last_native_offset = 0;
409 const unsigned char* il_code;
412 if (!in_the_mono_debugger)
415 mono_debugger_lock ();
417 header = mono_method_get_header (method);
419 max_size = 28 * jit->num_line_numbers;
420 if (max_size > BUFSIZ)
421 ptr = oldptr = g_malloc (max_size);
423 ptr = oldptr = buffer;
425 write_leb128 (jit->prologue_end, ptr, &ptr);
426 write_leb128 (jit->epilogue_begin, ptr, &ptr);
427 write_leb128 (jit->num_line_numbers, ptr, &ptr);
428 for (i = 0; i < jit->num_line_numbers; i++) {
429 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
431 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
432 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
434 last_il_offset = lne->il_offset;
435 last_native_offset = lne->native_offset;
438 write_leb128 (method->wrapper_type, ptr, &ptr);
441 g_assert (size < max_size);
442 total_size = size + sizeof (MonoDebugWrapperData);
444 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
445 // FIXME: Maybe we should print a warning here.
446 // This should only happen for very big methods, for instance
447 // with more than 40.000 line numbers and more than 5.000
449 mono_debugger_unlock ();
453 wrapper = (MonoDebugWrapperData *) allocate_data_item (MONO_DEBUG_DATA_ITEM_WRAPPER, total_size);
455 wrapper->method = method;
456 wrapper->size = total_size;
457 wrapper->code_start = jit->code_start;
458 wrapper->code_size = jit->code_size;
459 wrapper->name = mono_method_full_name (method, TRUE);
461 il_code = mono_method_header_get_code (header, &il_codesize, NULL);
462 wrapper->cil_code = mono_disasm_code (
463 NULL, method, il_code, il_code + il_codesize);
465 memcpy (&wrapper->data, oldptr, size);
467 if (max_size > BUFSIZ)
470 mono_debugger_unlock ();
476 * This is called by the JIT to tell the debugging code about a newly
479 MonoDebugMethodAddress *
480 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
482 MonoDebugMethodAddress *address;
483 guint8 buffer [BUFSIZ];
484 guint8 *ptr, *oldptr;
485 guint32 i, size, total_size, max_size;
486 gint32 last_il_offset = 0, last_native_offset = 0;
487 MonoDebugHandle *handle;
488 MonoDebugMethodInfo *minfo;
489 MethodHashEntry *hash;
491 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
492 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
493 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
494 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
495 (method->wrapper_type != MONO_WRAPPER_NONE)) {
496 mono_debug_add_wrapper (method, jit);
500 mono_debugger_lock ();
502 handle = _mono_debug_get_image (method->klass->image);
503 if (!handle || !handle->symfile || !handle->symfile->offset_table) {
504 mono_debug_add_wrapper (method, jit);
505 mono_debugger_unlock ();
509 minfo = _mono_debug_lookup_method (method);
511 mono_debugger_unlock ();
515 max_size = 24 + 8 * jit->num_line_numbers + 16 * minfo->num_lexical_blocks + 20 * (1 + jit->num_params + jit->num_locals);
516 if (max_size > BUFSIZ)
517 ptr = oldptr = g_malloc (max_size);
519 ptr = oldptr = buffer;
521 write_leb128 (jit->prologue_end, ptr, &ptr);
522 write_leb128 (jit->epilogue_begin, ptr, &ptr);
524 write_leb128 (jit->num_line_numbers, ptr, &ptr);
525 for (i = 0; i < jit->num_line_numbers; i++) {
526 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
528 write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr);
529 write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr);
531 last_il_offset = lne->il_offset;
532 last_native_offset = lne->native_offset;
535 jit->num_lexical_blocks = minfo->num_lexical_blocks;
536 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
537 for (i = 0; i < jit->num_lexical_blocks; i ++) {
538 MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i];
539 MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i];
540 jit_lbe->il_start_offset = read32 (&(minfo_lbe->_start_offset));
541 jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset);
543 jit_lbe->il_end_offset = read32 (&(minfo_lbe->_end_offset));
544 jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset);
548 last_native_offset = 0;
549 write_leb128 (jit->num_lexical_blocks, ptr, &ptr);
550 for (i = 0; i < jit->num_lexical_blocks; i++) {
551 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
553 write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr);
554 write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr);
556 last_il_offset = lbe->il_start_offset;
557 last_native_offset = lbe->native_start_offset;
559 write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr);
560 write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr);
562 last_il_offset = lbe->il_end_offset;
563 last_native_offset = lbe->native_end_offset;
566 *ptr++ = jit->this_var ? 1 : 0;
568 write_variable (jit->this_var, ptr, &ptr);
570 write_leb128 (jit->num_params, ptr, &ptr);
571 for (i = 0; i < jit->num_params; i++)
572 write_variable (&jit->params [i], ptr, &ptr);
574 write_leb128 (jit->num_locals, ptr, &ptr);
575 for (i = 0; i < jit->num_locals; i++)
576 write_variable (&jit->locals [i], ptr, &ptr);
579 g_assert (size < max_size);
580 total_size = size + sizeof (MonoDebugMethodAddress);
582 if (total_size + 9 >= DATA_TABLE_CHUNK_SIZE) {
583 // FIXME: Maybe we should print a warning here.
584 // This should only happen for very big methods, for instance
585 // with more than 40.000 line numbers and more than 5.000
587 mono_debugger_unlock ();
591 address = (MonoDebugMethodAddress *) allocate_data_item (MONO_DEBUG_DATA_ITEM_METHOD, total_size);
593 address->size = total_size;
594 address->symfile_id = handle->index;
595 address->domain_id = mono_domain_get_id (domain);
596 address->method_id = minfo->index;
597 address->code_start = jit->code_start;
598 address->code_size = jit->code_size;
599 address->wrapper_addr = jit->wrapper_addr;
601 memcpy (&address->data, oldptr, size);
603 if (max_size > BUFSIZ)
606 hash = g_new0 (MethodHashEntry, 1);
607 hash->symfile_id = address->symfile_id;
608 hash->domain_id = address->domain_id;
609 hash->method_id = address->method_id;
611 g_hash_table_insert (method_hash, hash, address);
613 mono_debugger_unlock ();
618 static inline guint32
619 read_leb128 (guint8 *ptr, guint8 **rptr)
621 guint32 result = 0, shift = 0;
624 guint8 byte = *ptr++;
626 result |= (byte & 0x7f) << shift;
627 if ((byte & 0x80) == 0)
637 read_sleb128 (guint8 *ptr, guint8 **rptr)
643 guint8 byte = *ptr++;
645 result |= (byte & 0x7f) << shift;
651 if ((shift < 32) && (byte & 0x40))
652 result |= - (1 << shift);
661 read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
663 var->index = read_leb128 (ptr, &ptr);
664 var->offset = read_sleb128 (ptr, &ptr);
665 var->size = read_leb128 (ptr, &ptr);
666 var->begin_scope = read_leb128 (ptr, &ptr);
667 var->end_scope = read_leb128 (ptr, &ptr);
671 MonoDebugMethodJitInfo *
672 mono_debug_read_method (MonoDebugMethodAddress *address)
674 MonoDebugMethodJitInfo *jit;
675 guint32 i, il_offset = 0, native_offset = 0;
681 jit = address->jit = g_new0 (MonoDebugMethodJitInfo, 1);
682 jit->code_start = address->code_start;
683 jit->code_size = address->code_size;
684 jit->wrapper_addr = address->wrapper_addr;
686 ptr = (guint8 *) &address->data;
688 jit->prologue_end = read_leb128 (ptr, &ptr);
689 jit->epilogue_begin = read_leb128 (ptr, &ptr);
691 jit->num_line_numbers = read_leb128 (ptr, &ptr);
692 jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
693 for (i = 0; i < jit->num_line_numbers; i++) {
694 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
696 il_offset += read_sleb128 (ptr, &ptr);
697 native_offset += read_sleb128 (ptr, &ptr);
699 lne->il_offset = il_offset;
700 lne->native_offset = native_offset;
705 jit->num_lexical_blocks = read_leb128 (ptr, &ptr);
706 jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks);
707 for (i = 0; i < jit->num_lexical_blocks; i ++) {
708 MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i];
710 il_offset += read_sleb128 (ptr, &ptr);
711 native_offset += read_sleb128 (ptr, &ptr);
713 lbe->il_start_offset = il_offset;
714 lbe->native_start_offset = native_offset;
716 il_offset += read_sleb128 (ptr, &ptr);
717 native_offset += read_sleb128 (ptr, &ptr);
719 lbe->il_end_offset = il_offset;
720 lbe->native_end_offset = native_offset;
724 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
725 read_variable (jit->this_var, ptr, &ptr);
728 jit->num_params = read_leb128 (ptr, &ptr);
729 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
730 for (i = 0; i < jit->num_params; i++)
731 read_variable (&jit->params [i], ptr, &ptr);
733 jit->num_locals = read_leb128 (ptr, &ptr);
734 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
735 for (i = 0; i < jit->num_locals; i++)
736 read_variable (&jit->locals [i], ptr, &ptr);
742 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit)
745 jit->address->jit = NULL;
747 g_free (jit->line_numbers);
748 g_free (jit->this_var);
749 g_free (jit->params);
750 g_free (jit->locals);
755 * This is called via the `mono_debugger_class_init_func' from mono_class_init() each time
756 * a new class is initialized.
759 mono_debug_start_add_type (MonoClass *klass)
761 MonoDebugHandle *handle;
763 handle = _mono_debug_get_image (klass->image);
769 mono_debug_add_type (MonoClass *klass)
771 MonoDebugHandle *handle;
772 MonoDebugClassEntry *entry;
773 guint8 buffer [BUFSIZ];
774 guint8 *ptr, *oldptr;
775 guint32 size, total_size, max_size;
778 handle = _mono_debug_get_image (klass->image);
782 if (klass->generic_class || klass->rank ||
783 (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
786 max_size = 12 + sizeof (gpointer);
787 if (max_size > BUFSIZ)
788 ptr = oldptr = g_malloc (max_size);
790 ptr = oldptr = buffer;
792 if (klass->valuetype)
793 base_offset = - (int)(sizeof (MonoObject));
795 write_leb128 (klass->type_token, ptr, &ptr);
796 write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
797 WRITE_UNALIGNED (gpointer, ptr, klass);
798 ptr += sizeof (gpointer);
801 g_assert (size < max_size);
802 total_size = size + sizeof (MonoDebugClassEntry);
804 g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
806 entry = (MonoDebugClassEntry *) allocate_data_item (MONO_DEBUG_DATA_ITEM_CLASS, total_size);
808 entry->size = total_size;
809 entry->symfile_id = handle->index;
811 memcpy (&entry->data, oldptr, size);
813 if (max_size > BUFSIZ)
816 mono_debugger_add_type (handle, klass);
819 static MonoDebugMethodJitInfo *
820 find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
822 MethodHashEntry lookup;
823 MonoDebugMethodAddress *address;
825 lookup.symfile_id = minfo->handle->index;
826 lookup.domain_id = mono_domain_get_id (domain);
827 lookup.method_id = minfo->index;
829 address = g_hash_table_lookup (method_hash, &lookup);
833 return mono_debug_read_method (address);
836 MonoDebugMethodJitInfo *
837 mono_debug_find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
839 MonoDebugMethodJitInfo *res;
840 mono_debugger_lock ();
841 res = find_method (minfo, domain);
842 mono_debugger_unlock ();
847 il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32 native_offset)
849 MonoDebugMethodJitInfo *jit;
852 jit = find_method (minfo, domain);
853 if (!jit || !jit->line_numbers)
856 for (i = jit->num_line_numbers - 1; i >= 0; i--) {
857 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
859 if (lne.native_offset <= native_offset)
860 return lne.il_offset;
867 * mono_debug_lookup_source_location:
868 * @address: Native offset within the @method's machine code.
870 * Lookup the source code corresponding to the machine instruction located at
871 * native offset @address within @method.
873 * The returned `MonoDebugSourceLocation' contains both file / line number
874 * information and the corresponding IL offset. It must be freed by
875 * mono_debug_free_source_location().
877 MonoDebugSourceLocation *
878 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
880 MonoDebugMethodInfo *minfo;
881 MonoDebugSourceLocation *location;
884 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
887 mono_debugger_lock ();
888 minfo = _mono_debug_lookup_method (method);
889 if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
890 mono_debugger_unlock ();
894 offset = il_offset_from_address (minfo, domain, address);
896 mono_debugger_unlock ();
900 location = mono_debug_symfile_lookup_location (minfo, offset);
901 mono_debugger_unlock ();
906 * mono_debug_free_source_location:
907 * @location: A `MonoDebugSourceLocation'.
909 * Frees the @location.
912 mono_debug_free_source_location (MonoDebugSourceLocation *location)
915 g_free (location->source_file);
921 * mono_debug_print_stack_frame:
922 * @native_offset: Native offset within the @method's machine code.
924 * Conventient wrapper around mono_debug_lookup_source_location() which can be
925 * used if you only want to use the location to print a stack frame.
928 mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
930 MonoDebugSourceLocation *location;
931 gchar *fname, *ptr, *res;
933 fname = mono_method_full_name (method, TRUE);
934 for (ptr = fname; *ptr; ptr++) {
935 if (*ptr == ':') *ptr = '.';
938 location = mono_debug_lookup_source_location (method, native_offset, domain);
941 res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
946 res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
947 location->source_file, location->row);
950 mono_debug_free_source_location (location);