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 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
->global_data_table
)
295 free_data_table (mono_symbol_table
->global_data_table
);
297 g_free (mono_symbol_table
);
298 mono_symbol_table
= NULL
;
302 mono_debug_domain_create (MonoDomain
*domain
)
304 MonoDebugDataTable
*table
;
306 if (!mono_debug_initialized
)
309 mono_debugger_lock ();
311 table
= create_data_table (domain
);
313 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE
, (guint64
) (gsize
) table
,
314 mono_domain_get_id (domain
));
316 mono_debugger_unlock ();
320 mono_debug_domain_unload (MonoDomain
*domain
)
322 MonoDebugDataTable
*table
;
324 if (!mono_debug_initialized
)
327 mono_debugger_lock ();
329 table
= g_hash_table_lookup (data_table_hash
, domain
);
331 g_warning (G_STRLOC
": unloading unknown domain %p / %d",
332 domain
, mono_domain_get_id (domain
));
333 mono_debugger_unlock ();
337 mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD
, (guint64
) (gsize
) table
,
338 mono_domain_get_id (domain
));
340 g_hash_table_remove (data_table_hash
, domain
);
342 mono_debugger_unlock ();
346 * LOCKING: Assumes the debug lock is held.
348 static MonoDebugHandle
*
349 _mono_debug_get_image (MonoImage
*image
)
351 return g_hash_table_lookup (mono_debug_handles
, image
);
355 mono_debug_close_image (MonoImage
*image
)
357 MonoDebugHandle
*handle
;
359 if (!mono_debug_initialized
)
362 mono_debugger_lock ();
364 handle
= _mono_debug_get_image (image
);
366 mono_debugger_unlock ();
370 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE
, (guint64
) (gsize
) handle
,
373 mono_debug_list_remove (&mono_symbol_table
->symbol_files
, handle
);
374 g_hash_table_remove (mono_debug_handles
, image
);
376 mono_debugger_unlock ();
379 static MonoDebugHandle
*
380 mono_debug_open_image (MonoImage
*image
, const guint8
*raw_contents
, int size
)
382 MonoDebugHandle
*handle
;
384 if (mono_image_is_dynamic (image
))
387 mono_debugger_lock ();
389 handle
= _mono_debug_get_image (image
);
390 if (handle
!= NULL
) {
391 mono_debugger_unlock ();
395 handle
= g_new0 (MonoDebugHandle
, 1);
396 handle
->index
= ++next_symbol_file_id
;
398 handle
->image
= image
;
399 mono_image_addref (image
);
400 handle
->image_file
= g_strdup (mono_image_get_filename (image
));
402 handle
->type_table
= create_data_table (NULL
);
404 handle
->symfile
= mono_debug_open_mono_symbols (
405 handle
, raw_contents
, size
, _mono_debug_using_mono_debugger
);
407 mono_debug_list_add (&mono_symbol_table
->symbol_files
, handle
);
409 g_hash_table_insert (mono_debug_handles
, image
, handle
);
411 if (mono_symbol_table
->corlib
)
412 mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE
,
413 (guint64
) (gsize
) handle
, 0);
415 mono_debugger_unlock ();
421 mono_debug_add_assembly (MonoAssembly
*assembly
, gpointer user_data
)
423 mono_debugger_lock ();
424 mono_debug_open_image (mono_assembly_get_image (assembly
), NULL
, 0);
425 mono_debugger_unlock ();
429 allocate_data_item (MonoDebugDataTable
*table
, MonoDebugDataItemType type
, guint32 size
)
434 size
= ALIGN_TO (size
, sizeof (gpointer
));
436 if (size
+ 16 < DATA_TABLE_CHUNK_SIZE
)
437 chunk_size
= DATA_TABLE_CHUNK_SIZE
;
439 chunk_size
= size
+ 16;
441 g_assert (table
->current_chunk
->current_offset
== table
->current_chunk
->allocated_size
);
443 if (table
->current_chunk
->allocated_size
+ size
+ 8 >= table
->current_chunk
->total_size
) {
444 MonoDebugDataChunk
*new_chunk
;
446 new_chunk
= g_malloc0 (sizeof (MonoDebugDataChunk
) + chunk_size
);
447 new_chunk
->total_size
= chunk_size
;
449 table
->current_chunk
->next
= new_chunk
;
450 table
->current_chunk
= new_chunk
;
453 data
= &table
->current_chunk
->data
[table
->current_chunk
->allocated_size
];
454 table
->current_chunk
->allocated_size
+= size
+ 8;
456 * ((guint32
*) data
) = size
;
458 * ((guint32
*) data
) = type
;
464 write_data_item (MonoDebugDataTable
*table
, const guint8
*data
)
466 MonoDebugDataChunk
*current_chunk
= table
->current_chunk
;
467 guint32 size
= * ((guint32
*) (data
- 8));
469 g_assert (current_chunk
->current_offset
+ size
+ 8 == current_chunk
->allocated_size
);
470 current_chunk
->current_offset
= current_chunk
->allocated_size
;
473 struct LookupMethodData
475 MonoDebugMethodInfo
*minfo
;
480 lookup_method_func (gpointer key
, gpointer value
, gpointer user_data
)
482 MonoDebugHandle
*handle
= (MonoDebugHandle
*) value
;
483 struct LookupMethodData
*data
= (struct LookupMethodData
*) user_data
;
489 data
->minfo
= mono_debug_symfile_lookup_method (handle
, data
->method
);
492 static MonoDebugMethodInfo
*
493 _mono_debug_lookup_method (MonoMethod
*method
)
495 struct LookupMethodData data
;
498 data
.method
= method
;
500 if (!mono_debug_handles
)
503 g_hash_table_foreach (mono_debug_handles
, lookup_method_func
, &data
);
508 * mono_debug_lookup_method:
510 * Lookup symbol file information for the method @method. The returned
511 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
512 * mono_debug_symfile_lookup_location().
514 MonoDebugMethodInfo
*
515 mono_debug_lookup_method (MonoMethod
*method
)
517 MonoDebugMethodInfo
*minfo
;
519 mono_debugger_lock ();
520 minfo
= _mono_debug_lookup_method (method
);
521 mono_debugger_unlock ();
526 write_leb128 (guint32 value
, guint8
*ptr
, guint8
**rptr
)
529 guint8 byte
= value
& 0x7f;
540 write_sleb128 (gint32 value
, guint8
*ptr
, guint8
**rptr
)
545 guint8 byte
= value
& 0x7f;
548 if (((value
== 0) && ((byte
& 0x40) == 0)) || ((value
== -1) && (byte
& 0x40)))
559 write_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
561 write_leb128 (var
->index
, ptr
, &ptr
);
562 write_sleb128 (var
->offset
, ptr
, &ptr
);
563 write_leb128 (var
->size
, ptr
, &ptr
);
564 write_leb128 (var
->begin_scope
, ptr
, &ptr
);
565 write_leb128 (var
->end_scope
, ptr
, &ptr
);
566 WRITE_UNALIGNED (gpointer
, ptr
, var
->type
);
567 ptr
+= sizeof (gpointer
);
571 MonoDebugMethodAddress
*
572 mono_debug_add_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
, MonoDomain
*domain
)
574 MonoMethod
*declaring
;
575 MonoDebugDataTable
*table
;
576 MonoDebugMethodHeader
*header
;
577 MonoDebugMethodAddress
*address
;
578 MonoDebugMethodInfo
*minfo
;
579 MonoDebugHandle
*handle
;
580 guint8 buffer
[BUFSIZ
];
581 guint8
*ptr
, *oldptr
;
582 guint32 i
, size
, total_size
, max_size
;
583 gboolean is_wrapper
= FALSE
;
585 mono_debugger_lock ();
587 table
= lookup_data_table (domain
);
589 handle
= _mono_debug_get_image (method
->klass
->image
);
590 minfo
= _mono_debug_lookup_method (method
);
592 if (!minfo
|| (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
593 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) ||
594 (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
595 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
596 (method
->wrapper_type
!= MONO_WRAPPER_NONE
)) {
600 max_size
= (5 * 5) + 1 + (10 * jit
->num_line_numbers
) +
601 (25 + sizeof (gpointer
)) * (1 + jit
->num_params
+ jit
->num_locals
);
603 if (max_size
> BUFSIZ
)
604 ptr
= oldptr
= g_malloc (max_size
);
606 ptr
= oldptr
= buffer
;
608 write_leb128 (jit
->prologue_end
, ptr
, &ptr
);
609 write_leb128 (jit
->epilogue_begin
, ptr
, &ptr
);
611 write_leb128 (jit
->num_line_numbers
, ptr
, &ptr
);
612 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
613 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
615 write_sleb128 (lne
->il_offset
, ptr
, &ptr
);
616 write_sleb128 (lne
->native_offset
, ptr
, &ptr
);
619 *ptr
++ = jit
->this_var
? 1 : 0;
621 write_variable (jit
->this_var
, ptr
, &ptr
);
623 write_leb128 (jit
->num_params
, ptr
, &ptr
);
624 for (i
= 0; i
< jit
->num_params
; i
++)
625 write_variable (&jit
->params
[i
], ptr
, &ptr
);
627 write_leb128 (jit
->num_locals
, ptr
, &ptr
);
628 for (i
= 0; i
< jit
->num_locals
; i
++)
629 write_variable (&jit
->locals
[i
], ptr
, &ptr
);
632 g_assert (size
< max_size
);
633 total_size
= size
+ sizeof (MonoDebugMethodAddress
);
635 address
= (MonoDebugMethodAddress
*) allocate_data_item (
636 table
, MONO_DEBUG_DATA_ITEM_METHOD
, total_size
);
638 address
->header
.size
= total_size
;
639 address
->header
.symfile_id
= handle
? handle
->index
: 0;
640 address
->header
.domain_id
= mono_domain_get_id (domain
);
641 address
->header
.method_id
= is_wrapper
? 0 : minfo
->index
;
642 address
->header
.method
= method
;
644 address
->code_start
= jit
->code_start
;
645 address
->code_size
= jit
->code_size
;
647 memcpy (&address
->data
, oldptr
, size
);
648 if (max_size
> BUFSIZ
)
651 declaring
= method
->is_inflated
? ((MonoMethodInflated
*) method
)->declaring
: method
;
652 header
= g_hash_table_lookup (table
->method_hash
, declaring
);
655 header
= &address
->header
;
656 g_hash_table_insert (table
->method_hash
, declaring
, header
);
659 MonoDebugWrapperData
*wrapper
;
661 header
->wrapper_data
= wrapper
= g_new0 (MonoDebugWrapperData
, 1);
663 wrapper
->wrapper_type
= method
->wrapper_type
;
664 wrapper
->method_name
= mono_method_full_name (declaring
, TRUE
);
665 wrapper
->obsolete_cil_code
= "";
668 address
->header
.wrapper_data
= header
->wrapper_data
;
669 header
->address_list
= g_slist_prepend (header
->address_list
, address
);
672 g_hash_table_insert (table
->method_address_hash
, method
, address
);
674 write_data_item (table
, (guint8
*) address
);
676 mono_debugger_unlock ();
681 mono_debug_add_delegate_trampoline (gpointer code
, int size
)
683 MonoDebugDelegateTrampolineEntry
*entry
;
685 if (!mono_debug_initialized
)
688 mono_debugger_lock ();
690 entry
= (MonoDebugDelegateTrampolineEntry
*) allocate_data_item (
691 mono_symbol_table
->global_data_table
, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
,
692 sizeof (MonoDebugDelegateTrampolineEntry
));
696 write_data_item (mono_symbol_table
->global_data_table
, (guint8
*) entry
);
698 mono_debugger_unlock ();
701 static inline guint32
702 read_leb128 (guint8
*ptr
, guint8
**rptr
)
704 guint32 result
= 0, shift
= 0;
707 guint8 byte
= *ptr
++;
709 result
|= (byte
& 0x7f) << shift
;
710 if ((byte
& 0x80) == 0)
720 read_sleb128 (guint8
*ptr
, guint8
**rptr
)
726 guint8 byte
= *ptr
++;
728 result
|= (byte
& 0x7f) << shift
;
734 if ((shift
< 32) && (byte
& 0x40))
735 result
|= - (1 << shift
);
744 read_variable (MonoDebugVarInfo
*var
, guint8
*ptr
, guint8
**rptr
)
746 var
->index
= read_leb128 (ptr
, &ptr
);
747 var
->offset
= read_sleb128 (ptr
, &ptr
);
748 var
->size
= read_leb128 (ptr
, &ptr
);
749 var
->begin_scope
= read_leb128 (ptr
, &ptr
);
750 var
->end_scope
= read_leb128 (ptr
, &ptr
);
751 READ_UNALIGNED (gpointer
, ptr
, var
->type
);
752 ptr
+= sizeof (gpointer
);
757 mono_debug_free_method_jit_info (MonoDebugMethodJitInfo
*jit
)
761 g_free (jit
->line_numbers
);
762 g_free (jit
->this_var
);
763 g_free (jit
->params
);
764 g_free (jit
->locals
);
768 static MonoDebugMethodJitInfo
*
769 mono_debug_read_method (MonoDebugMethodAddress
*address
)
771 MonoDebugMethodJitInfo
*jit
;
775 jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
776 jit
->code_start
= address
->code_start
;
777 jit
->code_size
= address
->code_size
;
778 jit
->wrapper_addr
= address
->wrapper_addr
;
780 ptr
= (guint8
*) &address
->data
;
782 jit
->prologue_end
= read_leb128 (ptr
, &ptr
);
783 jit
->epilogue_begin
= read_leb128 (ptr
, &ptr
);
785 jit
->num_line_numbers
= read_leb128 (ptr
, &ptr
);
786 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
787 for (i
= 0; i
< jit
->num_line_numbers
; i
++) {
788 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
790 lne
->il_offset
= read_sleb128 (ptr
, &ptr
);
791 lne
->native_offset
= read_sleb128 (ptr
, &ptr
);
795 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
796 read_variable (jit
->this_var
, ptr
, &ptr
);
799 jit
->num_params
= read_leb128 (ptr
, &ptr
);
800 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
801 for (i
= 0; i
< jit
->num_params
; i
++)
802 read_variable (&jit
->params
[i
], ptr
, &ptr
);
804 jit
->num_locals
= read_leb128 (ptr
, &ptr
);
805 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
806 for (i
= 0; i
< jit
->num_locals
; i
++)
807 read_variable (&jit
->locals
[i
], ptr
, &ptr
);
813 mono_debug_add_type (MonoClass
*klass
)
815 MonoDebugHandle
*handle
;
816 MonoDebugClassEntry
*entry
;
817 guint8 buffer
[BUFSIZ
];
818 guint8
*ptr
, *oldptr
;
819 guint32 size
, total_size
, max_size
;
822 if (klass
->generic_class
|| klass
->rank
||
823 (klass
->byval_arg
.type
== MONO_TYPE_VAR
) || (klass
->byval_arg
.type
== MONO_TYPE_MVAR
))
826 mono_debugger_lock ();
828 handle
= _mono_debug_get_image (klass
->image
);
830 mono_debugger_unlock ();
834 max_size
= 12 + sizeof (gpointer
);
835 if (max_size
> BUFSIZ
)
836 ptr
= oldptr
= g_malloc (max_size
);
838 ptr
= oldptr
= buffer
;
840 if (klass
->valuetype
)
841 base_offset
= - (int)(sizeof (MonoObject
));
843 write_leb128 (klass
->type_token
, ptr
, &ptr
);
844 write_leb128 (klass
->instance_size
+ base_offset
, ptr
, &ptr
);
845 WRITE_UNALIGNED (gpointer
, ptr
, klass
);
846 ptr
+= sizeof (gpointer
);
849 g_assert (size
< max_size
);
850 total_size
= size
+ sizeof (MonoDebugClassEntry
);
852 g_assert (total_size
+ 9 < DATA_TABLE_CHUNK_SIZE
);
854 entry
= (MonoDebugClassEntry
*) allocate_data_item (
855 handle
->type_table
, MONO_DEBUG_DATA_ITEM_CLASS
, total_size
);
857 entry
->size
= total_size
;
859 memcpy (&entry
->data
, oldptr
, size
);
861 write_data_item (handle
->type_table
, (guint8
*) entry
);
863 if (max_size
> BUFSIZ
)
866 mono_debugger_unlock ();
869 static MonoDebugMethodJitInfo
*
870 find_method (MonoMethod
*method
, MonoDomain
*domain
)
872 MonoDebugDataTable
*table
;
873 MonoDebugMethodAddress
*address
;
875 table
= lookup_data_table (domain
);
876 address
= g_hash_table_lookup (table
->method_address_hash
, method
);
881 return mono_debug_read_method (address
);
884 MonoDebugMethodJitInfo
*
885 mono_debug_find_method (MonoMethod
*method
, MonoDomain
*domain
)
887 MonoDebugMethodJitInfo
*res
;
889 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
892 mono_debugger_lock ();
893 res
= find_method (method
, domain
);
894 mono_debugger_unlock ();
898 struct LookupMethodAddressData
901 MonoDebugMethodHeader
*result
;
905 lookup_method_address_func (gpointer key
, gpointer value
, gpointer user_data
)
907 MonoDebugDataTable
*table
= (MonoDebugDataTable
*) value
;
908 struct LookupMethodAddressData
*data
= (struct LookupMethodAddressData
*) user_data
;
909 MonoDebugMethodHeader
*header
;
911 header
= g_hash_table_lookup (table
->method_hash
, data
->method
);
913 data
->result
= header
;
916 MonoDebugMethodAddressList
*
917 mono_debug_lookup_method_addresses (MonoMethod
*method
)
919 MonoDebugMethodAddressList
*info
;
920 MonoDebugMethodHeader
*header
= NULL
;
921 struct LookupMethodAddressData data
;
922 MonoMethod
*declaring
;
927 g_assert ((mono_debug_debugger_version
== 4) || (mono_debug_debugger_version
== 5));
929 mono_debugger_lock ();
931 declaring
= method
->is_inflated
? ((MonoMethodInflated
*) method
)->declaring
: method
;
933 data
.method
= declaring
;
936 g_hash_table_foreach (data_table_hash
, lookup_method_address_func
, &data
);
937 header
= data
.result
;
940 mono_debugger_unlock ();
944 count
= g_slist_length (header
->address_list
) + 1;
945 size
= sizeof (MonoDebugMethodAddressList
) + count
* sizeof (gpointer
);
947 info
= g_malloc0 (size
);
953 WRITE_UNALIGNED (gpointer
, ptr
, header
);
954 ptr
+= sizeof (gpointer
);
956 for (list
= header
->address_list
; list
; list
= list
->next
) {
957 WRITE_UNALIGNED (gpointer
, ptr
, list
->data
);
958 ptr
+= sizeof (gpointer
);
961 mono_debugger_unlock ();
966 il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
968 MonoDebugMethodJitInfo
*jit
;
971 jit
= find_method (method
, domain
);
972 if (!jit
|| !jit
->line_numbers
)
973 goto cleanup_and_fail
;
975 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
976 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
978 if (lne
.native_offset
<= native_offset
) {
979 mono_debug_free_method_jit_info (jit
);
980 return lne
.il_offset
;
985 mono_debug_free_method_jit_info (jit
);
990 * mono_debug_il_offset_from_address:
992 * Compute the IL offset corresponding to NATIVE_OFFSET inside the native
993 * code of METHOD in DOMAIN.
996 mono_debug_il_offset_from_address (MonoMethod
*method
, MonoDomain
*domain
, guint32 native_offset
)
1000 mono_debugger_lock ();
1002 res
= il_offset_from_address (method
, domain
, native_offset
);
1004 mono_debugger_unlock ();
1010 * mono_debug_lookup_source_location:
1011 * @address: Native offset within the @method's machine code.
1013 * Lookup the source code corresponding to the machine instruction located at
1014 * native offset @address within @method.
1016 * The returned `MonoDebugSourceLocation' contains both file / line number
1017 * information and the corresponding IL offset. It must be freed by
1018 * mono_debug_free_source_location().
1020 MonoDebugSourceLocation
*
1021 mono_debug_lookup_source_location (MonoMethod
*method
, guint32 address
, MonoDomain
*domain
)
1023 MonoDebugMethodInfo
*minfo
;
1024 MonoDebugSourceLocation
*location
;
1027 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
1030 mono_debugger_lock ();
1031 minfo
= _mono_debug_lookup_method (method
);
1032 if (!minfo
|| !minfo
->handle
|| !minfo
->handle
->symfile
|| !minfo
->handle
->symfile
->offset_table
) {
1033 mono_debugger_unlock ();
1037 offset
= il_offset_from_address (method
, domain
, address
);
1039 mono_debugger_unlock ();
1043 location
= mono_debug_symfile_lookup_location (minfo
, offset
);
1044 mono_debugger_unlock ();
1049 * mono_debug_lookup_locals:
1051 * Return information about the local variables of MINFO.
1052 * NAMES and INDEXES are set to g_malloc-ed arrays containing the local names and
1054 * Returns: the number of elements placed into the arrays, or -1 if there is no
1055 * local variable info.
1058 mono_debug_lookup_locals (MonoMethod
*method
, char ***names
, int **indexes
)
1060 MonoDebugMethodInfo
*minfo
;
1066 if (mono_debug_format
== MONO_DEBUG_FORMAT_NONE
)
1069 mono_debugger_lock ();
1070 minfo
= _mono_debug_lookup_method (method
);
1071 if (!minfo
|| !minfo
->handle
|| !minfo
->handle
->symfile
|| !minfo
->handle
->symfile
->offset_table
) {
1072 mono_debugger_unlock ();
1076 res
= mono_debug_symfile_lookup_locals (minfo
, names
, indexes
);
1077 mono_debugger_unlock ();
1083 * mono_debug_free_source_location:
1084 * @location: A `MonoDebugSourceLocation'.
1086 * Frees the @location.
1089 mono_debug_free_source_location (MonoDebugSourceLocation
*location
)
1092 g_free (location
->source_file
);
1098 * mono_debug_print_stack_frame:
1099 * @native_offset: Native offset within the @method's machine code.
1101 * Conventient wrapper around mono_debug_lookup_source_location() which can be
1102 * used if you only want to use the location to print a stack frame.
1105 mono_debug_print_stack_frame (MonoMethod
*method
, guint32 native_offset
, MonoDomain
*domain
)
1107 MonoDebugSourceLocation
*location
;
1108 gchar
*fname
, *ptr
, *res
;
1111 fname
= mono_method_full_name (method
, TRUE
);
1112 for (ptr
= fname
; *ptr
; ptr
++) {
1113 if (*ptr
== ':') *ptr
= '.';
1116 location
= mono_debug_lookup_source_location (method
, native_offset
, domain
);
1119 if (mono_debug_initialized
) {
1120 mono_debugger_lock ();
1121 offset
= il_offset_from_address (method
, domain
, native_offset
);
1122 mono_debugger_unlock ();
1128 res
= g_strdup_printf ("at %s <0x%05x>", fname
, native_offset
);
1130 res
= g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname
, offset
, native_offset
);
1135 res
= g_strdup_printf ("at %s [0x%05x] in %s:%d", fname
, location
->il_offset
,
1136 location
->source_file
, location
->row
);
1139 mono_debug_free_source_location (location
);
1144 mono_debug_list_add (MonoDebugList
**list
, gconstpointer data
)
1146 MonoDebugList
*element
, **ptr
;
1148 element
= g_new0 (MonoDebugList
, 1);
1149 element
->data
= data
;
1151 for (ptr
= list
; *ptr
; ptr
= &(*ptr
)->next
)
1158 mono_debug_list_remove (MonoDebugList
**list
, gconstpointer data
)
1160 MonoDebugList
**ptr
;
1161 MonoDebugList
*next
;
1163 for (ptr
= list
; *ptr
; ptr
= &(*ptr
)->next
) {
1164 if ((*ptr
)->data
!= data
)
1167 next
= (*ptr
)->next
;
1174 static gboolean is_attached
= FALSE
;
1177 mono_set_is_debugger_attached (gboolean attached
)
1179 is_attached
= attached
;
1183 mono_is_debugger_attached (void)