4 #include <mono/metadata/assembly.h>
5 #include <mono/metadata/metadata.h>
6 #include <mono/metadata/tabledefs.h>
7 #include <mono/metadata/tokentype.h>
8 #include <mono/metadata/appdomain.h>
9 #include <mono/metadata/gc-internal.h>
10 #include <mono/os/gc_wrapper.h>
11 #include <mono/metadata/object-internals.h>
12 #include <mono/metadata/class-internals.h>
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/mono-debug.h>
15 #include <mono/metadata/mono-debug-debugger.h>
16 #include <mono/metadata/mono-endian.h>
18 #define SYMFILE_TABLE_CHUNK_SIZE 16
19 #define RANGE_TABLE_CHUNK_SIZE 256
20 #define CLASS_TABLE_CHUNK_SIZE 256
21 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
22 #define TYPE_TABLE_CHUNK_SIZE 65536
23 #define MISC_TABLE_PTR_CHUNK_SIZE 256
24 #define MISC_TABLE_CHUNK_SIZE 65536
26 static guint32 debugger_lock_level
= 0;
27 static CRITICAL_SECTION debugger_lock_mutex
;
28 static gboolean mono_debugger_initialized
= FALSE
;
29 static MonoObject
*last_exception
= NULL
;
31 static gboolean must_reload_symtabs
= FALSE
;
32 static gboolean builtin_types_initialized
= FALSE
;
34 static GHashTable
*images
= NULL
;
35 static GHashTable
*type_table
= NULL
;
36 static GHashTable
*misc_table
= NULL
;
37 static GHashTable
*class_table
= NULL
;
38 static GHashTable
*class_info_table
= NULL
;
40 static MonoDebuggerRangeInfo
*allocate_range_entry (MonoDebuggerSymbolFile
*symfile
);
41 static MonoDebuggerClassInfo
*allocate_class_entry (MonoDebuggerSymbolFile
*symfile
);
42 static guint32
allocate_type_entry (MonoDebuggerSymbolTable
*table
, guint32 size
, guint8
**ptr
);
43 static guint32
write_type (MonoDebuggerSymbolTable
*table
, MonoType
*type
);
44 static guint32
do_write_class (MonoDebuggerSymbolTable
*table
, MonoClass
*klass
,
45 MonoDebuggerClassInfo
*cinfo
);
46 static guint32
write_class (MonoDebuggerSymbolTable
*table
, MonoClass
*klass
);
48 MonoDebuggerSymbolTable
*mono_debugger_symbol_table
= NULL
;
49 void (*mono_debugger_event_handler
) (MonoDebuggerEvent event
, gpointer data
, guint32 arg
) = NULL
;
51 #define WRITE_UINT32(ptr,value) G_STMT_START { \
52 * ((guint32 *) ptr) = value; \
56 #define WRITE_POINTER(ptr,value) G_STMT_START { \
57 * ((gpointer *) ptr) = (gpointer) (value); \
58 ptr += sizeof (gpointer); \
61 #define WRITE_STRING(ptr,value) G_STMT_START { \
62 memcpy (ptr, value, strlen (value)+1); \
63 ptr += strlen (value)+1; \
67 gpointer stack_pointer
;
68 MonoObject
*exception_obj
;
70 } MonoDebuggerExceptionInfo
;
72 #ifndef PLATFORM_WIN32
74 MonoDebuggerIOLayer mono_debugger_io_layer
= {
75 InitializeCriticalSection
, DeleteCriticalSection
, TryEnterCriticalSection
,
76 EnterCriticalSection
, LeaveCriticalSection
, WaitForSingleObjectEx
, SignalObjectAndWait
,
77 WaitForMultipleObjectsEx
, CreateSemaphore
, ReleaseSemaphore
, CreateThread
,
84 mono_debugger_lock (void)
86 if (!mono_debugger_initialized
) {
87 debugger_lock_level
++;
91 EnterCriticalSection (&debugger_lock_mutex
);
92 debugger_lock_level
++;
96 mono_debugger_unlock (void)
98 g_assert (debugger_lock_level
> 0);
100 if (!mono_debugger_initialized
) {
101 debugger_lock_level
--;
105 if (debugger_lock_level
== 1) {
106 if (must_reload_symtabs
) {
107 mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS
, NULL
, 0);
108 must_reload_symtabs
= FALSE
;
112 debugger_lock_level
--;
113 LeaveCriticalSection (&debugger_lock_mutex
);
116 static MonoDebuggerSymbolFile
*
117 allocate_symbol_file_entry (MonoDebuggerSymbolTable
*table
)
119 MonoDebuggerSymbolFile
*symfile
;
121 if (!table
->symbol_files
)
122 table
->symbol_files
= g_new0 (MonoDebuggerSymbolFile
*, SYMFILE_TABLE_CHUNK_SIZE
);
123 else if (!((table
->num_symbol_files
+ 1) % SYMFILE_TABLE_CHUNK_SIZE
)) {
124 guint32 chunks
= (table
->num_symbol_files
+ 1) / SYMFILE_TABLE_CHUNK_SIZE
;
125 guint32 size
= sizeof (MonoDebuggerSymbolFile
*) * SYMFILE_TABLE_CHUNK_SIZE
* (chunks
+ 1);
127 table
->symbol_files
= g_realloc (table
->symbol_files
, size
);
130 symfile
= g_new0 (MonoDebuggerSymbolFile
, 1);
131 symfile
->index
= table
->num_symbol_files
;
132 symfile
->range_entry_size
= sizeof (MonoDebuggerRangeInfo
);
133 symfile
->class_entry_size
= sizeof (MonoDebuggerClassInfo
);
134 symfile
->class_table_size
= sizeof (MonoDebuggerClassTable
);
135 table
->symbol_files
[table
->num_symbol_files
++] = symfile
;
140 mono_debugger_initialize (void)
142 MonoDebuggerSymbolTable
*symbol_table
;
144 MONO_GC_REGISTER_ROOT (last_exception
);
146 g_assert (!mono_debugger_initialized
);
148 InitializeCriticalSection (&debugger_lock_mutex
);
149 mono_debugger_initialized
= TRUE
;
151 mono_debugger_lock ();
153 symbol_table
= g_new0 (MonoDebuggerSymbolTable
, 1);
154 symbol_table
->magic
= MONO_DEBUGGER_MAGIC
;
155 symbol_table
->version
= MONO_DEBUGGER_VERSION
;
156 symbol_table
->total_size
= sizeof (MonoDebuggerSymbolTable
);
158 images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
159 type_table
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
160 misc_table
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
161 class_table
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
162 class_info_table
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
164 mono_debugger_symbol_table
= symbol_table
;
166 mono_debugger_unlock ();
169 MonoDebuggerSymbolFile
*
170 mono_debugger_add_symbol_file (MonoDebugHandle
*handle
)
172 MonoDebuggerSymbolFile
*info
;
174 g_assert (mono_debugger_initialized
);
175 mono_debugger_lock ();
177 info
= g_hash_table_lookup (images
, handle
->image
);
179 mono_debugger_unlock ();
183 info
= allocate_symbol_file_entry (mono_debugger_symbol_table
);
184 info
->symfile
= handle
->symfile
;
185 info
->image
= handle
->image
;
186 info
->image_file
= handle
->image_file
;
188 g_hash_table_insert (images
, handle
->image
, info
);
189 mono_debugger_unlock ();
195 write_builtin_type (MonoDebuggerSymbolTable
*table
, MonoDebuggerSymbolFile
*symfile
,
196 MonoClass
*klass
, MonoDebuggerBuiltinTypeInfo
*info
)
198 guint8 buffer
[BUFSIZ
], *ptr
= buffer
;
201 g_assert (!klass
->init_pending
);
202 mono_class_init (klass
);
204 switch (klass
->byval_arg
.type
) {
206 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN
;
207 WRITE_UINT32 (ptr
, 0);
211 case MONO_TYPE_BOOLEAN
:
223 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL
;
224 WRITE_UINT32 (ptr
, klass
->instance_size
- sizeof (MonoObject
));
228 case MONO_TYPE_STRING
: {
231 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_STRING
;
232 WRITE_UINT32 (ptr
, klass
->instance_size
);
234 *ptr
++ = (guint8
*)&string
.length
- (guint8
*)&string
;
235 *ptr
++ = sizeof (string
.length
);
236 *ptr
++ = (guint8
*)&string
.chars
- (guint8
*)&string
;
243 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL
;
244 WRITE_UINT32 (ptr
, sizeof (void *));
248 case MONO_TYPE_VALUETYPE
:
249 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_STRUCT
;
250 WRITE_UINT32 (ptr
, klass
->instance_size
);
254 case MONO_TYPE_CLASS
:
255 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_CLASS
;
256 WRITE_UINT32 (ptr
, klass
->instance_size
);
260 case MONO_TYPE_OBJECT
:
261 g_assert (klass
== mono_defaults
.object_class
);
262 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_OBJECT
;
263 WRITE_UINT32 (ptr
, klass
->instance_size
);
268 g_error (G_STRLOC
": Unknown builtin type %s.%s - %d", klass
->name_space
, klass
->name
, klass
->byval_arg
.type
);
272 info
->type_info
= allocate_type_entry (table
, size
, &info
->type_data
);
273 memcpy (info
->type_data
, buffer
, size
);
275 info
->centry
->info
= g_new0 (MonoDebuggerClassInfo
, 1); //allocate_class_entry (symfile);
276 info
->centry
->info
->klass
= klass
;
278 info
->centry
->info
->token
= klass
->element_class
->type_token
;
279 info
->centry
->info
->rank
= klass
->rank
;
281 info
->centry
->info
->token
= klass
->type_token
;
282 info
->centry
->info
->type_info
= info
->type_info
;
285 static MonoDebuggerBuiltinTypeInfo
*
286 add_builtin_type (MonoDebuggerSymbolFile
*symfile
, MonoClass
*klass
)
288 MonoDebuggerClassEntry
*centry
;
289 MonoDebuggerBuiltinTypeInfo
*info
;
291 centry
= g_new0 (MonoDebuggerClassEntry
, 1);
293 info
= g_new0 (MonoDebuggerBuiltinTypeInfo
, 1);
295 info
->centry
= centry
;
297 g_hash_table_insert (class_info_table
, klass
, centry
);
299 write_builtin_type (mono_debugger_symbol_table
, symfile
, klass
, info
);
304 add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo
*info
)
306 info
->class_info
= do_write_class (mono_debugger_symbol_table
, info
->klass
, NULL
);
307 * (guint32
*) (info
->type_data
+ 5) = info
->class_info
;
311 add_exception_class (MonoDebuggerSymbolFile
*symfile
, MonoException
*exc
)
313 mono_debugger_start_add_type (symfile
, ((MonoObject
*) exc
)->vtable
->klass
);
314 mono_debugger_add_type (symfile
, ((MonoObject
*) exc
)->vtable
->klass
);
317 MonoDebuggerBuiltinTypes
*
318 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile
*symfile
)
320 MonoDebuggerBuiltinTypes
*types
= g_new0 (MonoDebuggerBuiltinTypes
, 1);
323 mono_debugger_symbol_table
->corlib
= symfile
;
324 mono_debugger_symbol_table
->builtin_types
= types
;
326 types
->total_size
= sizeof (MonoDebuggerBuiltinTypes
);
327 types
->type_info_size
= sizeof (MonoDebuggerBuiltinTypeInfo
);
329 types
->object_type
= add_builtin_type (symfile
, mono_defaults
.object_class
);
330 klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "ValueType");
332 types
->valuetype_type
= add_builtin_type (symfile
, klass
);
334 types
->byte_type
= add_builtin_type (symfile
, mono_defaults
.byte_class
);
335 types
->void_type
= add_builtin_type (symfile
, mono_defaults
.void_class
);
336 types
->boolean_type
= add_builtin_type (symfile
, mono_defaults
.boolean_class
);
337 types
->sbyte_type
= add_builtin_type (symfile
, mono_defaults
.sbyte_class
);
338 types
->int16_type
= add_builtin_type (symfile
, mono_defaults
.int16_class
);
339 types
->uint16_type
= add_builtin_type (symfile
, mono_defaults
.uint16_class
);
340 types
->int32_type
= add_builtin_type (symfile
, mono_defaults
.int32_class
);
341 types
->uint32_type
= add_builtin_type (symfile
, mono_defaults
.uint32_class
);
342 types
->int_type
= add_builtin_type (symfile
, mono_defaults
.int_class
);
343 types
->uint_type
= add_builtin_type (symfile
, mono_defaults
.uint_class
);
344 types
->int64_type
= add_builtin_type (symfile
, mono_defaults
.int64_class
);
345 types
->uint64_type
= add_builtin_type (symfile
, mono_defaults
.uint64_class
);
346 types
->single_type
= add_builtin_type (symfile
, mono_defaults
.single_class
);
347 types
->double_type
= add_builtin_type (symfile
, mono_defaults
.double_class
);
348 types
->char_type
= add_builtin_type (symfile
, mono_defaults
.char_class
);
349 types
->string_type
= add_builtin_type (symfile
, mono_defaults
.string_class
);
351 klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "Type");
353 types
->type_type
= add_builtin_type (symfile
, klass
);
355 types
->enum_type
= add_builtin_type (symfile
, mono_defaults
.enum_class
);
356 types
->array_type
= add_builtin_type (symfile
, mono_defaults
.array_class
);
357 types
->exception_type
= add_builtin_type (symfile
, mono_defaults
.exception_class
);
359 add_builtin_type_2 (types
->object_type
);
360 add_builtin_type_2 (types
->valuetype_type
);
362 add_builtin_type_2 (types
->byte_type
);
363 add_builtin_type_2 (types
->void_type
);
364 add_builtin_type_2 (types
->boolean_type
);
365 add_builtin_type_2 (types
->sbyte_type
);
366 add_builtin_type_2 (types
->int16_type
);
367 add_builtin_type_2 (types
->uint16_type
);
368 add_builtin_type_2 (types
->int32_type
);
369 add_builtin_type_2 (types
->uint32_type
);
370 add_builtin_type_2 (types
->int_type
);
371 add_builtin_type_2 (types
->uint_type
);
372 add_builtin_type_2 (types
->int64_type
);
373 add_builtin_type_2 (types
->uint64_type
);
374 add_builtin_type_2 (types
->single_type
);
375 add_builtin_type_2 (types
->double_type
);
376 add_builtin_type_2 (types
->char_type
);
377 add_builtin_type_2 (types
->string_type
);
378 add_builtin_type_2 (types
->type_type
);
380 add_builtin_type_2 (types
->enum_type
);
381 add_builtin_type_2 (types
->array_type
);
382 add_builtin_type_2 (types
->exception_type
);
384 add_exception_class (symfile
, mono_get_exception_divide_by_zero ());
385 add_exception_class (symfile
, mono_get_exception_security ());
386 add_exception_class (symfile
, mono_get_exception_arithmetic ());
387 add_exception_class (symfile
, mono_get_exception_overflow ());
388 add_exception_class (symfile
, mono_get_exception_null_reference ());
389 add_exception_class (symfile
, mono_get_exception_thread_abort ());
390 add_exception_class (symfile
, mono_get_exception_invalid_cast ());
391 add_exception_class (symfile
, mono_get_exception_index_out_of_range ());
392 add_exception_class (symfile
, mono_get_exception_thread_abort ());
393 add_exception_class (symfile
, mono_get_exception_index_out_of_range ());
394 add_exception_class (symfile
, mono_get_exception_array_type_mismatch ());
395 add_exception_class (symfile
, mono_get_exception_missing_method ());
396 add_exception_class (symfile
, mono_get_exception_appdomain_unloaded ());
397 add_exception_class (symfile
, mono_get_exception_stack_overflow ());
399 builtin_types_initialized
= TRUE
;
405 write_class (MonoDebuggerSymbolTable
*table
, MonoClass
*klass
)
407 MonoDebuggerClassEntry
*centry
;
409 centry
= g_hash_table_lookup (class_info_table
, klass
);
411 MonoDebuggerSymbolFile
*symfile
= _mono_debugger_get_symfile (klass
->image
);
414 mono_debugger_start_add_type (symfile
, klass
);
415 centry
= g_hash_table_lookup (class_info_table
, klass
);
420 g_assert (centry
->info
->type_info
);
421 return centry
->info
->type_info
;
424 if (!centry
->type_reference
) {
427 centry
->type_reference
= allocate_type_entry (table
, 5, &ptr
);
429 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_REFERENCE
;
430 WRITE_POINTER (ptr
, klass
);
433 return centry
->type_reference
;
437 mono_debugger_start_add_type (MonoDebuggerSymbolFile
*symfile
, MonoClass
*klass
)
439 MonoDebuggerClassEntry
*centry
;
441 mono_debugger_lock ();
442 centry
= g_hash_table_lookup (class_info_table
, klass
);
444 mono_debugger_unlock ();
448 centry
= g_new0 (MonoDebuggerClassEntry
, 1);
449 g_hash_table_insert (class_info_table
, klass
, centry
);
450 mono_debugger_unlock ();
454 mono_debugger_add_type (MonoDebuggerSymbolFile
*symfile
, MonoClass
*klass
)
456 MonoDebuggerClassEntry
*centry
;
458 mono_debugger_lock ();
459 centry
= g_hash_table_lookup (class_info_table
, klass
);
463 mono_debugger_unlock ();
467 centry
->info
= allocate_class_entry (symfile
);
468 centry
->info
->klass
= klass
;
470 centry
->info
->token
= klass
->element_class
->type_token
;
471 centry
->info
->rank
= klass
->rank
;
473 centry
->info
->token
= klass
->type_token
;
475 do_write_class (mono_debugger_symbol_table
, klass
, centry
->info
);
477 g_assert (centry
->info
&& centry
->info
->type_info
);
479 symfile
->generation
++;
480 must_reload_symtabs
= TRUE
;
482 mono_debugger_unlock ();
486 mono_debugger_add_method (MonoDebuggerSymbolFile
*symfile
, MonoDebugMethodInfo
*minfo
,
487 MonoDebugMethodJitInfo
*jit
)
489 MonoSymbolFileMethodAddress
*address
;
490 MonoSymbolFileLexicalBlockEntry
*block
;
491 MonoDebugVarInfo
*var_table
;
492 MonoDebuggerRangeInfo
*range
;
493 MonoMethodHeader
*header
;
494 guint32 size
, num_variables
, variable_size
, variable_offset
;
495 guint32 type_size
, type_offset
, *type_index_table
, has_this
;
496 guint32 line_size
= 0, line_offset
= 0, block_offset
, block_size
;
497 MonoDebugLexicalBlockEntry
*block_table
;
498 MonoDebugLineNumberEntry
*line_table
;
503 if (!symfile
->symfile
->method_hash
)
506 header
= ((MonoMethodNormal
*) minfo
->method
)->header
;
508 symfile
->generation
++;
510 size
= sizeof (MonoSymbolFileMethodAddress
);
512 num_variables
= jit
->num_params
+ read32(&(minfo
->entry
->_num_locals
));
513 has_this
= jit
->this_var
!= NULL
;
515 variable_size
= (num_variables
+ has_this
) * sizeof (MonoDebugVarInfo
);
516 variable_offset
= size
;
517 size
+= variable_size
;
519 type_size
= (num_variables
+ 1) * sizeof (gpointer
);
523 if (jit
->line_numbers
) {
525 line_size
= jit
->line_numbers
->len
* sizeof (MonoDebugLineNumberEntry
);
529 block_size
= read32(&(minfo
->entry
->_num_lexical_blocks
)) * sizeof (MonoSymbolFileLexicalBlockEntry
);
533 address
= g_malloc0 (size
);
534 ptr
= (guint8
*) address
;
536 block
= (MonoSymbolFileLexicalBlockEntry
*)
537 (symfile
->symfile
->raw_contents
+ read32(&(minfo
->entry
->_lexical_block_table_offset
)));
538 block_table
= (MonoDebugLexicalBlockEntry
*) (ptr
+ block_offset
);
540 for (i
= 0; i
< read32(&(minfo
->entry
->_num_lexical_blocks
)); i
++, block
++) {
541 block_table
[i
].start_address
= _mono_debug_address_from_il_offset (jit
, read32(&(block
->_start_offset
)));
542 block_table
[i
].end_address
= _mono_debug_address_from_il_offset (jit
, read32(&(block
->_end_offset
)));
545 address
->size
= size
;
546 address
->has_this
= has_this
;
547 address
->num_params
= jit
->num_params
;
548 address
->start_address
= jit
->code_start
;
549 address
->end_address
= jit
->code_start
+ jit
->code_size
;
550 address
->method_start_address
= address
->start_address
+ jit
->prologue_end
;
551 address
->method_end_address
= address
->start_address
+ jit
->epilogue_begin
;
552 address
->wrapper_address
= jit
->wrapper_addr
;
553 address
->variable_table_offset
= variable_offset
;
554 address
->type_table_offset
= type_offset
;
555 address
->lexical_block_table_offset
= block_offset
;
557 if (jit
->line_numbers
) {
558 address
->num_line_numbers
= jit
->line_numbers
->len
;
559 address
->line_number_offset
= line_offset
;
561 line_table
= (MonoDebugLineNumberEntry
*) (ptr
+ line_offset
);
562 memcpy (line_table
, jit
->line_numbers
->data
, line_size
);
565 range
= allocate_range_entry (symfile
);
566 range
->index
= minfo
->index
;
567 range
->start_address
= address
->start_address
;
568 range
->end_address
= address
->end_address
;
569 range
->dynamic_data
= address
;
570 range
->dynamic_size
= size
;
572 if ((minfo
->method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
573 (minfo
->method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) ||
574 (minfo
->method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
577 var_table
= (MonoDebugVarInfo
*) (ptr
+ variable_offset
);
578 type_table
= (guint32
*) (ptr
+ type_offset
);
580 type_index_table
= (guint32
*)
581 (symfile
->symfile
->raw_contents
+ read32(&(minfo
->entry
->_type_index_table_offset
)));
584 *var_table
++ = *jit
->this_var
;
585 *type_table
++ = write_type (mono_debugger_symbol_table
, &minfo
->method
->klass
->this_arg
);
587 for (i
= 0; i
< jit
->num_params
; i
++) {
588 *var_table
++ = jit
->params
[i
];
589 *type_table
++ = write_type (mono_debugger_symbol_table
, minfo
->method
->signature
->params
[i
]);
592 if (jit
->num_locals
< read32(&(minfo
->entry
->_num_locals
))) {
593 g_warning (G_STRLOC
": Method %s.%s has %d locals, but symbol file claims it has %d.",
594 minfo
->method
->klass
->name
, minfo
->method
->name
, jit
->num_locals
,
595 read32(&(minfo
->entry
->_num_locals
)));
596 var_table
+= read32(&(minfo
->entry
->_num_locals
));
598 g_assert ((header
!= NULL
) || (minfo
->entry
->_num_locals
== 0));
599 for (i
= 0; i
< read32(&(minfo
->entry
->_num_locals
)); i
++) {
600 *var_table
++ = jit
->locals
[i
];
601 *type_table
++ = write_type (mono_debugger_symbol_table
, header
->locals
[i
]);
605 must_reload_symtabs
= TRUE
;
608 static MonoDebuggerRangeInfo
*
609 allocate_range_entry (MonoDebuggerSymbolFile
*symfile
)
611 MonoDebuggerRangeInfo
*retval
;
612 guint32 size
, chunks
;
614 if (!symfile
->range_table
) {
615 size
= sizeof (MonoDebuggerRangeInfo
) * RANGE_TABLE_CHUNK_SIZE
;
616 symfile
->range_table
= g_malloc0 (size
);
617 symfile
->num_range_entries
= 1;
618 return symfile
->range_table
;
621 if (!((symfile
->num_range_entries
+ 1) % RANGE_TABLE_CHUNK_SIZE
)) {
622 chunks
= (symfile
->num_range_entries
+ 1) / RANGE_TABLE_CHUNK_SIZE
;
623 size
= sizeof (MonoDebuggerRangeInfo
) * RANGE_TABLE_CHUNK_SIZE
* (chunks
+ 1);
625 symfile
->range_table
= g_realloc (symfile
->range_table
, size
);
628 retval
= symfile
->range_table
+ symfile
->num_range_entries
;
629 symfile
->num_range_entries
++;
633 static MonoDebuggerClassInfo
*
634 allocate_class_entry (MonoDebuggerSymbolFile
*symfile
)
636 MonoDebuggerClassInfo
*retval
;
637 MonoDebuggerClassTable
*table
;
640 if (!symfile
->class_table_start
) {
641 table
= g_new0 (MonoDebuggerClassTable
, 1);
642 symfile
->class_table_start
= symfile
->current_class_table
= table
;
644 size
= sizeof (MonoDebuggerClassInfo
) * CLASS_TABLE_CHUNK_SIZE
;
645 table
->data
= g_malloc0 (size
);
646 table
->size
= CLASS_TABLE_CHUNK_SIZE
;
652 table
= symfile
->current_class_table
;
653 if (table
->index
>= table
->size
) {
654 table
= g_new0 (MonoDebuggerClassTable
, 1);
656 symfile
->current_class_table
->next
= table
;
657 symfile
->current_class_table
= table
;
659 size
= sizeof (MonoDebuggerClassInfo
) * CLASS_TABLE_CHUNK_SIZE
;
660 table
->data
= g_malloc0 (size
);
661 table
->size
= CLASS_TABLE_CHUNK_SIZE
;
667 retval
= table
->data
+ table
->index
;
673 * Allocate a new entry of size `size' in the type table.
674 * Returns the global offset which is to be used to reference this type and
675 * a pointer (in the `ptr' argument) which is to be used to write the type.
678 allocate_type_entry (MonoDebuggerSymbolTable
*table
, guint32 size
, guint8
**ptr
)
683 g_assert (size
+ 4 < TYPE_TABLE_CHUNK_SIZE
);
684 g_assert (ptr
!= NULL
);
686 /* Initialize things if necessary. */
687 if (!table
->current_type_table
) {
688 table
->current_type_table
= g_malloc0 (TYPE_TABLE_CHUNK_SIZE
);
689 table
->type_table_size
= TYPE_TABLE_CHUNK_SIZE
;
690 table
->type_table_chunk_size
= TYPE_TABLE_CHUNK_SIZE
;
691 table
->type_table_offset
= MONO_DEBUGGER_TYPE_MAX
+ 1;
695 /* First let's check whether there's still enough room in the current_type_table. */
696 if (table
->type_table_offset
+ size
+ 4 < table
->type_table_size
) {
697 retval
= table
->type_table_offset
;
698 table
->type_table_offset
+= size
+ 4;
699 data
= ((guint8
*) table
->current_type_table
) + retval
- table
->type_table_start
;
700 *(gint32
*) data
= size
;
701 data
+= sizeof(gint32
);
706 /* Add the current_type_table to the type_tables vector and ... */
707 if (!table
->type_tables
) {
708 guint32 tsize
= sizeof (gpointer
) * TYPE_TABLE_PTR_CHUNK_SIZE
;
709 table
->type_tables
= g_malloc0 (tsize
);
712 if (!((table
->num_type_tables
+ 1) % TYPE_TABLE_PTR_CHUNK_SIZE
)) {
713 guint32 chunks
= (table
->num_type_tables
+ 1) / TYPE_TABLE_PTR_CHUNK_SIZE
;
714 guint32 tsize
= sizeof (gpointer
) * TYPE_TABLE_PTR_CHUNK_SIZE
* (chunks
+ 1);
716 table
->type_tables
= g_realloc (table
->type_tables
, tsize
);
719 table
->type_tables
[table
->num_type_tables
++] = table
->current_type_table
;
721 /* .... allocate a new current_type_table. */
722 table
->current_type_table
= g_malloc0 (TYPE_TABLE_CHUNK_SIZE
);
723 table
->type_table_start
= table
->type_table_offset
= table
->type_table_size
;
724 table
->type_table_size
+= TYPE_TABLE_CHUNK_SIZE
;
730 * Allocate a new entry of size `size' in the misc table.
731 * Returns the global offset which is to be used to reference this entry and
732 * a pointer (in the `ptr' argument) which is to be used to write the entry.
735 allocate_misc_entry (MonoDebuggerSymbolTable
*table
, guint32 size
, guint8
**ptr
)
740 g_assert (size
+ 4 < MISC_TABLE_CHUNK_SIZE
);
741 g_assert (ptr
!= NULL
);
743 /* Initialize things if necessary. */
744 if (!table
->current_misc_table
) {
745 table
->current_misc_table
= g_malloc0 (MISC_TABLE_CHUNK_SIZE
);
746 table
->misc_table_size
= MISC_TABLE_CHUNK_SIZE
;
747 table
->misc_table_chunk_size
= MISC_TABLE_CHUNK_SIZE
;
748 table
->misc_table_offset
= 1;
752 /* First let's check whether there's still enough room in the current_misc_table. */
753 if (table
->misc_table_offset
+ size
+ 4 < table
->misc_table_size
) {
754 retval
= table
->misc_table_offset
;
755 table
->misc_table_offset
+= size
+ 4;
756 data
= ((guint8
*) table
->current_misc_table
) + retval
- table
->misc_table_start
;
757 *(gint32
*) data
= size
;
758 data
+= sizeof(gint32
);
763 /* Add the current_misc_table to the misc_tables vector and ... */
764 if (!table
->misc_tables
) {
765 guint32 tsize
= sizeof (gpointer
) * MISC_TABLE_PTR_CHUNK_SIZE
;
766 table
->misc_tables
= g_malloc0 (tsize
);
769 if (!((table
->num_misc_tables
+ 1) % MISC_TABLE_PTR_CHUNK_SIZE
)) {
770 guint32 chunks
= (table
->num_misc_tables
+ 1) / MISC_TABLE_PTR_CHUNK_SIZE
;
771 guint32 tsize
= sizeof (gpointer
) * MISC_TABLE_PTR_CHUNK_SIZE
* (chunks
+ 1);
773 table
->misc_tables
= g_realloc (table
->misc_tables
, tsize
);
776 table
->misc_tables
[table
->num_misc_tables
++] = table
->current_misc_table
;
778 /* .... allocate a new current_misc_table. */
779 table
->current_misc_table
= g_malloc0 (MISC_TABLE_CHUNK_SIZE
);
780 table
->misc_table_start
= table
->misc_table_offset
= table
->misc_table_size
;
781 table
->misc_table_size
+= MISC_TABLE_CHUNK_SIZE
;
787 property_is_static (MonoProperty
*prop
)
795 return method
->flags
& METHOD_ATTRIBUTE_STATIC
;
799 event_is_static (MonoEvent
*ev
)
805 return method
->flags
& METHOD_ATTRIBUTE_STATIC
;
809 do_write_class (MonoDebuggerSymbolTable
*table
, MonoClass
*klass
, MonoDebuggerClassInfo
*cinfo
)
811 guint8 buffer
[BUFSIZ
], *ptr
= buffer
, *old_ptr
;
812 GPtrArray
*methods
= NULL
, *static_methods
= NULL
, *ctors
= NULL
, *cctors
= NULL
;
813 int num_fields
= 0, num_static_fields
= 0, num_properties
= 0, num_static_properties
= 0;
814 int num_events
= 0, num_static_events
= 0;
815 int num_methods
= 0, num_static_methods
= 0, num_params
= 0, num_static_params
= 0, base_offset
= 0;
816 int num_ctors
= 0, num_ctor_params
= 0;
818 int field_info_size
= 0, static_field_info_size
= 0, property_info_size
= 0, event_info_size
= 0, static_event_info_size
= 0;
819 int static_property_info_size
= 0, method_info_size
= 0, static_method_info_size
= 0;
820 int ctor_info_size
= 0, cctor_info_size
= 0, iface_info_size
= 0;
821 guint32 size
, data_size
, offset
, data_offset
;
822 GHashTable
*method_slots
= NULL
;
825 if (klass
->init_pending
)
826 g_warning (G_STRLOC
": %p - %s.%s", klass
, klass
->name_space
, klass
->name
);
827 g_assert (!klass
->init_pending
);
828 mono_class_init (klass
);
830 offset
= GPOINTER_TO_UINT (g_hash_table_lookup (class_table
, klass
));
834 if (klass
->enumtype
) {
835 offset
= allocate_type_entry (table
, 13, &ptr
);
837 cinfo
->type_info
= offset
;
838 g_hash_table_insert (class_table
, klass
, GUINT_TO_POINTER (offset
));
840 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_ENUM
;
841 WRITE_UINT32 (ptr
, klass
->instance_size
);
842 WRITE_UINT32 (ptr
, MONO_DEBUGGER_TYPE_ENUM
);
843 WRITE_UINT32 (ptr
, write_type (table
, klass
->enum_basetype
));
847 for (i
= 0; i
< klass
->field
.count
; i
++)
848 if (!(klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
853 for (i
= 0; i
< klass
->property
.count
; i
++)
854 if (!property_is_static (&klass
->properties
[i
]))
857 ++num_static_properties
;
859 for (i
= 0; i
< klass
->event
.count
; i
++)
860 if (!event_is_static (&klass
->events
[i
]))
865 method_slots
= g_hash_table_new (NULL
, NULL
);
866 methods
= g_ptr_array_new ();
867 static_methods
= g_ptr_array_new ();
868 ctors
= g_ptr_array_new ();
869 cctors
= g_ptr_array_new ();
871 for (i
= 0; i
< klass
->method
.count
; i
++) {
872 MonoMethod
*method
= klass
->methods
[i
];
874 if (!strcmp (method
->name
, ".cctor")) {
876 g_ptr_array_add (cctors
, method
);
880 if (!strcmp (method
->name
, ".ctor")) {
882 num_ctor_params
+= method
->signature
->param_count
;
883 g_ptr_array_add (ctors
, method
);
887 if (method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
)
890 if (method
->slot
!= -1) {
891 if (g_hash_table_lookup (method_slots
, GUINT_TO_POINTER (method
->slot
)))
893 g_hash_table_insert (method_slots
, GUINT_TO_POINTER (method
->slot
), method
);
896 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
897 ++num_static_methods
;
898 num_static_params
+= method
->signature
->param_count
;
899 g_ptr_array_add (static_methods
, method
);
902 num_params
+= method
->signature
->param_count
;
903 g_ptr_array_add (methods
, method
);
907 g_hash_table_destroy (method_slots
);
909 field_info_size
= num_fields
* 8;
910 static_field_info_size
= num_static_fields
* 8;
911 property_info_size
= num_properties
* (4 + 2 * sizeof (gpointer
));
912 static_property_info_size
= num_static_properties
* (4 + 2 * sizeof (gpointer
));
913 event_info_size
= num_events
* (4 + 2 * sizeof (gpointer
));
914 static_event_info_size
= num_static_events
* (4 + 2 * sizeof (gpointer
));
915 method_info_size
= num_methods
* (2 * 4 + sizeof (gpointer
)) + num_params
* 4;
916 static_method_info_size
= num_static_methods
* (2 * 4 + sizeof (gpointer
)) +
917 num_static_params
* 4;
918 ctor_info_size
= num_ctors
* (2 * 4 + sizeof (gpointer
)) + num_ctor_params
* 4;
919 cctor_info_size
= num_cctors
* (2 * 4 + sizeof (gpointer
));
920 iface_info_size
= klass
->interface_count
* 4;
922 size
= 98 + sizeof (gpointer
) + field_info_size
+ static_field_info_size
+
923 property_info_size
+ static_property_info_size
+ event_info_size
+
924 static_event_info_size
+ method_info_size
+ static_method_info_size
+
925 ctor_info_size
+ cctor_info_size
+ iface_info_size
;
929 offset
= allocate_type_entry (table
, data_size
, &ptr
);
933 cinfo
->type_info
= offset
;
935 g_hash_table_insert (class_table
, klass
, GUINT_TO_POINTER (offset
));
937 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO
;
939 if (klass
->valuetype
)
940 base_offset
= - sizeof (MonoObject
);
942 WRITE_UINT32 (ptr
, klass
->instance_size
+ base_offset
);
943 *ptr
++ = klass
->valuetype
;
944 WRITE_POINTER (ptr
, klass
);
946 WRITE_UINT32 (ptr
, num_fields
);
947 WRITE_UINT32 (ptr
, data_offset
);
948 data_offset
+= field_info_size
;
949 WRITE_UINT32 (ptr
, num_properties
);
950 WRITE_UINT32 (ptr
, data_offset
);
951 data_offset
+= property_info_size
;
952 WRITE_UINT32 (ptr
, num_events
);
953 WRITE_UINT32 (ptr
, data_offset
);
954 data_offset
+= event_info_size
;
955 WRITE_UINT32 (ptr
, num_methods
);
956 WRITE_UINT32 (ptr
, data_offset
);
957 data_offset
+= method_info_size
;
958 WRITE_UINT32 (ptr
, num_static_fields
);
959 WRITE_UINT32 (ptr
, data_offset
);
960 data_offset
+= static_field_info_size
;
961 WRITE_UINT32 (ptr
, num_static_properties
);
962 WRITE_UINT32 (ptr
, data_offset
);
963 data_offset
+= static_property_info_size
;
964 WRITE_UINT32 (ptr
, num_static_events
);
965 WRITE_UINT32 (ptr
, data_offset
);
966 data_offset
+= static_event_info_size
;
967 WRITE_UINT32 (ptr
, num_static_methods
);
968 WRITE_UINT32 (ptr
, data_offset
);
969 data_offset
+= static_method_info_size
;
970 WRITE_UINT32 (ptr
, num_ctors
);
971 WRITE_UINT32 (ptr
, data_offset
);
972 data_offset
+= ctor_info_size
;
973 WRITE_UINT32 (ptr
, num_cctors
);
974 WRITE_UINT32 (ptr
, data_offset
);
975 data_offset
+= cctor_info_size
;
976 WRITE_UINT32 (ptr
, klass
->interface_count
);
977 WRITE_UINT32 (ptr
, data_offset
);
978 data_offset
+= iface_info_size
;
980 if (klass
->parent
&& (klass
->parent
!= mono_defaults
.object_class
))
981 WRITE_UINT32 (ptr
, write_class (table
, klass
->parent
));
983 WRITE_UINT32 (ptr
, 0);
985 for (i
= 0; i
< klass
->field
.count
; i
++) {
986 if (klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
989 WRITE_UINT32 (ptr
, klass
->fields
[i
].offset
+ base_offset
);
990 WRITE_UINT32 (ptr
, write_type (table
, klass
->fields
[i
].type
));
993 for (i
= 0; i
< klass
->property
.count
; i
++) {
994 if (property_is_static (&klass
->properties
[i
]))
997 if (klass
->properties
[i
].get
)
998 WRITE_UINT32 (ptr
, write_type (table
, klass
->properties
[i
].get
->signature
->ret
));
1000 WRITE_UINT32 (ptr
, 0);
1001 WRITE_POINTER (ptr
, klass
->properties
[i
].get
);
1002 WRITE_POINTER (ptr
, klass
->properties
[i
].set
);
1005 for (i
= 0; i
< klass
->event
.count
; i
++) {
1006 if (event_is_static (&klass
->events
[i
]))
1009 if (klass
->events
[i
].add
) {
1010 WRITE_UINT32 (ptr
, write_type (table
, klass
->events
[i
].add
->signature
->params
[0]));
1013 g_warning ("event add method not defined");
1014 WRITE_UINT32 (ptr
, 0);
1016 WRITE_POINTER (ptr
, klass
->events
[i
].add
);
1017 WRITE_POINTER (ptr
, klass
->events
[i
].remove
);
1021 for (i
= 0; i
< methods
->len
; i
++) {
1022 MonoMethod
*method
= g_ptr_array_index (methods
, i
);
1025 WRITE_POINTER (ptr
, method
);
1026 if ((method
->signature
->ret
) && (method
->signature
->ret
->type
!= MONO_TYPE_VOID
))
1027 WRITE_UINT32 (ptr
, write_type (table
, method
->signature
->ret
));
1029 WRITE_UINT32 (ptr
, 0);
1030 WRITE_UINT32 (ptr
, method
->signature
->param_count
);
1031 for (j
= 0; j
< method
->signature
->param_count
; j
++)
1032 WRITE_UINT32 (ptr
, write_type (table
, method
->signature
->params
[j
]));
1035 g_ptr_array_free (methods
, FALSE
);
1037 for (i
= 0; i
< klass
->field
.count
; i
++) {
1038 if (!(klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
1041 WRITE_UINT32 (ptr
, klass
->fields
[i
].offset
);
1042 WRITE_UINT32 (ptr
, write_type (table
, klass
->fields
[i
].type
));
1045 for (i
= 0; i
< klass
->property
.count
; i
++) {
1046 if (!property_is_static (&klass
->properties
[i
]))
1049 if (klass
->properties
[i
].get
)
1050 WRITE_UINT32 (ptr
, write_type (table
, klass
->properties
[i
].get
->signature
->ret
));
1052 WRITE_UINT32 (ptr
, 0);
1053 WRITE_POINTER (ptr
, klass
->properties
[i
].get
);
1054 WRITE_POINTER (ptr
, klass
->properties
[i
].set
);
1057 for (i
= 0; i
< klass
->event
.count
; i
++) {
1058 if (!event_is_static (&klass
->events
[i
]))
1061 if (klass
->events
[i
].add
) {
1062 WRITE_UINT32 (ptr
, write_type (table
, klass
->events
[i
].add
->signature
->params
[0]));
1065 g_warning ("event add method not defined");
1066 WRITE_UINT32 (ptr
, 0);
1068 WRITE_POINTER (ptr
, klass
->events
[i
].add
);
1069 WRITE_POINTER (ptr
, klass
->events
[i
].remove
);
1073 for (i
= 0; i
< static_methods
->len
; i
++) {
1074 MonoMethod
*method
= g_ptr_array_index (static_methods
, i
);
1077 WRITE_POINTER (ptr
, method
);
1078 if ((method
->signature
->ret
) && (method
->signature
->ret
->type
!= MONO_TYPE_VOID
))
1079 WRITE_UINT32 (ptr
, write_type (table
, method
->signature
->ret
));
1081 WRITE_UINT32 (ptr
, 0);
1082 WRITE_UINT32 (ptr
, method
->signature
->param_count
);
1083 for (j
= 0; j
< method
->signature
->param_count
; j
++)
1084 WRITE_UINT32 (ptr
, write_type (table
, method
->signature
->params
[j
]));
1087 g_ptr_array_free (static_methods
, FALSE
);
1089 for (i
= 0; i
< ctors
->len
; i
++) {
1090 MonoMethod
*ctor
= g_ptr_array_index (ctors
, i
);
1093 WRITE_POINTER (ptr
, ctor
);
1094 WRITE_UINT32 (ptr
, 0);
1095 WRITE_UINT32 (ptr
, ctor
->signature
->param_count
);
1096 for (j
= 0; j
< ctor
->signature
->param_count
; j
++)
1097 WRITE_UINT32 (ptr
, write_type (table
, ctor
->signature
->params
[j
]));
1100 g_ptr_array_free (ctors
, FALSE
);
1102 for (i
= 0; i
< cctors
->len
; i
++) {
1103 MonoMethod
*cctor
= g_ptr_array_index (cctors
, i
);
1105 WRITE_POINTER (ptr
, cctor
);
1106 WRITE_UINT32 (ptr
, 0);
1107 WRITE_UINT32 (ptr
, 0);
1110 g_ptr_array_free (cctors
, FALSE
);
1112 for (i
= 0; i
< klass
->interface_count
; i
++)
1113 WRITE_UINT32 (ptr
, write_class (table
, klass
->interfaces
[i
]));
1115 if (ptr
- old_ptr
!= data_size
) {
1116 g_warning (G_STRLOC
": %d,%d,%d", ptr
- old_ptr
, data_size
, sizeof (gpointer
));
1118 g_warning (G_STRLOC
": %s.%s", klass
->name_space
, klass
->name
);
1119 g_assert_not_reached ();
1126 * Adds type `type' to the type table and returns its offset.
1129 write_type (MonoDebuggerSymbolTable
*table
, MonoType
*type
)
1131 guint8 buffer
[BUFSIZ
], *ptr
= buffer
;
1132 guint32 size
, offset
;
1135 offset
= GPOINTER_TO_UINT (g_hash_table_lookup (type_table
, type
));
1139 klass
= mono_class_from_mono_type (type
);
1140 if (type
->type
== MONO_TYPE_CLASS
)
1141 return write_class (table
, klass
);
1143 // mono_class_init (klass);
1145 switch (type
->type
) {
1146 case MONO_TYPE_VOID
:
1147 return MONO_DEBUGGER_TYPE_VOID
;
1149 case MONO_TYPE_BOOLEAN
:
1150 return MONO_DEBUGGER_TYPE_BOOLEAN
;
1153 return MONO_DEBUGGER_TYPE_I1
;
1156 return MONO_DEBUGGER_TYPE_U1
;
1158 case MONO_TYPE_CHAR
:
1159 return MONO_DEBUGGER_TYPE_CHAR
;
1162 return MONO_DEBUGGER_TYPE_I2
;
1165 return MONO_DEBUGGER_TYPE_U2
;
1168 return MONO_DEBUGGER_TYPE_I4
;
1171 return MONO_DEBUGGER_TYPE_U4
;
1174 return MONO_DEBUGGER_TYPE_I8
;
1177 return MONO_DEBUGGER_TYPE_U8
;
1180 return MONO_DEBUGGER_TYPE_R4
;
1183 return MONO_DEBUGGER_TYPE_R8
;
1185 case MONO_TYPE_STRING
:
1186 return MONO_DEBUGGER_TYPE_STRING
;
1189 return MONO_DEBUGGER_TYPE_I
;
1192 return MONO_DEBUGGER_TYPE_U
;
1194 case MONO_TYPE_SZARRAY
: {
1197 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY
;
1198 WRITE_UINT32 (ptr
, sizeof (MonoArray
));
1199 WRITE_UINT32 (ptr
, MONO_DEBUGGER_TYPE_ARRAY
);
1200 *ptr
++ = (guint8
*)&array
.max_length
- (guint8
*)&array
;
1201 *ptr
++ = sizeof (array
.max_length
);
1202 *ptr
++ = (guint8
*)&array
.vector
- (guint8
*)&array
;
1203 WRITE_UINT32 (ptr
, write_type (table
, &type
->data
.klass
->byval_arg
));
1207 case MONO_TYPE_ARRAY
: {
1209 MonoArrayBounds bounds
;
1211 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_ARRAY
;
1212 WRITE_UINT32 (ptr
, sizeof (MonoArray
));
1213 WRITE_UINT32 (ptr
, MONO_DEBUGGER_TYPE_ARRAY
);
1214 *ptr
++ = (guint8
*)&array
.max_length
- (guint8
*)&array
;
1215 *ptr
++ = sizeof (array
.max_length
);
1216 *ptr
++ = (guint8
*)&array
.vector
- (guint8
*)&array
;
1217 *ptr
++ = klass
->rank
;
1218 *ptr
++ = (guint8
*)&array
.bounds
- (guint8
*)&array
;
1219 *ptr
++ = sizeof (MonoArrayBounds
);
1220 *ptr
++ = (guint8
*)&bounds
.lower_bound
- (guint8
*)&bounds
;
1221 *ptr
++ = sizeof (bounds
.lower_bound
);
1222 *ptr
++ = (guint8
*)&bounds
.length
- (guint8
*)&bounds
;
1223 *ptr
++ = sizeof (bounds
.length
);
1224 WRITE_UINT32 (ptr
, write_type (table
, &type
->data
.array
->eklass
->byval_arg
));
1228 case MONO_TYPE_VALUETYPE
:
1229 case MONO_TYPE_CLASS
:
1230 case MONO_TYPE_GENERICINST
:
1231 case MONO_TYPE_OBJECT
:
1232 return write_class (table
, klass
);
1235 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_POINTER
;
1236 WRITE_UINT32 (ptr
, sizeof (gpointer
));
1237 WRITE_UINT32 (ptr
, write_type (table
, type
->data
.type
));
1241 /* g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type); */
1242 *ptr
++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN
;
1243 WRITE_UINT32 (ptr
, klass
->instance_size
);
1244 WRITE_UINT32 (ptr
, write_class (table
, klass
));
1248 size
= ptr
- buffer
;
1249 offset
= allocate_type_entry (mono_debugger_symbol_table
, size
, &ptr
);
1250 memcpy (ptr
, buffer
, size
);
1255 MonoReflectionMethod
*
1256 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly
*assembly
, guint32 token
)
1260 method
= mono_get_method (mono_assembly_get_image (assembly
->assembly
), token
, NULL
);
1262 return mono_method_get_object (mono_domain_get (), method
, NULL
);
1266 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly
*assembly
, MonoReflectionMethod
*method
)
1268 return method
->method
->token
;
1271 MonoReflectionType
*
1272 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly
*assembly
, guint32 token
)
1276 klass
= mono_class_get (mono_assembly_get_image (assembly
->assembly
), token
);
1278 g_warning (G_STRLOC
": %x", token
);
1282 return mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
1285 MonoReflectionType
*
1286 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly
*assembly
, MonoArray
*signature
)
1294 MONO_CHECK_ARG_NULL (assembly
);
1295 MONO_CHECK_ARG_NULL (signature
);
1297 domain
= mono_domain_get();
1298 image
= mono_assembly_get_image (assembly
->assembly
);
1300 ptr
= mono_array_addr (signature
, char, 0);
1301 g_assert (*ptr
++ == 0x07);
1302 len
= mono_metadata_decode_value (ptr
, &ptr
);
1303 g_assert (len
== 1);
1305 type
= mono_metadata_parse_type (image
, MONO_PARSE_LOCAL
, 0, ptr
, &ptr
);
1307 return mono_type_get_object (domain
, type
);
1311 mono_debugger_event (MonoDebuggerEvent event
, gpointer data
, guint32 arg
)
1313 if (mono_debugger_event_handler
)
1314 (* mono_debugger_event_handler
) (event
, data
, arg
);
1318 mono_debugger_cleanup (void)
1320 /* Do nothing yet. */
1324 * Debugger breakpoint interface.
1326 * This interface is used to insert breakpoints on methods which are not yet JITed.
1327 * The debugging code keeps a list of all such breakpoints and automatically inserts the
1328 * breakpoint when the method is JITed.
1331 static GPtrArray
*breakpoints
= NULL
;
1334 mono_debugger_insert_breakpoint_full (MonoMethodDesc
*desc
)
1336 static int last_breakpoint_id
= 0;
1337 MonoDebuggerBreakpointInfo
*info
;
1339 info
= g_new0 (MonoDebuggerBreakpointInfo
, 1);
1341 info
->index
= ++last_breakpoint_id
;
1344 breakpoints
= g_ptr_array_new ();
1346 g_ptr_array_add (breakpoints
, info
);
1352 mono_debugger_remove_breakpoint (int breakpoint_id
)
1359 for (i
= 0; i
< breakpoints
->len
; i
++) {
1360 MonoDebuggerBreakpointInfo
*info
= g_ptr_array_index (breakpoints
, i
);
1362 if (info
->index
!= breakpoint_id
)
1365 mono_method_desc_free (info
->desc
);
1366 g_ptr_array_remove (breakpoints
, info
);
1375 mono_debugger_insert_breakpoint (const gchar
*method_name
, gboolean include_namespace
)
1377 MonoMethodDesc
*desc
;
1379 desc
= mono_method_desc_new (method_name
, include_namespace
);
1383 return mono_debugger_insert_breakpoint_full (desc
);
1387 mono_debugger_method_has_breakpoint (MonoMethod
*method
)
1391 if (!breakpoints
|| (method
->wrapper_type
!= MONO_WRAPPER_NONE
))
1394 for (i
= 0; i
< breakpoints
->len
; i
++) {
1395 MonoDebuggerBreakpointInfo
*info
= g_ptr_array_index (breakpoints
, i
);
1397 if (!mono_method_desc_full_match (info
->desc
, method
))
1407 mono_debugger_breakpoint_callback (MonoMethod
*method
, guint32 index
)
1409 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT
, method
, index
);
1413 mono_debugger_unhandled_exception (gpointer addr
, gpointer stack
, MonoObject
*exc
)
1415 if (!mono_debugger_initialized
)
1418 // Prevent the object from being finalized.
1419 last_exception
= exc
;
1420 mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION
, exc
, addr
);
1425 mono_debugger_handle_exception (gpointer addr
, gpointer stack
, MonoObject
*exc
)
1427 MonoDebuggerExceptionInfo info
;
1429 if (!mono_debugger_initialized
)
1432 // Prevent the object from being finalized.
1433 last_exception
= exc
;
1435 info
.stack_pointer
= stack
;
1436 info
.exception_obj
= exc
;
1439 mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION
, &info
, addr
);
1443 mono_debugger_throw_exception (gpointer addr
, gpointer stack
, MonoObject
*exc
)
1445 MonoDebuggerExceptionInfo info
;
1447 if (!mono_debugger_initialized
)
1450 // Prevent the object from being finalized.
1451 last_exception
= exc
;
1453 info
.stack_pointer
= stack
;
1454 info
.exception_obj
= exc
;
1457 mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION
, &info
, addr
);
1458 return info
.stop
!= 0;
1462 get_exception_message (MonoObject
*exc
)
1464 char *message
= NULL
;
1470 if (mono_object_isinst (exc
, mono_defaults
.exception_class
)) {
1471 klass
= exc
->vtable
->klass
;
1473 while (klass
&& method
== NULL
) {
1474 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1475 method
= klass
->methods
[i
];
1476 if (!strcmp ("ToString", method
->name
) &&
1477 method
->signature
->param_count
== 0 &&
1478 method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
&&
1479 method
->flags
& METHOD_ATTRIBUTE_PUBLIC
) {
1486 klass
= klass
->parent
;
1491 str
= (MonoString
*) mono_runtime_invoke (method
, exc
, NULL
, NULL
);
1493 message
= mono_string_to_utf8 (str
);
1500 mono_debugger_runtime_invoke (MonoMethod
*method
, void *obj
, void **params
, MonoObject
**exc
)
1505 if (!strcmp (method
->name
, ".ctor")) {
1506 retval
= obj
= mono_object_new (mono_domain_get (), method
->klass
);
1508 mono_runtime_invoke (method
, obj
, params
, exc
);
1510 retval
= mono_runtime_invoke (method
, obj
, params
, exc
);
1512 if (!exc
|| (*exc
== NULL
))
1515 message
= get_exception_message (*exc
);
1517 *exc
= (MonoObject
*) mono_string_new_wrapper (message
);
1525 mono_debugger_lookup_type (const gchar
*type_name
)
1529 mono_debugger_lock ();
1531 for (i
= 0; i
< mono_debugger_symbol_table
->num_symbol_files
; i
++) {
1532 MonoDebuggerSymbolFile
*symfile
= mono_debugger_symbol_table
->symbol_files
[i
];
1537 name
= g_strdup (type_name
);
1538 type
= mono_reflection_type_from_name (name
, symfile
->image
);
1543 offset
= write_type (mono_debugger_symbol_table
, type
);
1545 mono_debugger_unlock ();
1549 mono_debugger_unlock ();
1554 mono_debugger_lookup_assembly (const gchar
*name
)
1556 MonoAssembly
*assembly
;
1557 MonoImageOpenStatus status
;
1560 mono_debugger_lock ();
1563 for (i
= 0; i
< mono_debugger_symbol_table
->num_symbol_files
; i
++) {
1564 MonoDebuggerSymbolFile
*symfile
= mono_debugger_symbol_table
->symbol_files
[i
];
1566 if (!strcmp (symfile
->image_file
, name
)) {
1567 mono_debugger_unlock ();
1572 assembly
= mono_assembly_open (name
, &status
);
1574 if (status
!= MONO_IMAGE_OK
) {
1575 g_warning (G_STRLOC
": Cannot open image `%s'", name
);
1576 mono_debugger_unlock ();
1580 must_reload_symtabs
= TRUE
;
1585 mono_debugger_add_wrapper (MonoMethod
*wrapper
, MonoDebugMethodJitInfo
*jit
, gpointer addr
)
1587 guint32 size
, offset
;
1590 if (!mono_debugger_symbol_table
)
1593 size
= strlen (wrapper
->name
) + 5 + 5 * sizeof (gpointer
);
1595 offset
= allocate_misc_entry (mono_debugger_symbol_table
, size
, &ptr
);
1597 WRITE_UINT32 (ptr
, MONO_DEBUGGER_MISC_ENTRY_TYPE_WRAPPER
);
1598 WRITE_STRING (ptr
, wrapper
->name
);
1599 WRITE_POINTER (ptr
, jit
->code_start
);
1600 WRITE_POINTER (ptr
, jit
->code_start
+ jit
->code_size
);
1601 WRITE_POINTER (ptr
, addr
);
1602 WRITE_POINTER (ptr
, jit
->code_start
+ jit
->prologue_end
);
1603 WRITE_POINTER (ptr
, jit
->code_start
+ jit
->epilogue_begin
);