4 #include <mono/metadata/metadata.h>
5 #include <mono/metadata/tabledefs.h>
6 #include <mono/metadata/tokentype.h>
7 #include <mono/metadata/appdomain.h>
8 #include <mono/metadata/exception.h>
9 #include <mono/metadata/mono-debug.h>
10 #include <mono/metadata/mono-debug-debugger.h>
11 #include <mono/metadata/mono-endian.h>
13 #define SYMFILE_TABLE_CHUNK_SIZE 16
14 #define RANGE_TABLE_CHUNK_SIZE 256
15 #define CLASS_TABLE_CHUNK_SIZE 256
16 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
17 #define TYPE_TABLE_CHUNK_SIZE 65536
19 static guint32 debugger_lock_level = 0;
20 static CRITICAL_SECTION debugger_lock_mutex;
21 static gboolean mono_debugger_initialized = FALSE;
23 static gboolean must_reload_symtabs = FALSE;
25 static GHashTable *images = NULL;
26 static GHashTable *type_table = NULL;
27 static GHashTable *class_table = NULL;
28 static GHashTable *class_info_table = NULL;
30 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
31 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
32 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
33 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
34 static guint32 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass);
36 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
37 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
39 #define WRITE_UINT32(ptr,value) G_STMT_START { \
40 * ((guint32 *) ptr) = value; \
44 #define WRITE_POINTER(ptr,value) G_STMT_START { \
45 * ((gpointer *) ptr) = value; \
46 ptr += sizeof (gpointer); \
49 #ifndef PLATFORM_WIN32
51 MonoDebuggerIOLayer mono_debugger_io_layer = {
52 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
53 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
54 WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
61 mono_debugger_lock (void)
63 if (!mono_debugger_initialized) {
64 debugger_lock_level++;
68 EnterCriticalSection (&debugger_lock_mutex);
69 debugger_lock_level++;
73 mono_debugger_unlock (void)
75 g_assert (debugger_lock_level > 0);
77 if (!mono_debugger_initialized) {
78 debugger_lock_level--;
82 if (debugger_lock_level == 1) {
83 if (must_reload_symtabs) {
84 mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, NULL, 0);
85 must_reload_symtabs = FALSE;
89 debugger_lock_level--;
90 LeaveCriticalSection (&debugger_lock_mutex);
93 static MonoDebuggerSymbolFile *
94 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
96 MonoDebuggerSymbolFile *symfile;
98 if (!table->symbol_files)
99 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
100 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
101 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
102 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
104 table->symbol_files = g_realloc (table->symbol_files, size);
107 symfile = g_new0 (MonoDebuggerSymbolFile, 1);
108 symfile->index = table->num_symbol_files;
109 symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
110 symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
111 table->symbol_files [table->num_symbol_files++] = symfile;
116 mono_debugger_initialize (MonoDomain *domain)
118 MonoDebuggerSymbolTable *symbol_table;
120 g_assert (!mono_debugger_initialized);
122 InitializeCriticalSection (&debugger_lock_mutex);
123 mono_debugger_initialized = TRUE;
125 mono_debugger_lock ();
127 symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
128 symbol_table->magic = MONO_DEBUGGER_MAGIC;
129 symbol_table->version = MONO_DEBUGGER_VERSION;
130 symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
132 symbol_table->domain = domain;
134 images = g_hash_table_new (g_direct_hash, g_direct_equal);
135 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
136 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
137 class_info_table = g_hash_table_new (g_direct_hash, g_direct_equal);
139 mono_debugger_symbol_table = symbol_table;
141 mono_debugger_unlock ();
144 MonoDebuggerSymbolFile *
145 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
147 MonoDebuggerSymbolFile *info;
149 g_assert (mono_debugger_initialized);
150 mono_debugger_lock ();
152 info = g_hash_table_lookup (images, handle->image);
154 mono_debugger_unlock ();
158 info = allocate_symbol_file_entry (mono_debugger_symbol_table);
159 info->symfile = handle->symfile;
160 info->image = handle->image;
161 info->image_file = handle->image_file;
163 g_hash_table_insert (images, handle->image, info);
164 mono_debugger_unlock ();
170 write_builtin_type (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerBuiltinTypeInfo *info)
172 guint8 buffer [BUFSIZ], *ptr = buffer;
175 g_assert (!klass->init_pending);
176 mono_class_init (klass);
178 switch (klass->byval_arg.type) {
180 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
181 WRITE_UINT32 (ptr, 0);
185 case MONO_TYPE_BOOLEAN:
197 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
198 WRITE_UINT32 (ptr, klass->instance_size - sizeof (MonoObject));
202 case MONO_TYPE_STRING: {
205 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
206 WRITE_UINT32 (ptr, klass->instance_size);
208 *ptr++ = (guint8*)&string.length - (guint8*)&string;
209 *ptr++ = sizeof (string.length);
210 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
217 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
218 WRITE_UINT32 (ptr, sizeof (void *));
222 case MONO_TYPE_VALUETYPE:
223 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
224 WRITE_UINT32 (ptr, klass->instance_size);
228 case MONO_TYPE_CLASS:
229 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
230 WRITE_UINT32 (ptr, klass->instance_size);
234 case MONO_TYPE_OBJECT:
235 g_assert (klass == mono_defaults.object_class);
236 *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
237 WRITE_UINT32 (ptr, klass->instance_size);
242 g_error (G_STRLOC ": Unknown builtin type %s.%s - %d", klass->name_space, klass->name, klass->byval_arg.type);
246 info->cinfo->type_info = info->type_info = allocate_type_entry (table, size, &info->type_data);
247 memcpy (info->type_data, buffer, size);
250 static MonoDebuggerBuiltinTypeInfo *
251 add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
253 MonoDebuggerClassInfo *cinfo;
254 MonoDebuggerBuiltinTypeInfo *info;
256 cinfo = g_new0 (MonoDebuggerClassInfo, 1);
257 cinfo->klass = klass;
259 cinfo->token = klass->element_class->type_token;
260 cinfo->rank = klass->rank;
262 cinfo->token = klass->type_token;
264 g_hash_table_insert (class_info_table, klass, cinfo);
266 info = g_new0 (MonoDebuggerBuiltinTypeInfo, 1);
270 write_builtin_type (mono_debugger_symbol_table, klass, info);
275 add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo *info)
277 info->class_info = write_class (mono_debugger_symbol_table, info->klass);
278 * (guint32 *) (info->type_data + 5) = info->class_info;
281 MonoDebuggerBuiltinTypes *
282 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
284 MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
286 mono_debugger_symbol_table->corlib = symfile;
287 mono_debugger_symbol_table->builtin_types = types;
289 types->total_size = sizeof (MonoDebuggerBuiltinTypes);
290 types->type_info_size = sizeof (MonoDebuggerBuiltinTypeInfo);
292 types->object_type = add_builtin_type (symfile, mono_defaults.object_class);
293 types->byte_type = add_builtin_type (symfile, mono_defaults.byte_class);
294 types->void_type = add_builtin_type (symfile, mono_defaults.void_class);
295 types->boolean_type = add_builtin_type (symfile, mono_defaults.boolean_class);
296 types->sbyte_type = add_builtin_type (symfile, mono_defaults.sbyte_class);
297 types->int16_type = add_builtin_type (symfile, mono_defaults.int16_class);
298 types->uint16_type = add_builtin_type (symfile, mono_defaults.uint16_class);
299 types->int32_type = add_builtin_type (symfile, mono_defaults.int32_class);
300 types->uint32_type = add_builtin_type (symfile, mono_defaults.uint32_class);
301 types->int_type = add_builtin_type (symfile, mono_defaults.int_class);
302 types->uint_type = add_builtin_type (symfile, mono_defaults.uint_class);
303 types->int64_type = add_builtin_type (symfile, mono_defaults.int64_class);
304 types->uint64_type = add_builtin_type (symfile, mono_defaults.uint64_class);
305 types->single_type = add_builtin_type (symfile, mono_defaults.single_class);
306 types->double_type = add_builtin_type (symfile, mono_defaults.double_class);
307 types->char_type = add_builtin_type (symfile, mono_defaults.char_class);
308 types->string_type = add_builtin_type (symfile, mono_defaults.string_class);
310 types->enum_type = add_builtin_type (symfile, mono_defaults.enum_class);
311 types->array_type = add_builtin_type (symfile, mono_defaults.array_class);
312 types->exception_type = add_builtin_type (symfile, mono_defaults.exception_class);
314 add_builtin_type_2 (types->object_type);
315 add_builtin_type_2 (types->byte_type);
316 add_builtin_type_2 (types->void_type);
317 add_builtin_type_2 (types->boolean_type);
318 add_builtin_type_2 (types->sbyte_type);
319 add_builtin_type_2 (types->int16_type);
320 add_builtin_type_2 (types->uint16_type);
321 add_builtin_type_2 (types->int32_type);
322 add_builtin_type_2 (types->uint32_type);
323 add_builtin_type_2 (types->int_type);
324 add_builtin_type_2 (types->uint_type);
325 add_builtin_type_2 (types->int64_type);
326 add_builtin_type_2 (types->uint64_type);
327 add_builtin_type_2 (types->single_type);
328 add_builtin_type_2 (types->double_type);
329 add_builtin_type_2 (types->char_type);
330 add_builtin_type_2 (types->string_type);
331 add_builtin_type_2 (types->enum_type);
332 add_builtin_type_2 (types->array_type);
333 add_builtin_type_2 (types->exception_type);
339 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
341 MonoDebuggerClassInfo *cinfo;
343 mono_debugger_lock ();
345 cinfo = g_hash_table_lookup (class_info_table, klass);
347 mono_debugger_unlock ();
351 symfile->generation++;
353 cinfo = allocate_class_entry (symfile);
354 cinfo->klass = klass;
356 cinfo->token = klass->element_class->type_token;
357 cinfo->rank = klass->rank;
359 cinfo->token = klass->type_token;
360 g_hash_table_insert (class_info_table, klass, cinfo);
362 cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
364 must_reload_symtabs = TRUE;
365 mono_debugger_unlock ();
369 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
370 MonoDebugMethodJitInfo *jit)
372 MonoSymbolFileMethodAddress *address;
373 MonoSymbolFileLexicalBlockEntry *block;
374 MonoDebugVarInfo *var_table;
375 MonoDebuggerRangeInfo *range;
376 MonoMethodHeader *header;
377 guint32 size, num_variables, variable_size, variable_offset;
378 guint32 type_size, type_offset, *type_index_table, has_this;
379 guint32 line_size, line_offset, block_offset, block_size;
380 MonoDebugLexicalBlockEntry *block_table;
381 MonoDebugLineNumberEntry *line_table;
386 if (!symfile->symfile->method_hash)
389 header = ((MonoMethodNormal *) minfo->method)->header;
391 symfile->generation++;
393 size = sizeof (MonoSymbolFileMethodAddress);
395 num_variables = read32(&(minfo->entry->_num_parameters)) + read32(&(minfo->entry->_num_locals));
396 has_this = jit->this_var != NULL;
398 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
399 variable_offset = size;
400 size += variable_size;
402 type_size = (num_variables + 1) * sizeof (gpointer);
406 if (jit->line_numbers) {
408 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
412 block_size = read32(&(minfo->entry->_num_lexical_blocks)) * sizeof (MonoSymbolFileLexicalBlockEntry);
416 address = g_malloc0 (size);
417 ptr = (guint8 *) address;
419 block = (MonoSymbolFileLexicalBlockEntry *)
420 (symfile->symfile->raw_contents + read32(&(minfo->entry->_lexical_block_table_offset)));
421 block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
423 for (i = 0; i < read32(&(minfo->entry->_num_lexical_blocks)); i++, block++) {
424 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_start_offset)));
425 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_end_offset)));
428 address->size = size;
429 address->has_this = has_this;
430 address->start_address = jit->code_start;
431 address->end_address = jit->code_start + jit->code_size;
432 address->method_start_address = address->start_address + jit->prologue_end;
433 address->method_end_address = address->start_address + jit->epilogue_begin;
434 address->wrapper_address = jit->wrapper_addr;
435 address->variable_table_offset = variable_offset;
436 address->type_table_offset = type_offset;
437 address->lexical_block_table_offset = block_offset;
439 if (jit->line_numbers) {
440 address->num_line_numbers = jit->line_numbers->len;
441 address->line_number_offset = line_offset;
443 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
444 memcpy (line_table, jit->line_numbers->data, line_size);
447 range = allocate_range_entry (symfile);
448 range->index = minfo->index;
449 range->start_address = address->start_address;
450 range->end_address = address->end_address;
451 range->dynamic_data = address;
452 range->dynamic_size = size;
454 if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
455 (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
456 (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
459 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
460 type_table = (guint32 *) (ptr + type_offset);
462 type_index_table = (guint32 *)
463 (symfile->symfile->raw_contents + read32(&(minfo->entry->_type_index_table_offset)));
466 *var_table++ = *jit->this_var;
467 *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
469 if (jit->num_params != read32(&(minfo->entry->_num_parameters))) {
470 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
471 minfo->method->klass->name, minfo->method->name, jit->num_params,
472 read32(&(minfo->entry->_num_parameters)));
473 var_table += read32(&(minfo->entry->_num_parameters));
475 for (i = 0; i < jit->num_params; i++) {
476 *var_table++ = jit->params [i];
477 *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
481 if (jit->num_locals < read32(&(minfo->entry->_num_locals))) {
482 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
483 minfo->method->klass->name, minfo->method->name, jit->num_locals,
484 read32(&(minfo->entry->_num_locals)));
485 var_table += read32(&(minfo->entry->_num_locals));
487 g_assert ((header != NULL) || (minfo->entry->_num_locals == 0));
488 for (i = 0; i < read32(&(minfo->entry->_num_locals)); i++) {
489 *var_table++ = jit->locals [i];
490 *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
494 must_reload_symtabs = TRUE;
497 static MonoDebuggerRangeInfo *
498 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
500 MonoDebuggerRangeInfo *retval;
501 guint32 size, chunks;
503 if (!symfile->range_table) {
504 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
505 symfile->range_table = g_malloc0 (size);
506 symfile->num_range_entries = 1;
507 return symfile->range_table;
510 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
511 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
512 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
514 symfile->range_table = g_realloc (symfile->range_table, size);
517 retval = symfile->range_table + symfile->num_range_entries;
518 symfile->num_range_entries++;
522 static MonoDebuggerClassInfo *
523 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
525 MonoDebuggerClassInfo *retval;
526 guint32 size, chunks;
528 if (!symfile->class_table) {
529 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
530 symfile->class_table = g_malloc0 (size);
531 symfile->num_class_entries = 1;
532 return symfile->class_table;
535 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
536 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
537 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
539 symfile->class_table = g_realloc (symfile->class_table, size);
542 retval = symfile->class_table + symfile->num_class_entries;
543 symfile->num_class_entries++;
548 * Allocate a new entry of size `size' in the type table.
549 * Returns the global offset which is to be used to reference this type and
550 * a pointer (in the `ptr' argument) which is to be used to write the type.
553 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
558 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
559 g_assert (ptr != NULL);
561 /* Initialize things if necessary. */
562 if (!table->current_type_table) {
563 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
564 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
565 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
566 table->type_table_offset = 1;
570 /* First let's check whether there's still enough room in the current_type_table. */
571 if (table->type_table_offset + size + 4 < table->type_table_size) {
572 retval = table->type_table_offset;
573 table->type_table_offset += size + 4;
574 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
575 *(gint32 *) data = size;
576 data += sizeof(gint32);
581 /* Add the current_type_table to the type_tables vector and ... */
582 if (!table->type_tables) {
583 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
584 table->type_tables = g_malloc0 (tsize);
587 if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
588 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
589 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
591 table->type_tables = g_realloc (table->type_tables, tsize);
594 table->type_tables [table->num_type_tables++] = table->current_type_table;
596 /* .... allocate a new current_type_table. */
597 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
598 table->type_table_start = table->type_table_offset = table->type_table_size;
599 table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
605 property_is_static (MonoProperty *prop)
613 return method->flags & METHOD_ATTRIBUTE_STATIC;
617 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
619 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
620 GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL;
621 int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
622 int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
623 int num_ctors = 0, num_ctor_params = 0;
624 guint32 size, data_size, offset;
625 GHashTable *method_slots = NULL;
628 g_assert (!klass->init_pending);
629 mono_class_init (klass);
631 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
635 if (klass->enumtype) {
636 offset = allocate_type_entry (table, 13, &ptr);
637 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
639 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
640 WRITE_UINT32 (ptr, klass->instance_size);
641 WRITE_UINT32 (ptr, table->builtin_types->enum_type->type_info);
642 WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
646 for (i = 0; i < klass->field.count; i++)
647 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
652 for (i = 0; i < klass->property.count; i++)
653 if (!property_is_static (&klass->properties [i]))
656 ++num_static_properties;
658 method_slots = g_hash_table_new (NULL, NULL);
659 methods = g_ptr_array_new ();
660 static_methods = g_ptr_array_new ();
661 ctors = g_ptr_array_new ();
663 for (i = 0; i < klass->method.count; i++) {
664 MonoMethod *method = klass->methods [i];
666 if (!strcmp (method->name, ".cctor"))
668 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
671 if (!strcmp (method->name, ".ctor")) {
673 num_ctor_params += method->signature->param_count;
674 g_ptr_array_add (ctors, method);
678 if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
681 if (method->slot != -1) {
682 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
684 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
687 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
688 ++num_static_methods;
689 num_static_params += method->signature->param_count;
690 g_ptr_array_add (static_methods, method);
693 num_params += method->signature->param_count;
694 g_ptr_array_add (methods, method);
698 g_hash_table_destroy (method_slots);
700 size = 66 + sizeof (gpointer) + num_fields * 8 + num_static_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
701 num_static_properties * (4 + 2 * sizeof (gpointer)) + num_methods * (8 + sizeof (gpointer)) + num_params * 4 +
702 num_static_methods * (8 + sizeof (gpointer)) + num_static_params * 4 + num_ctors * (8 + sizeof (gpointer)) +
707 offset = allocate_type_entry (table, data_size, &ptr);
710 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
712 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
714 if (klass->valuetype)
715 base_offset = - sizeof (MonoObject);
717 WRITE_UINT32 (ptr, klass->instance_size + base_offset);
718 *ptr++ = klass->valuetype;
719 WRITE_POINTER (ptr, klass);
720 WRITE_UINT32 (ptr, num_fields);
721 WRITE_UINT32 (ptr, num_fields * 8);
722 WRITE_UINT32 (ptr, num_static_fields);
723 WRITE_UINT32 (ptr, num_static_fields * 8);
724 WRITE_UINT32 (ptr, num_properties);
725 WRITE_UINT32 (ptr, num_properties * (4 + 2 * sizeof (gpointer)));
726 WRITE_UINT32 (ptr, num_static_properties);
727 WRITE_UINT32 (ptr, num_static_properties * (4 + 2 * sizeof (gpointer)));
728 WRITE_UINT32 (ptr, num_methods);
729 WRITE_UINT32 (ptr, num_methods * (4 + 2 * sizeof (gpointer)) + num_params * sizeof (gpointer));
730 WRITE_UINT32 (ptr, num_static_methods);
731 WRITE_UINT32 (ptr, num_static_methods * (4 + 2 * sizeof (gpointer)) + num_static_params * sizeof (gpointer));
732 WRITE_UINT32 (ptr, num_ctors);
733 WRITE_UINT32 (ptr, num_ctors * (4 + 2 * sizeof (gpointer)) + num_ctor_params * sizeof (gpointer));
735 for (i = 0; i < klass->field.count; i++) {
736 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
739 WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
740 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
743 for (i = 0; i < klass->property.count; i++) {
744 if (property_is_static (&klass->properties [i]))
747 if (klass->properties [i].get)
748 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
750 WRITE_UINT32 (ptr, 0);
751 WRITE_POINTER (ptr, klass->properties [i].get);
752 WRITE_POINTER (ptr, klass->properties [i].set);
755 for (i = 0; i < methods->len; i++) {
756 MonoMethod *method = g_ptr_array_index (methods, i);
759 WRITE_POINTER (ptr, method);
760 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
761 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
763 WRITE_UINT32 (ptr, 0);
764 WRITE_UINT32 (ptr, method->signature->param_count);
765 for (j = 0; j < method->signature->param_count; j++)
766 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
769 g_ptr_array_free (methods, FALSE);
771 for (i = 0; i < klass->field.count; i++) {
772 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
775 WRITE_UINT32 (ptr, klass->fields [i].offset);
776 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
779 for (i = 0; i < klass->property.count; i++) {
780 if (!property_is_static (&klass->properties [i]))
783 if (klass->properties [i].get)
784 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
786 WRITE_UINT32 (ptr, 0);
787 WRITE_POINTER (ptr, klass->properties [i].get);
788 WRITE_POINTER (ptr, klass->properties [i].set);
791 for (i = 0; i < static_methods->len; i++) {
792 MonoMethod *method = g_ptr_array_index (static_methods, i);
795 WRITE_POINTER (ptr, method);
796 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
797 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
799 WRITE_UINT32 (ptr, 0);
800 WRITE_UINT32 (ptr, method->signature->param_count);
801 for (j = 0; j < method->signature->param_count; j++)
802 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
805 g_ptr_array_free (static_methods, FALSE);
807 for (i = 0; i < ctors->len; i++) {
808 MonoMethod *ctor = g_ptr_array_index (ctors, i);
811 WRITE_POINTER (ptr, ctor);
812 WRITE_UINT32 (ptr, 0);
813 WRITE_UINT32 (ptr, ctor->signature->param_count);
814 for (j = 0; j < ctor->signature->param_count; j++)
815 WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
818 g_ptr_array_free (ctors, FALSE);
820 if (klass->parent && (klass->parent != mono_defaults.object_class))
821 WRITE_UINT32 (ptr, write_class (table, klass->parent));
823 WRITE_UINT32 (ptr, 0);
825 if (ptr - old_ptr != data_size) {
826 g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
828 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
829 g_assert_not_reached ();
836 * Adds type `type' to the type table and returns its offset.
839 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
841 guint8 buffer [BUFSIZ], *ptr = buffer;
842 guint32 size, offset;
845 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
849 klass = mono_class_from_mono_type (type);
850 if (klass->init_pending)
852 mono_class_init (klass);
854 switch (type->type) {
856 return table->builtin_types->void_type->type_info;
858 case MONO_TYPE_BOOLEAN:
859 return table->builtin_types->boolean_type->type_info;
862 return table->builtin_types->sbyte_type->type_info;
865 return table->builtin_types->byte_type->type_info;
868 return table->builtin_types->char_type->type_info;
871 return table->builtin_types->int16_type->type_info;
874 return table->builtin_types->uint16_type->type_info;
877 return table->builtin_types->int32_type->type_info;
880 return table->builtin_types->uint32_type->type_info;
883 return table->builtin_types->int64_type->type_info;
886 return table->builtin_types->uint64_type->type_info;
889 return table->builtin_types->single_type->type_info;
892 return table->builtin_types->double_type->type_info;
894 case MONO_TYPE_STRING:
895 return table->builtin_types->string_type->type_info;
898 return table->builtin_types->int_type->type_info;
901 return table->builtin_types->uint_type->type_info;
903 case MONO_TYPE_SZARRAY: {
906 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
907 WRITE_UINT32 (ptr, sizeof (MonoArray));
908 g_assert (table->builtin_types->array_type->type_info != 0);
909 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
910 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
911 *ptr++ = sizeof (array.max_length);
912 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
913 WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
917 case MONO_TYPE_ARRAY: {
919 MonoArrayBounds bounds;
921 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
922 WRITE_UINT32 (ptr, sizeof (MonoArray));
923 g_assert (table->builtin_types->array_type->type_info != 0);
924 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
925 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
926 *ptr++ = sizeof (array.max_length);
927 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
928 *ptr++ = klass->rank;
929 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
930 *ptr++ = sizeof (MonoArrayBounds);
931 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
932 *ptr++ = sizeof (bounds.lower_bound);
933 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
934 *ptr++ = sizeof (bounds.length);
935 WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
939 case MONO_TYPE_VALUETYPE:
940 case MONO_TYPE_CLASS:
941 case MONO_TYPE_OBJECT:
942 return write_class (table, klass);
945 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
946 WRITE_UINT32 (ptr, sizeof (gpointer));
947 WRITE_UINT32 (ptr, write_type (table, type->data.type));
951 g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type);
952 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
953 WRITE_UINT32 (ptr, klass->instance_size);
954 WRITE_UINT32 (ptr, write_class (table, klass));
959 offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
960 memcpy (ptr, buffer, size);
965 MonoReflectionMethod *
966 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
970 method = mono_get_method (assembly->assembly->image, token, NULL);
972 return mono_method_get_object (mono_domain_get (), method, NULL);
976 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
978 return method->method->token;
982 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
986 klass = mono_class_get (assembly->assembly->image, token);
988 g_warning (G_STRLOC ": %x", token);
992 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
996 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
1004 MONO_CHECK_ARG_NULL (assembly);
1005 MONO_CHECK_ARG_NULL (signature);
1007 domain = mono_domain_get();
1008 image = assembly->assembly->image;
1010 ptr = mono_array_addr (signature, char, 0);
1011 g_assert (*ptr++ == 0x07);
1012 len = mono_metadata_decode_value (ptr, &ptr);
1013 g_assert (len == 1);
1015 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1017 return mono_type_get_object (domain, type);
1021 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
1023 if (mono_debugger_event_handler)
1024 (* mono_debugger_event_handler) (event, data, arg);
1028 mono_debugger_cleanup (void)
1030 /* Do nothing yet. */
1034 * Debugger breakpoint interface.
1036 * This interface is used to insert breakpoints on methods which are not yet JITed.
1037 * The debugging code keeps a list of all such breakpoints and automatically inserts the
1038 * breakpoint when the method is JITed.
1041 static GPtrArray *breakpoints = NULL;
1044 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
1046 static int last_breakpoint_id = 0;
1047 MonoDebuggerBreakpointInfo *info;
1049 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1051 info->index = ++last_breakpoint_id;
1054 breakpoints = g_ptr_array_new ();
1056 g_ptr_array_add (breakpoints, info);
1062 mono_debugger_remove_breakpoint (int breakpoint_id)
1069 for (i = 0; i < breakpoints->len; i++) {
1070 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1072 if (info->index != breakpoint_id)
1075 mono_method_desc_free (info->desc);
1076 g_ptr_array_remove (breakpoints, info);
1085 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1087 MonoMethodDesc *desc;
1089 desc = mono_method_desc_new (method_name, include_namespace);
1093 return mono_debugger_insert_breakpoint_full (desc);
1097 mono_debugger_method_has_breakpoint (MonoMethod *method)
1101 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1104 for (i = 0; i < breakpoints->len; i++) {
1105 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1107 if (!mono_method_desc_full_match (info->desc, method))
1117 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
1119 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
1123 get_exception_message (MonoObject *exc)
1125 char *message = NULL;
1131 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1132 klass = exc->vtable->klass;
1134 while (klass && method == NULL) {
1135 for (i = 0; i < klass->method.count; ++i) {
1136 method = klass->methods [i];
1137 if (!strcmp ("ToString", method->name) &&
1138 method->signature->param_count == 0 &&
1139 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1140 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1147 klass = klass->parent;
1152 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1154 message = mono_string_to_utf8 (str);
1161 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1166 if (method->klass->valuetype && (obj != NULL))
1167 obj = mono_value_box (mono_domain_get (), method->klass, obj);
1169 if (!strcmp (method->name, ".ctor")) {
1170 retval = obj = mono_object_new (mono_domain_get (), method->klass);
1172 mono_runtime_invoke (method, obj, params, exc);
1174 retval = mono_runtime_invoke (method, obj, params, exc);
1179 message = get_exception_message (*exc);
1181 *exc = (MonoObject *) mono_string_new_wrapper (message);
1189 mono_debugger_lookup_type (const gchar *type_name)
1193 mono_debugger_lock ();
1195 for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1196 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1201 name = g_strdup (type_name);
1202 type = mono_reflection_type_from_name (name, symfile->image);
1207 offset = write_type (mono_debugger_symbol_table, type);
1209 mono_debugger_unlock ();
1213 mono_debugger_unlock ();
1218 mono_debugger_lookup_assembly (const gchar *name)
1220 MonoAssembly *assembly;
1221 MonoImageOpenStatus status;
1224 mono_debugger_lock ();
1227 for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1228 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1230 if (!strcmp (symfile->image_file, name)) {
1231 mono_debugger_unlock ();
1236 assembly = mono_assembly_open (name, &status);
1238 if (status != MONO_IMAGE_OK) {
1239 g_warning (G_STRLOC ": Cannot open image `%s'", name);
1240 mono_debugger_unlock ();
1244 must_reload_symtabs = TRUE;