5 * Mono Project (http://www.mono-project.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include <mono/metadata/assembly.h>
13 #include <mono/metadata/tabledefs.h>
14 #include <mono/metadata/tokentype.h>
15 #include <mono/metadata/appdomain.h>
16 #include <mono/metadata/class-internals.h>
17 #include <mono/metadata/mono-debug.h>
18 #include <mono/metadata/mono-debug-debugger.h>
19 #include <mono/metadata/mono-endian.h>
22 #define DATA_TABLE_CHUNK_SIZE 16384
24 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
26 #if NO_UNALIGNED_ACCESS
27 #define RETURN_UNALIGNED(type, addr) \
30 memcpy(&val, p + offset, sizeof(val)); \
33 #define WRITE_UNALIGNED(type, addr, val) \
34 memcpy(addr, &val, sizeof(type))
35 #define READ_UNALIGNED(type, addr, val) \
36 memcpy(&val, addr, sizeof(type))
38 #define RETURN_UNALIGNED(type, addr) \
39 return *(type*)(p + offset);
40 #define WRITE_UNALIGNED(type, addr, val) \
41 (*(type *)(addr) = (val))
42 #define READ_UNALIGNED(type, addr, val) \
43 val = (*(type *)(addr))
47 MONO_DEBUG_DATA_ITEM_UNKNOWN
= 0,
48 MONO_DEBUG_DATA_ITEM_CLASS
,
49 MONO_DEBUG_DATA_ITEM_METHOD
,
50 MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
51 } MonoDebugDataItemType
;
53 typedef struct _MonoDebugDataChunk MonoDebugDataChunk
;
55 struct _MonoDebugDataChunk
{
57 guint32 allocated_size
;
58 guint32 current_offset
;
60 MonoDebugDataChunk
*next
;
61 guint8 data
[MONO_ZERO_LEN_ARRAY
];
64 struct _MonoDebugDataTable
{
66 gint32 _dummy
; /* alignment for next field. */
67 MonoDebugDataChunk
*first_chunk
;
68 MonoDebugDataChunk
*current_chunk
;
69 GHashTable
*method_hash
;
70 GHashTable
*method_address_hash
;
74 const gchar
*method_name
;
75 const gchar
*obsolete_cil_code
;
77 } MonoDebugWrapperData
;
84 MonoDebugWrapperData
*wrapper_data
;
87 } MonoDebugMethodHeader
;
89 struct _MonoDebugMethodAddress
{
90 MonoDebugMethodHeader header
;
91 const guint8
*code_start
;
92 const guint8
*wrapper_addr
;
94 guint8 data
[MONO_ZERO_LEN_ARRAY
];
97 struct _MonoDebugClassEntry
{
99 guint8 data
[MONO_ZERO_LEN_ARRAY
];
105 } MonoDebugDelegateTrampolineEntry
;
107 MonoSymbolTable
*mono_symbol_table
= NULL
;
108 MonoDebugFormat mono_debug_format
= MONO_DEBUG_FORMAT_NONE
;
109 gint32 mono_debug_debugger_version
= 5;
110 gint32 _mono_debug_using_mono_debugger
= 0;
112 static gboolean mono_debug_initialized
= FALSE
;
113 static GHashTable
*mono_debug_handles
= NULL
;
115 static GHashTable
*data_table_hash
= NULL
;
116 static int next_symbol_file_id
= 0;
118 static MonoDebugHandle
*mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
);
120 static MonoDebugHandle
*_mono_debug_get_image (MonoImage
*image
);
121 static void mono_debug_add_assembly (MonoAssembly
*assembly
,
123 static void mono_debug_add_type (MonoClass
*klass
);
125 void _mono_debug_init_corlib (MonoDomain
*domain
);
127 extern void (*mono_debugger_class_init_func
) (MonoClass
*klass
);
128 extern void (*mono_debugger_class_loaded_methods_func
) (MonoClass
*klass
);
130 static MonoDebugDataTable
*
131 create_data_table (MonoDomain
*domain
)
133 MonoDebugDataTable
*table
;
134 MonoDebugDataChunk
*chunk
;
136 table
= g_new0 (MonoDebugDataTable
, 1);
137 table
->domain
= domain
? mono_domain_get_id (domain
) : -1;
139 table
->method_address_hash
= g_hash_table_new (NULL
, NULL
);
140 table
->method_hash
= g_hash_table_new (NULL
, NULL
);
142 chunk
= g_malloc0 (sizeof (MonoDebugDataChunk
) + DATA_TABLE_CHUNK_SIZE
);
143 chunk
->total_size
= DATA_TABLE_CHUNK_SIZE
;
145 table
->first_chunk
= table
->current_chunk
= chunk
;
148 mono_debug_list_add (&mono_symbol_table
->data_tables
, table
);
149 g_hash_table_insert (data_table_hash
, domain
, table
);
156 free_header_data (gpointer key
, gpointer value
, gpointer user_data
)
158 MonoDebugMethodHeader
*header
= (MonoDebugMethodHeader
*)value
;
160 if (header
->wrapper_data
) {
161 g_free ((gpointer
)header
->wrapper_data
->method_name
);
162 g_slist_free (header
->address_list
);
163 g_free (header
->wrapper_data
);
168 free_data_table (MonoDebugDataTable
*table
)
170 MonoDebugDataChunk
*chunk
, *next_chunk
;
172 g_hash_table_foreach (table
->method_hash
, free_header_data
, NULL
);
173 g_hash_table_destroy (table
->method_hash
);
174 g_hash_table_destroy (table
->method_address_hash
);
176 table
->method_hash
= NULL
;
177 table
->method_address_hash
= NULL
;
179 chunk
= table
->first_chunk
;
181 next_chunk
= chunk
->next
;
186 table
->first_chunk
= table
->current_chunk
= NULL
;
187 mono_debug_list_remove (&mono_symbol_table
->data_tables
, table
);
191 static MonoDebugDataTable
*
192 lookup_data_table (MonoDomain
*domain
)
194 MonoDebugDataTable
*table
;
196 table
= g_hash_table_lookup (data_table_hash
, domain
);
202 free_debug_handle (MonoDebugHandle
*handle
)
205 mono_debug_close_mono_symbol_file (handle
->symfile
);
206 /* decrease the refcount added with mono_image_addref () */
207 free_data_table (handle
->type_table
);
208 mono_image_close (handle
->image
);
209 g_free (handle
->image_file
);
214 * Initialize debugging support.
216 * This method must be called after loading corlib,
217 * but before opening the application's main assembly because we need to set some
221 mono_debug_init (MonoDebugFormat format
)
223 g_assert (!mono_debug_initialized
);
225 if (_mono_debug_using_mono_debugger
)
226 format
= MONO_DEBUG_FORMAT_DEBUGGER
;
228 mono_debug_initialized
= TRUE
;
229 mono_debug_format
= format
;
231 mono_debugger_initialize (_mono_debug_using_mono_debugger
);
233 mono_debugger_lock ();
235 mono_symbol_table
= g_new0 (MonoSymbolTable
, 1);
236 mono_symbol_table
->magic
= MONO_DEBUGGER_MAGIC
;
237 mono_symbol_table
->version
= MONO_DEBUGGER_MAJOR_VERSION
;
238 mono_symbol_table
->total_size
= sizeof (MonoSymbolTable
);
240 mono_debug_handles
= g_hash_table_new_full
241 (NULL
, NULL
, NULL
, (GDestroyNotify
) free_debug_handle
);
243 data_table_hash
= g_hash_table_new_full (
244 NULL
, NULL
, NULL
, (GDestroyNotify
) free_data_table
);
246 mono_debugger_class_init_func
= mono_debug_add_type
;
247 mono_debugger_class_loaded_methods_func
= mono_debugger_class_initialized
;
248 mono_install_assembly_load_hook (mono_debug_add_assembly
, NULL
);
250 mono_symbol_table
->global_data_table
= create_data_table (NULL
);
252 mono_debugger_unlock ();
256 * INTERNAL USE ONLY !
259 _mono_debug_init_corlib (MonoDomain
*domain
)
261 if (!mono_debug_initialized
)
264 mono_symbol_table
->corlib
= mono_debug_open_image (mono_defaults
.corlib
, NULL
, 0);
265 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB
,
266 (guint64
) (gsize
) mono_symbol_table
->corlib
, 0);
270 mono_debug_open_image_from_memory (MonoImage
*image
, const guint8
*raw_contents
, int size
)
272 mono_debug_open_image (image
, raw_contents
, size
);
277 mono_debug_using_mono_debugger (void)
279 return _mono_debug_using_mono_debugger
;
283 mono_debug_cleanup (void)
285 if (mono_debug_handles
)
286 g_hash_table_destroy (mono_debug_handles
);
287 mono_debug_handles
= NULL
;
289 if (data_table_hash
) {
290 g_hash_table_destroy (data_table_hash
);
291 data_table_hash
= NULL
;
294 if (mono_symbol_table
) {
295 if (mono_symbol_table
->global_data_table
)
296 free_data_table (mono_symbol_table
->global_data_table
);
298 g_free (mono_symbol_table
);
299 mono_symbol_table
= NULL
;
304 mono_debug_domain_create (MonoDomain
*domain
)
306 MonoDebugDataTable
*table
;
308 if (!mono_debug_initialized
)
311 mono_debugger_lock ();
313 table
= create_data_table (domain
);
315 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE
, (guint64
) (gsize
) table
,
316 mono_domain_get_id (domain
));
318 mono_debugger_unlock ();
322 mono_debug_domain_unload (MonoDomain
*domain
)
324 MonoDebugDataTable
*table
;
326 if (!mono_debug_initialized
)
329 mono_debugger_lock ();
331 table
= g_hash_table_lookup (data_table_hash
, domain
);
333 g_warning (G_STRLOC
": unloading unknown domain %p / %d",
334 domain
, mono_domain_get_id (domain
));
335 mono_debugger_unlock ();
339 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD
, (guint64
) (gsize
) table
,
340 mono_domain_get_id (domain
));
342 g_hash_table_remove (data_table_hash
, domain
);
344 mono_debugger_unlock ();
348 * LOCKING: Assumes the debug lock is held.
350 static MonoDebugHandle
*
351 _mono_debug_get_image (MonoImage
*image
)
353 return g_hash_table_lookup (mono_debug_handles
, image
);
357 mono_debug_close_image (MonoImage
*image
)
359 MonoDebugHandle
*handle
;
361 if (!mono_debug_initialized
)
364 mono_debugger_lock ();
366 handle
= _mono_debug_get_image (image
);
368 mono_debugger_unlock ();
372 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE
, (guint64
) (gsize
) handle
,
375 mono_debug_list_remove (&mono_symbol_table
->symbol_files
, handle
);
376 g_hash_table_remove (mono_debug_handles
, image
);
378 mono_debugger_unlock ();
381 static MonoDebugHandle
*
382 mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
)
384 MonoDebugHandle
*handle
;
386 if (mono_image_is_dynamic (image
))
389 mono_debugger_lock ();
391 handle
= _mono_debug_get_image (image
);
392 if (handle
!= NULL
) {
393 mono_debugger_unlock ();
397 handle
= g_new0 (MonoDebugHandle
, 1);
398 handle
->index
= ++next_symbol_file_id
;
400 handle
->image
= image
;
401 mono_image_addref (image
);
402 handle
->image_file
= g_strdup (mono_image_get_filename (image
));
404 handle
->type_table
= create_data_table (NULL
);
406 handle
->symfile
= mono_debug_open_mono_symbols (
407 handle
, raw_contents
, size
, _mono_debug_using_mono_debugger
);
409 mono_debug_list_add (&mono_symbol_table
->symbol_files
, handle
);
411 g_hash_table_insert (mono_debug_handles
, image
, handle
);
413 if (mono_symbol_table
->corlib
)
414 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE
,
415 (guint64
) (gsize
) handle
, 0);
417 mono_debugger_unlock ();
423 mono_debug_add_assembly (MonoAssembly
*assembly
, gpointer user_data
)
425 mono_debugger_lock ();
426 mono_debug_open_image (mono_assembly_get_image (assembly
), NULL
, 0);
427 mono_debugger_unlock ();
431 allocate_data_item (MonoDebugDataTable
*table
, MonoDebugDataItemType type
, guint32 size
)
436 size
= ALIGN_TO (size
, sizeof (gpointer
));
438 if (size
+ 16 < DATA_TABLE_CHUNK_SIZE
)
439 chunk_size
= DATA_TABLE_CHUNK_SIZE
;
441 chunk_size
= size
+ 16;
443 g_assert (table
->current_chunk
->current_offset
== table
->current_chunk
->allocated_size
);
445 if (table
->current_chunk
->allocated_size
+ size
+ 8 >= table
->current_chunk
->total_size
) {
446 MonoDebugDataChunk
*new_chunk
;
448 new_chunk
= g_malloc0 (sizeof (MonoDebugDataChunk
) + chunk_size
);
449 new_chunk
->total_size
= chunk_size
;
451 table
->current_chunk
->next
= new_chunk
;
452 table
->current_chunk
= new_chunk
;
455 data
= &table
->current_chunk
->data
[table
->current_chunk
->allocated_size
];
456 table
->current_chunk
->allocated_size
+= size
+ 8;
458 * ((guint32
*) data
) = size
;
460 * ((guint32
*) data
) = type
;
466 write_data_item (MonoDebugDataTable
*table
, const guint8
*data
)
468 MonoDebugDataChunk
*current_chunk
= table
->current_chunk
;
469 guint32 size
= * ((guint32
*) (data
- 8));
471 g_assert (current_chunk
->current_offset
+ size
+ 8 == current_chunk
->allocated_size
);
472 current_chunk
->current_offset
= current_chunk
->allocated_size
;
475 struct LookupMethodData
477 MonoDebugMethodInfo
*minfo
;
482 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
484 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
485 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
491 data
->minfo
= mono_debug_symfile_lookup_method (handle
, data
->method
);
494 static MonoDebugMethodInfo
*
495 _mono_debug_lookup_method (MonoMethod
*method
)
497 struct LookupMethodData data
;
500 data
.method
= method
;
502 if (!mono_debug_handles
)
505 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
510 * mono_debug_lookup_method:
512 * Lookup symbol file information for the method @method. The returned
513 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
514 * mono_debug_symfile_lookup_location().
516 MonoDebugMethodInfo
*
517 mono_debug_lookup_method (MonoMethod
*method
)
519 MonoDebugMethodInfo
*minfo
;
521 mono_debugger_lock ();
522 minfo
= _mono_debug_lookup_method (method
);
523 mono_debugger_unlock ();
528 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
531 guint8 byte
= value
& 0x7f;
542 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
547 guint8 byte
= value
& 0x7f;
550 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
561 write_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
563 write_leb128 (var
->index
, ptr
, &ptr
);
564 write_sleb128 (var
->offset
, ptr
, &ptr
);
565 write_leb128 (var
->size
, ptr
, &ptr
);
566 write_leb128 (var
->begin_scope
, ptr
, &ptr
);
567 write_leb128 (var
->end_scope
, ptr
, &ptr
);
568 WRITE_UNALIGNED (gpointer
, ptr
, var
->type
);
569 ptr
+= sizeof (gpointer
);
573 MonoDebugMethodAddress
*
574 mono_debug_add_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
, MonoDomain
*domain
)
576 MonoMethod
*declaring
;
577 MonoDebugDataTable
*table
;
578 MonoDebugMethodHeader
*header
;
579 MonoDebugMethodAddress
*address
;
580 MonoDebugMethodInfo
*minfo
;
581 MonoDebugHandle
*handle
;
582 guint8 buffer
[BUFSIZ
];
583 guint8
*ptr
, *oldptr
;
584 guint32 i
, size
, total_size
, max_size
;
585 gboolean is_wrapper
= FALSE
;
587 mono_debugger_lock ();
589 table
= lookup_data_table (domain
);
591 handle
= _mono_debug_get_image (method
->klass
->image
);
592 minfo
= _mono_debug_lookup_method (method
);
594 if (!minfo
|| (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
595 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) ||
596 (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
597 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
598 (method
->wrapper_type
!= MONO_WRAPPER_NONE
)) {
602 max_size
= (5 * 5) + 1 + (10 * jit
->num_line_numbers
) +
603 (25 + sizeof (gpointer
)) * (1 + jit
->num_params
+ jit
->num_locals
);
605 if (max_size
> BUFSIZ
)
606 ptr
= oldptr
= g_malloc (max_size
);
608 ptr
= oldptr
= buffer
;
610 write_leb128 (jit
->prologue_end
, ptr
, &ptr
);
611 write_leb128 (jit
->epilogue_begin
, ptr
, &ptr
);
613 write_leb128 (jit
->num_line_numbers
, ptr
, &ptr
);
614 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
615 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
617 write_sleb128 (lne
->il_offset
, ptr
, &ptr
);
618 write_sleb128 (lne
->native_offset
, ptr
, &ptr
);
621 *ptr
++ = jit
->this_var
? 1 : 0;
623 write_variable (jit
->this_var
, ptr
, &ptr
);
625 write_leb128 (jit
->num_params
, ptr
, &ptr
);
626 for (i
= 0; i
< jit
->num_params
; i
++)
627 write_variable (&jit
->params
[i
], ptr
, &ptr
);
629 write_leb128 (jit
->num_locals
, ptr
, &ptr
);
630 for (i
= 0; i
< jit
->num_locals
; i
++)
631 write_variable (&jit
->locals
[i
], ptr
, &ptr
);
634 g_assert (size
< max_size
);
635 total_size
= size
+ sizeof (MonoDebugMethodAddress
);
637 address
= (MonoDebugMethodAddress
*) allocate_data_item (
638 table
, MONO_DEBUG_DATA_ITEM_METHOD
, total_size
);
640 address
->header
.size
= total_size
;
641 address
->header
.symfile_id
= handle
? handle
->index
: 0;
642 address
->header
.domain_id
= mono_domain_get_id (domain
);
643 address
->header
.method_id
= is_wrapper
? 0 : minfo
->index
;
644 address
->header
.method
= method
;
646 address
->code_start
= jit
->code_start
;
647 address
->code_size
= jit
->code_size
;
649 memcpy (&address
->data
, oldptr
, size
);
650 if (max_size
> BUFSIZ
)
653 declaring
= method
->is_inflated
? ((MonoMethodInflated
*) method
)->declaring
: method
;
654 header
= g_hash_table_lookup (table
->method_hash
, declaring
);
657 header
= &address
->header
;
658 g_hash_table_insert (table
->method_hash
, declaring
, header
);
661 MonoDebugWrapperData
*wrapper
;
663 header
->wrapper_data
= wrapper
= g_new0 (MonoDebugWrapperData
, 1);
665 wrapper
->wrapper_type
= method
->wrapper_type
;
666 wrapper
->method_name
= mono_method_full_name (declaring
, TRUE
);
667 wrapper
->obsolete_cil_code
= "";
670 address
->header
.wrapper_data
= header
->wrapper_data
;
671 header
->address_list
= g_slist_prepend (header
->address_list
, address
);
674 g_hash_table_insert (table
->method_address_hash
, method
, address
);
676 write_data_item (table
, (guint8
*) address
);
678 mono_debugger_unlock ();
683 mono_debug_add_delegate_trampoline (gpointer code
, int size
)
685 MonoDebugDelegateTrampolineEntry
*entry
;
687 if (!mono_debug_initialized
)
690 mono_debugger_lock ();
692 entry
= (MonoDebugDelegateTrampolineEntry
*) allocate_data_item (
693 mono_symbol_table
->global_data_table
, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
,
694 sizeof (MonoDebugDelegateTrampolineEntry
));
698 write_data_item (mono_symbol_table
->global_data_table
, (guint8
*) entry
);
700 mono_debugger_unlock ();
703 static inline guint32
704 read_leb128 (guint8
*ptr
, guint8
**rptr
)
706 guint32 result
= 0, shift
= 0;
709 guint8 byte
= *ptr
++;
711 result
|= (byte
& 0x7f) << shift
;
712 if ((byte
& 0x80) == 0)
722 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
728 guint8 byte
= *ptr
++;
730 result
|= (byte
& 0x7f) << shift
;
736 if ((shift
< 32) && (byte
& 0x40))
737 result
|= - (1 << shift
);
746 read_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
748 var
->index
= read_leb128 (ptr
, &ptr
);
749 var
->offset
= read_sleb128 (ptr
, &ptr
);
750 var
->size
= read_leb128 (ptr
, &ptr
);
751 var
->begin_scope
= read_leb128 (ptr
, &ptr
);
752 var
->end_scope
= read_leb128 (ptr
, &ptr
);
753 READ_UNALIGNED (gpointer
, ptr
, var
->type
);
754 ptr
+= sizeof (gpointer
);
759 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
763 g_free (jit
->line_numbers
);
764 g_free (jit
->this_var
);
765 g_free (jit
->params
);
766 g_free (jit
->locals
);
770 static MonoDebugMethodJitInfo
*
771 mono_debug_read_method (MonoDebugMethodAddress
*address
)
773 MonoDebugMethodJitInfo
*jit
;
777 jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
778 jit
->code_start
= address
->code_start
;
779 jit
->code_size
= address
->code_size
;
780 jit
->wrapper_addr
= address
->wrapper_addr
;
782 ptr
= (guint8
*) &address
->data
;
784 jit
->prologue_end
= read_leb128 (ptr
, &ptr
);
785 jit
->epilogue_begin
= read_leb128 (ptr
, &ptr
);
787 jit
->num_line_numbers
= read_leb128 (ptr
, &ptr
);
788 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
789 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
790 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
792 lne
->il_offset
= read_sleb128 (ptr
, &ptr
);
793 lne
->native_offset
= read_sleb128 (ptr
, &ptr
);
797 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
798 read_variable (jit
->this_var
, ptr
, &ptr
);
801 jit
->num_params
= read_leb128 (ptr
, &ptr
);
802 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
803 for (i
= 0; i
< jit
->num_params
; i
++)
804 read_variable (&jit
->params
[i
], ptr
, &ptr
);
806 jit
->num_locals
= read_leb128 (ptr
, &ptr
);
807 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
808 for (i
= 0; i
< jit
->num_locals
; i
++)
809 read_variable (&jit
->locals
[i
], ptr
, &ptr
);
815 mono_debug_add_type (MonoClass
*klass
)
817 MonoDebugHandle
*handle
;
818 MonoDebugClassEntry
*entry
;
819 guint8 buffer
[BUFSIZ
];
820 guint8
*ptr
, *oldptr
;
821 guint32 size
, total_size
, max_size
;
824 if (klass
->generic_class
|| klass
->rank
||
825 (klass
->byval_arg
.type
== MONO_TYPE_VAR
) || (klass
->byval_arg
.type
== MONO_TYPE_MVAR
))
828 mono_debugger_lock ();
830 handle
= _mono_debug_get_image (klass
->image
);
832 mono_debugger_unlock ();
836 max_size
= 12 + sizeof (gpointer
);
837 if (max_size
> BUFSIZ
)
838 ptr
= oldptr
= g_malloc (max_size
);
840 ptr
= oldptr
= buffer
;
842 if (klass
->valuetype
)
843 base_offset
= - (int)(sizeof (MonoObject
));
845 write_leb128 (klass
->type_token
, ptr
, &ptr
);
846 write_leb128 (klass
->instance_size
+ base_offset
, ptr
, &ptr
);
847 WRITE_UNALIGNED (gpointer
, ptr
, klass
);
848 ptr
+= sizeof (gpointer
);
851 g_assert (size
< max_size
);
852 total_size
= size
+ sizeof (MonoDebugClassEntry
);
854 g_assert (total_size
+ 9 < DATA_TABLE_CHUNK_SIZE
);
856 entry
= (MonoDebugClassEntry
*) allocate_data_item (
857 handle
->type_table
, MONO_DEBUG_DATA_ITEM_CLASS
, total_size
);
859 entry
->size
= total_size
;
861 memcpy (&entry
->data
, oldptr
, size
);
863 write_data_item (handle
->type_table
, (guint8
*) entry
);
865 if (max_size
> BUFSIZ
)
868 mono_debugger_unlock ();
871 static MonoDebugMethodJitInfo
*
872 find_method (MonoMethod
*method
, MonoDomain
*domain
)
874 MonoDebugDataTable
*table
;
875 MonoDebugMethodAddress
*address
;
877 table
= lookup_data_table (domain
);
878 address
= g_hash_table_lookup (table
->method_address_hash
, method
);
883 return mono_debug_read_method (address
);
886 MonoDebugMethodJitInfo
*
887 mono_debug_find_method (MonoMethod
*method
, MonoDomain
*domain
)
889 MonoDebugMethodJitInfo
*res
;
891 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
894 mono_debugger_lock ();
895 res
= find_method (method
, domain
);
896 mono_debugger_unlock ();
900 struct LookupMethodAddressData
903 MonoDebugMethodHeader
*result
;
907 lookup_method_address_func (gpointer key
, gpointer value
, gpointer user_data
)
909 MonoDebugDataTable
*table
= (MonoDebugDataTable
*) value
;
910 struct LookupMethodAddressData
*data
= (struct LookupMethodAddressData
*) user_data
;
911 MonoDebugMethodHeader
*header
;
913 header
= g_hash_table_lookup (table
->method_hash
, data
->method
);
915 data
->result
= header
;
918 MonoDebugMethodAddressList
*
919 mono_debug_lookup_method_addresses (MonoMethod
*method
)
921 MonoDebugMethodAddressList
*info
;
922 MonoDebugMethodHeader
*header
= NULL
;
923 struct LookupMethodAddressData data
;
924 MonoMethod
*declaring
;
929 g_assert ((mono_debug_debugger_version
== 4) || (mono_debug_debugger_version
== 5));
931 mono_debugger_lock ();
933 declaring
= method
->is_inflated
? ((MonoMethodInflated
*) method
)->declaring
: method
;
935 data
.method
= declaring
;
938 g_hash_table_foreach (data_table_hash
, lookup_method_address_func
, &data
);
939 header
= data
.result
;
942 mono_debugger_unlock ();
946 count
= g_slist_length (header
->address_list
) + 1;
947 size
= sizeof (MonoDebugMethodAddressList
) + count
* sizeof (gpointer
);
949 info
= g_malloc0 (size
);
955 WRITE_UNALIGNED (gpointer
, ptr
, header
);
956 ptr
+= sizeof (gpointer
);
958 for (list
= header
->address_list
; list
; list
= list
->next
) {
959 WRITE_UNALIGNED (gpointer
, ptr
, list
->data
);
960 ptr
+= sizeof (gpointer
);
963 mono_debugger_unlock ();
968 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
970 MonoDebugMethodJitInfo
*jit
;
973 jit
= find_method (method
, domain
);
974 if (!jit
|| !jit
->line_numbers
)
975 goto cleanup_and_fail
;
977 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
978 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
980 if (lne
.native_offset
<= native_offset
) {
981 mono_debug_free_method_jit_info (jit
);
982 return lne
.il_offset
;
987 mono_debug_free_method_jit_info (jit
);
992 * mono_debug_il_offset_from_address:
994 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
995 * code of METHOD in DOMAIN.
998 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
1002 mono_debugger_lock ();
1004 res
= il_offset_from_address (method
, domain
, native_offset
);
1006 mono_debugger_unlock ();
1012 * mono_debug_lookup_source_location:
1013 * @address: Native offset within the @method's machine code.
1015 * Lookup the source code corresponding to the machine instruction located at
1016 * native offset @address within @method.
1018 * The returned `MonoDebugSourceLocation' contains both file / line number
1019 * information and the corresponding IL offset. It must be freed by
1020 * mono_debug_free_source_location().
1022 MonoDebugSourceLocation
*
1023 mono_debug_lookup_source_location (MonoMethod
*method
, guint32 address
, MonoDomain
*domain
)
1025 MonoDebugMethodInfo
*minfo
;
1026 MonoDebugSourceLocation
*location
;
1029 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
1032 mono_debugger_lock ();
1033 minfo
= _mono_debug_lookup_method (method
);
1034 if (!minfo
|| !minfo
->handle
|| !minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
)) {
1035 mono_debugger_unlock ();
1039 offset
= il_offset_from_address (method
, domain
, address
);
1041 mono_debugger_unlock ();
1045 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
1046 mono_debugger_unlock ();
1051 * mono_debug_lookup_locals:
1053 * Return information about the local variables of MINFO.
1054 * The result should be freed using mono_debug_symfile_free_locals ().
1056 MonoDebugLocalsInfo
*
1057 mono_debug_lookup_locals (MonoMethod
*method
)
1059 MonoDebugMethodInfo
*minfo
;
1060 MonoDebugLocalsInfo
*res
;
1062 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
1065 mono_debugger_lock ();
1066 minfo
= _mono_debug_lookup_method (method
);
1067 if (!minfo
|| !minfo
->handle
|| !minfo
->handle
->symfile
|| !mono_debug_symfile_is_loaded (minfo
->handle
->symfile
)) {
1068 mono_debugger_unlock ();
1072 res
= mono_debug_symfile_lookup_locals (minfo
);
1073 mono_debugger_unlock ();
1079 * mono_debug_free_source_location:
1080 * @location: A `MonoDebugSourceLocation'.
1082 * Frees the @location.
1085 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
1088 g_free (location
->source_file
);
1094 * mono_debug_print_stack_frame:
1095 * @native_offset: Native offset within the @method's machine code.
1097 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1098 * used if you only want to use the location to print a stack frame.
1101 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
1103 MonoDebugSourceLocation
*location
;
1104 gchar
*fname
, *ptr
, *res
;
1107 fname
= mono_method_full_name (method
, TRUE
);
1108 for (ptr
= fname
; *ptr
; ptr
++) {
1109 if (*ptr
== ':') *ptr
= '.';
1112 location
= mono_debug_lookup_source_location (method
, native_offset
, domain
);
1115 if (mono_debug_initialized
) {
1116 mono_debugger_lock ();
1117 offset
= il_offset_from_address (method
, domain
, native_offset
);
1118 mono_debugger_unlock ();
1124 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
1126 res
= g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname
, offset
, native_offset
);
1131 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
1132 location
->source_file
, location
->row
);
1135 mono_debug_free_source_location (location
);
1140 mono_debug_list_add (MonoDebugList
**list
, gconstpointer data
)
1142 MonoDebugList
*element
, **ptr
;
1144 element
= g_new0 (MonoDebugList
, 1);
1145 element
->data
= data
;
1147 for (ptr
= list
; *ptr
; ptr
= &(*ptr
)->next
)
1154 mono_debug_list_remove (MonoDebugList
**list
, gconstpointer data
)
1156 MonoDebugList
**ptr
;
1157 MonoDebugList
*next
;
1159 for (ptr
= list
; *ptr
; ptr
= &(*ptr
)->next
) {
1160 if ((*ptr
)->data
!= data
)
1163 next
= (*ptr
)->next
;
1170 static gboolean is_attached
= FALSE
;
1173 mono_set_is_debugger_attached (gboolean attached
)
1175 is_attached
= attached
;
1179 mono_is_debugger_attached (void)