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/metadata/object-internals.h>
11 #include <mono/metadata/class-internals.h>
12 #include <mono/metadata/exception.h>
13 #include <mono/metadata/mono-debug.h>
14 #include <mono/metadata/mono-debug-debugger.h>
15 #include <mono/metadata/mono-endian.h>
17 #define SYMFILE_TABLE_CHUNK_SIZE 16
18 #define RANGE_TABLE_CHUNK_SIZE 256
19 #define CLASS_TABLE_CHUNK_SIZE 256
20 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
21 #define TYPE_TABLE_CHUNK_SIZE 65536
23 static guint32 debugger_lock_level = 0;
24 static CRITICAL_SECTION debugger_lock_mutex;
25 static gboolean mono_debugger_initialized = FALSE;
26 static MonoObject *last_exception = NULL;
28 static gboolean must_reload_symtabs = FALSE;
30 static GHashTable *images = NULL;
31 static GHashTable *type_table = NULL;
32 static GHashTable *class_table = NULL;
33 static GHashTable *class_info_table = NULL;
35 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
36 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
37 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
38 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
39 static guint32 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass);
41 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
42 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
44 #define WRITE_UINT32(ptr,value) G_STMT_START { \
45 * ((guint32 *) ptr) = value; \
49 #define WRITE_POINTER(ptr,value) G_STMT_START { \
50 * ((gpointer *) ptr) = value; \
51 ptr += sizeof (gpointer); \
54 #ifndef PLATFORM_WIN32
56 MonoDebuggerIOLayer mono_debugger_io_layer = {
57 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
58 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
59 WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
66 mono_debugger_lock (void)
68 if (!mono_debugger_initialized) {
69 debugger_lock_level++;
73 EnterCriticalSection (&debugger_lock_mutex);
74 debugger_lock_level++;
78 mono_debugger_unlock (void)
80 g_assert (debugger_lock_level > 0);
82 if (!mono_debugger_initialized) {
83 debugger_lock_level--;
87 if (debugger_lock_level == 1) {
88 if (must_reload_symtabs) {
89 mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, NULL, 0);
90 must_reload_symtabs = FALSE;
94 debugger_lock_level--;
95 LeaveCriticalSection (&debugger_lock_mutex);
98 static MonoDebuggerSymbolFile *
99 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
101 MonoDebuggerSymbolFile *symfile;
103 if (!table->symbol_files)
104 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
105 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
106 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
107 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
109 table->symbol_files = g_realloc (table->symbol_files, size);
112 symfile = g_new0 (MonoDebuggerSymbolFile, 1);
113 symfile->index = table->num_symbol_files;
114 symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
115 symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
116 table->symbol_files [table->num_symbol_files++] = symfile;
121 mono_debugger_initialize (MonoDomain *domain)
123 MonoDebuggerSymbolTable *symbol_table;
125 g_assert (!mono_debugger_initialized);
127 InitializeCriticalSection (&debugger_lock_mutex);
128 mono_debugger_initialized = TRUE;
130 mono_debugger_lock ();
132 symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
133 symbol_table->magic = MONO_DEBUGGER_MAGIC;
134 symbol_table->version = MONO_DEBUGGER_VERSION;
135 symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
137 symbol_table->domain = domain;
139 images = g_hash_table_new (g_direct_hash, g_direct_equal);
140 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
141 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
142 class_info_table = g_hash_table_new (g_direct_hash, g_direct_equal);
144 mono_debugger_symbol_table = symbol_table;
146 mono_debugger_unlock ();
149 MonoDebuggerSymbolFile *
150 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
152 MonoDebuggerSymbolFile *info;
154 g_assert (mono_debugger_initialized);
155 mono_debugger_lock ();
157 info = g_hash_table_lookup (images, handle->image);
159 mono_debugger_unlock ();
163 info = allocate_symbol_file_entry (mono_debugger_symbol_table);
164 info->symfile = handle->symfile;
165 info->image = handle->image;
166 info->image_file = handle->image_file;
168 g_hash_table_insert (images, handle->image, info);
169 mono_debugger_unlock ();
175 write_builtin_type (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerBuiltinTypeInfo *info)
177 guint8 buffer [BUFSIZ], *ptr = buffer;
180 g_assert (!klass->init_pending);
181 mono_class_init (klass);
183 switch (klass->byval_arg.type) {
185 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
186 WRITE_UINT32 (ptr, 0);
190 case MONO_TYPE_BOOLEAN:
202 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
203 WRITE_UINT32 (ptr, klass->instance_size - sizeof (MonoObject));
207 case MONO_TYPE_STRING: {
210 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
211 WRITE_UINT32 (ptr, klass->instance_size);
213 *ptr++ = (guint8*)&string.length - (guint8*)&string;
214 *ptr++ = sizeof (string.length);
215 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
222 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
223 WRITE_UINT32 (ptr, sizeof (void *));
227 case MONO_TYPE_VALUETYPE:
228 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
229 WRITE_UINT32 (ptr, klass->instance_size);
233 case MONO_TYPE_CLASS:
234 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
235 WRITE_UINT32 (ptr, klass->instance_size);
239 case MONO_TYPE_OBJECT:
240 g_assert (klass == mono_defaults.object_class);
241 *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
242 WRITE_UINT32 (ptr, klass->instance_size);
247 g_error (G_STRLOC ": Unknown builtin type %s.%s - %d", klass->name_space, klass->name, klass->byval_arg.type);
251 info->cinfo->type_info = info->type_info = allocate_type_entry (table, size, &info->type_data);
252 memcpy (info->type_data, buffer, size);
255 static MonoDebuggerBuiltinTypeInfo *
256 add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
258 MonoDebuggerClassInfo *cinfo;
259 MonoDebuggerBuiltinTypeInfo *info;
261 cinfo = g_new0 (MonoDebuggerClassInfo, 1);
262 cinfo->klass = klass;
264 cinfo->token = klass->element_class->type_token;
265 cinfo->rank = klass->rank;
267 cinfo->token = klass->type_token;
269 g_hash_table_insert (class_info_table, klass, cinfo);
271 info = g_new0 (MonoDebuggerBuiltinTypeInfo, 1);
275 write_builtin_type (mono_debugger_symbol_table, klass, info);
280 add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo *info)
282 info->class_info = write_class (mono_debugger_symbol_table, info->klass);
283 * (guint32 *) (info->type_data + 5) = info->class_info;
287 add_exception_class (MonoDebuggerSymbolFile *symfile, MonoException *exc)
289 mono_debugger_add_type (symfile, ((MonoObject *) exc)->vtable->klass);
292 MonoDebuggerBuiltinTypes *
293 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
295 MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
298 mono_debugger_symbol_table->corlib = symfile;
299 mono_debugger_symbol_table->builtin_types = types;
301 types->total_size = sizeof (MonoDebuggerBuiltinTypes);
302 types->type_info_size = sizeof (MonoDebuggerBuiltinTypeInfo);
304 types->object_type = add_builtin_type (symfile, mono_defaults.object_class);
305 types->byte_type = add_builtin_type (symfile, mono_defaults.byte_class);
306 types->void_type = add_builtin_type (symfile, mono_defaults.void_class);
307 types->boolean_type = add_builtin_type (symfile, mono_defaults.boolean_class);
308 types->sbyte_type = add_builtin_type (symfile, mono_defaults.sbyte_class);
309 types->int16_type = add_builtin_type (symfile, mono_defaults.int16_class);
310 types->uint16_type = add_builtin_type (symfile, mono_defaults.uint16_class);
311 types->int32_type = add_builtin_type (symfile, mono_defaults.int32_class);
312 types->uint32_type = add_builtin_type (symfile, mono_defaults.uint32_class);
313 types->int_type = add_builtin_type (symfile, mono_defaults.int_class);
314 types->uint_type = add_builtin_type (symfile, mono_defaults.uint_class);
315 types->int64_type = add_builtin_type (symfile, mono_defaults.int64_class);
316 types->uint64_type = add_builtin_type (symfile, mono_defaults.uint64_class);
317 types->single_type = add_builtin_type (symfile, mono_defaults.single_class);
318 types->double_type = add_builtin_type (symfile, mono_defaults.double_class);
319 types->char_type = add_builtin_type (symfile, mono_defaults.char_class);
320 types->string_type = add_builtin_type (symfile, mono_defaults.string_class);
322 types->enum_type = add_builtin_type (symfile, mono_defaults.enum_class);
323 types->array_type = add_builtin_type (symfile, mono_defaults.array_class);
324 types->exception_type = add_builtin_type (symfile, mono_defaults.exception_class);
326 add_builtin_type_2 (types->object_type);
327 add_builtin_type_2 (types->byte_type);
328 add_builtin_type_2 (types->void_type);
329 add_builtin_type_2 (types->boolean_type);
330 add_builtin_type_2 (types->sbyte_type);
331 add_builtin_type_2 (types->int16_type);
332 add_builtin_type_2 (types->uint16_type);
333 add_builtin_type_2 (types->int32_type);
334 add_builtin_type_2 (types->uint32_type);
335 add_builtin_type_2 (types->int_type);
336 add_builtin_type_2 (types->uint_type);
337 add_builtin_type_2 (types->int64_type);
338 add_builtin_type_2 (types->uint64_type);
339 add_builtin_type_2 (types->single_type);
340 add_builtin_type_2 (types->double_type);
341 add_builtin_type_2 (types->char_type);
342 add_builtin_type_2 (types->string_type);
343 add_builtin_type_2 (types->enum_type);
344 add_builtin_type_2 (types->array_type);
345 add_builtin_type_2 (types->exception_type);
347 add_exception_class (symfile, mono_get_exception_divide_by_zero ());
348 add_exception_class (symfile, mono_get_exception_security ());
349 add_exception_class (symfile, mono_get_exception_arithmetic ());
350 add_exception_class (symfile, mono_get_exception_overflow ());
351 add_exception_class (symfile, mono_get_exception_null_reference ());
352 add_exception_class (symfile, mono_get_exception_thread_abort ());
353 add_exception_class (symfile, mono_get_exception_invalid_cast ());
354 add_exception_class (symfile, mono_get_exception_index_out_of_range ());
355 add_exception_class (symfile, mono_get_exception_thread_abort ());
356 add_exception_class (symfile, mono_get_exception_index_out_of_range ());
357 add_exception_class (symfile, mono_get_exception_array_type_mismatch ());
358 add_exception_class (symfile, mono_get_exception_missing_method ());
359 add_exception_class (symfile, mono_get_exception_appdomain_unloaded ());
360 add_exception_class (symfile, mono_get_exception_stack_overflow ());
366 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
368 MonoDebuggerClassInfo *cinfo;
370 mono_debugger_lock ();
372 cinfo = g_hash_table_lookup (class_info_table, klass);
374 mono_debugger_unlock ();
378 symfile->generation++;
380 cinfo = allocate_class_entry (symfile);
381 cinfo->klass = klass;
383 cinfo->token = klass->element_class->type_token;
384 cinfo->rank = klass->rank;
386 cinfo->token = klass->type_token;
387 g_hash_table_insert (class_info_table, klass, cinfo);
389 cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
391 must_reload_symtabs = TRUE;
392 mono_debugger_unlock ();
396 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
397 MonoDebugMethodJitInfo *jit)
399 MonoSymbolFileMethodAddress *address;
400 MonoSymbolFileLexicalBlockEntry *block;
401 MonoDebugVarInfo *var_table;
402 MonoDebuggerRangeInfo *range;
403 MonoMethodHeader *header;
404 guint32 size, num_variables, variable_size, variable_offset;
405 guint32 type_size, type_offset, *type_index_table, has_this;
406 guint32 line_size, line_offset, block_offset, block_size;
407 MonoDebugLexicalBlockEntry *block_table;
408 MonoDebugLineNumberEntry *line_table;
413 if (!symfile->symfile->method_hash)
416 header = ((MonoMethodNormal *) minfo->method)->header;
418 symfile->generation++;
420 size = sizeof (MonoSymbolFileMethodAddress);
422 num_variables = read32(&(minfo->entry->_num_parameters)) + read32(&(minfo->entry->_num_locals));
423 has_this = jit->this_var != NULL;
425 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
426 variable_offset = size;
427 size += variable_size;
429 type_size = (num_variables + 1) * sizeof (gpointer);
433 if (jit->line_numbers) {
435 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
439 block_size = read32(&(minfo->entry->_num_lexical_blocks)) * sizeof (MonoSymbolFileLexicalBlockEntry);
443 address = g_malloc0 (size);
444 ptr = (guint8 *) address;
446 block = (MonoSymbolFileLexicalBlockEntry *)
447 (symfile->symfile->raw_contents + read32(&(minfo->entry->_lexical_block_table_offset)));
448 block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
450 for (i = 0; i < read32(&(minfo->entry->_num_lexical_blocks)); i++, block++) {
451 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_start_offset)));
452 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_end_offset)));
455 address->size = size;
456 address->has_this = has_this;
457 address->start_address = jit->code_start;
458 address->end_address = jit->code_start + jit->code_size;
459 address->method_start_address = address->start_address + jit->prologue_end;
460 address->method_end_address = address->start_address + jit->epilogue_begin;
461 address->wrapper_address = jit->wrapper_addr;
462 address->variable_table_offset = variable_offset;
463 address->type_table_offset = type_offset;
464 address->lexical_block_table_offset = block_offset;
466 if (jit->line_numbers) {
467 address->num_line_numbers = jit->line_numbers->len;
468 address->line_number_offset = line_offset;
470 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
471 memcpy (line_table, jit->line_numbers->data, line_size);
474 range = allocate_range_entry (symfile);
475 range->index = minfo->index;
476 range->start_address = address->start_address;
477 range->end_address = address->end_address;
478 range->dynamic_data = address;
479 range->dynamic_size = size;
481 if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
482 (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
483 (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
486 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
487 type_table = (guint32 *) (ptr + type_offset);
489 type_index_table = (guint32 *)
490 (symfile->symfile->raw_contents + read32(&(minfo->entry->_type_index_table_offset)));
493 *var_table++ = *jit->this_var;
494 *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
496 if (jit->num_params != read32(&(minfo->entry->_num_parameters))) {
497 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
498 minfo->method->klass->name, minfo->method->name, jit->num_params,
499 read32(&(minfo->entry->_num_parameters)));
500 var_table += read32(&(minfo->entry->_num_parameters));
502 for (i = 0; i < jit->num_params; i++) {
503 *var_table++ = jit->params [i];
504 *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
508 if (jit->num_locals < read32(&(minfo->entry->_num_locals))) {
509 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
510 minfo->method->klass->name, minfo->method->name, jit->num_locals,
511 read32(&(minfo->entry->_num_locals)));
512 var_table += read32(&(minfo->entry->_num_locals));
514 g_assert ((header != NULL) || (minfo->entry->_num_locals == 0));
515 for (i = 0; i < read32(&(minfo->entry->_num_locals)); i++) {
516 *var_table++ = jit->locals [i];
517 *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
521 must_reload_symtabs = TRUE;
524 static MonoDebuggerRangeInfo *
525 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
527 MonoDebuggerRangeInfo *retval;
528 guint32 size, chunks;
530 if (!symfile->range_table) {
531 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
532 symfile->range_table = g_malloc0 (size);
533 symfile->num_range_entries = 1;
534 return symfile->range_table;
537 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
538 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
539 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
541 symfile->range_table = g_realloc (symfile->range_table, size);
544 retval = symfile->range_table + symfile->num_range_entries;
545 symfile->num_range_entries++;
549 static MonoDebuggerClassInfo *
550 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
552 MonoDebuggerClassInfo *retval;
553 guint32 size, chunks;
555 if (!symfile->class_table) {
556 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
557 symfile->class_table = g_malloc0 (size);
558 symfile->num_class_entries = 1;
559 return symfile->class_table;
562 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
563 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
564 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
566 symfile->class_table = g_realloc (symfile->class_table, size);
569 retval = symfile->class_table + symfile->num_class_entries;
570 symfile->num_class_entries++;
575 * Allocate a new entry of size `size' in the type table.
576 * Returns the global offset which is to be used to reference this type and
577 * a pointer (in the `ptr' argument) which is to be used to write the type.
580 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
585 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
586 g_assert (ptr != NULL);
588 /* Initialize things if necessary. */
589 if (!table->current_type_table) {
590 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
591 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
592 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
593 table->type_table_offset = 1;
597 /* First let's check whether there's still enough room in the current_type_table. */
598 if (table->type_table_offset + size + 4 < table->type_table_size) {
599 retval = table->type_table_offset;
600 table->type_table_offset += size + 4;
601 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
602 *(gint32 *) data = size;
603 data += sizeof(gint32);
608 /* Add the current_type_table to the type_tables vector and ... */
609 if (!table->type_tables) {
610 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
611 table->type_tables = g_malloc0 (tsize);
614 if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
615 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
616 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
618 table->type_tables = g_realloc (table->type_tables, tsize);
621 table->type_tables [table->num_type_tables++] = table->current_type_table;
623 /* .... allocate a new current_type_table. */
624 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
625 table->type_table_start = table->type_table_offset = table->type_table_size;
626 table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
632 property_is_static (MonoProperty *prop)
640 return method->flags & METHOD_ATTRIBUTE_STATIC;
644 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
646 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
647 GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL;
648 int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
649 int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
650 int num_ctors = 0, num_ctor_params = 0;
651 int field_info_size = 0, static_field_info_size = 0, property_info_size = 0;
652 int static_property_info_size = 0, method_info_size = 0, static_method_info_size = 0;
653 int ctor_info_size = 0, iface_info_size = 0;
654 guint32 size, data_size, offset, data_offset;
655 GHashTable *method_slots = NULL;
658 g_assert (!klass->init_pending);
659 mono_class_init (klass);
661 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
665 if (klass->enumtype) {
666 offset = allocate_type_entry (table, 13, &ptr);
667 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
669 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
670 WRITE_UINT32 (ptr, klass->instance_size);
671 WRITE_UINT32 (ptr, table->builtin_types->enum_type->type_info);
672 WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
676 for (i = 0; i < klass->field.count; i++)
677 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
682 for (i = 0; i < klass->property.count; i++)
683 if (!property_is_static (&klass->properties [i]))
686 ++num_static_properties;
688 method_slots = g_hash_table_new (NULL, NULL);
689 methods = g_ptr_array_new ();
690 static_methods = g_ptr_array_new ();
691 ctors = g_ptr_array_new ();
693 for (i = 0; i < klass->method.count; i++) {
694 MonoMethod *method = klass->methods [i];
696 if (!strcmp (method->name, ".cctor"))
698 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
701 if (!strcmp (method->name, ".ctor")) {
703 num_ctor_params += method->signature->param_count;
704 g_ptr_array_add (ctors, method);
708 if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
711 if (method->slot != -1) {
712 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
714 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
717 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
718 ++num_static_methods;
719 num_static_params += method->signature->param_count;
720 g_ptr_array_add (static_methods, method);
723 num_params += method->signature->param_count;
724 g_ptr_array_add (methods, method);
728 g_hash_table_destroy (method_slots);
730 field_info_size = num_fields * 8;
731 static_field_info_size = num_static_fields * 8;
732 property_info_size = num_properties * (4 + 2 * sizeof (gpointer));
733 static_property_info_size = num_static_properties * (4 + 2 * sizeof (gpointer));
734 method_info_size = num_methods * (4 + 2 * sizeof (gpointer)) + num_params * 4;
735 static_method_info_size = num_static_methods * (4 + 2 * sizeof (gpointer)) +
736 num_static_params * 4;
737 ctor_info_size = num_ctors * (4 + 2 * sizeof (gpointer)) + num_ctor_params * 4;
738 iface_info_size = klass->interface_count * 4;
740 size = 74 + sizeof (gpointer) + field_info_size + static_field_info_size +
741 property_info_size + static_property_info_size + method_info_size +
742 static_method_info_size + ctor_info_size + iface_info_size;
746 offset = allocate_type_entry (table, data_size, &ptr);
749 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
751 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
753 if (klass->valuetype)
754 base_offset = - sizeof (MonoObject);
756 WRITE_UINT32 (ptr, klass->instance_size + base_offset);
757 *ptr++ = klass->valuetype;
758 WRITE_POINTER (ptr, klass);
760 WRITE_UINT32 (ptr, num_fields);
761 WRITE_UINT32 (ptr, data_offset);
762 data_offset += field_info_size;
763 WRITE_UINT32 (ptr, num_properties);
764 WRITE_UINT32 (ptr, data_offset);
765 data_offset += property_info_size;
766 WRITE_UINT32 (ptr, num_methods);
767 WRITE_UINT32 (ptr, data_offset);
768 data_offset += method_info_size;
769 WRITE_UINT32 (ptr, num_static_fields);
770 WRITE_UINT32 (ptr, data_offset);
771 data_offset += static_field_info_size;
772 WRITE_UINT32 (ptr, num_static_properties);
773 WRITE_UINT32 (ptr, data_offset);
774 data_offset += static_property_info_size;
775 WRITE_UINT32 (ptr, num_static_methods);
776 WRITE_UINT32 (ptr, data_offset);
777 data_offset += static_method_info_size;
778 WRITE_UINT32 (ptr, num_ctors);
779 WRITE_UINT32 (ptr, data_offset);
780 data_offset += ctor_info_size;
781 WRITE_UINT32 (ptr, klass->interface_count);
782 WRITE_UINT32 (ptr, data_offset);
783 data_offset += iface_info_size;
785 if (klass->parent && (klass->parent != mono_defaults.object_class))
786 WRITE_UINT32 (ptr, write_class (table, klass->parent));
788 WRITE_UINT32 (ptr, 0);
790 for (i = 0; i < klass->field.count; i++) {
791 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
794 WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
795 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
798 for (i = 0; i < klass->property.count; i++) {
799 if (property_is_static (&klass->properties [i]))
802 if (klass->properties [i].get)
803 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
805 WRITE_UINT32 (ptr, 0);
806 WRITE_POINTER (ptr, klass->properties [i].get);
807 WRITE_POINTER (ptr, klass->properties [i].set);
810 for (i = 0; i < methods->len; i++) {
811 MonoMethod *method = g_ptr_array_index (methods, i);
814 WRITE_POINTER (ptr, method);
815 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
816 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
818 WRITE_UINT32 (ptr, 0);
819 WRITE_UINT32 (ptr, method->signature->param_count);
820 for (j = 0; j < method->signature->param_count; j++)
821 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
824 g_ptr_array_free (methods, FALSE);
826 for (i = 0; i < klass->field.count; i++) {
827 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
830 WRITE_UINT32 (ptr, klass->fields [i].offset);
831 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
834 for (i = 0; i < klass->property.count; i++) {
835 if (!property_is_static (&klass->properties [i]))
838 if (klass->properties [i].get)
839 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
841 WRITE_UINT32 (ptr, 0);
842 WRITE_POINTER (ptr, klass->properties [i].get);
843 WRITE_POINTER (ptr, klass->properties [i].set);
846 for (i = 0; i < static_methods->len; i++) {
847 MonoMethod *method = g_ptr_array_index (static_methods, i);
850 WRITE_POINTER (ptr, method);
851 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
852 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
854 WRITE_UINT32 (ptr, 0);
855 WRITE_UINT32 (ptr, method->signature->param_count);
856 for (j = 0; j < method->signature->param_count; j++)
857 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
860 g_ptr_array_free (static_methods, FALSE);
862 for (i = 0; i < ctors->len; i++) {
863 MonoMethod *ctor = g_ptr_array_index (ctors, i);
866 WRITE_POINTER (ptr, ctor);
867 WRITE_UINT32 (ptr, 0);
868 WRITE_UINT32 (ptr, ctor->signature->param_count);
869 for (j = 0; j < ctor->signature->param_count; j++)
870 WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
873 g_ptr_array_free (ctors, FALSE);
875 for (i = 0; i < klass->interface_count; i++)
876 WRITE_UINT32 (ptr, write_class (table, klass->interfaces [i]));
878 if (ptr - old_ptr != data_size) {
879 g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
881 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
882 g_assert_not_reached ();
889 * Adds type `type' to the type table and returns its offset.
892 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
894 guint8 buffer [BUFSIZ], *ptr = buffer;
895 guint32 size, offset;
898 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
902 klass = mono_class_from_mono_type (type);
903 if (klass->init_pending)
905 mono_class_init (klass);
907 switch (type->type) {
909 return table->builtin_types->void_type->type_info;
911 case MONO_TYPE_BOOLEAN:
912 return table->builtin_types->boolean_type->type_info;
915 return table->builtin_types->sbyte_type->type_info;
918 return table->builtin_types->byte_type->type_info;
921 return table->builtin_types->char_type->type_info;
924 return table->builtin_types->int16_type->type_info;
927 return table->builtin_types->uint16_type->type_info;
930 return table->builtin_types->int32_type->type_info;
933 return table->builtin_types->uint32_type->type_info;
936 return table->builtin_types->int64_type->type_info;
939 return table->builtin_types->uint64_type->type_info;
942 return table->builtin_types->single_type->type_info;
945 return table->builtin_types->double_type->type_info;
947 case MONO_TYPE_STRING:
948 return table->builtin_types->string_type->type_info;
951 return table->builtin_types->int_type->type_info;
954 return table->builtin_types->uint_type->type_info;
956 case MONO_TYPE_SZARRAY: {
959 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
960 WRITE_UINT32 (ptr, sizeof (MonoArray));
961 g_assert (table->builtin_types->array_type->type_info != 0);
962 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
963 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
964 *ptr++ = sizeof (array.max_length);
965 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
966 WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
970 case MONO_TYPE_ARRAY: {
972 MonoArrayBounds bounds;
974 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
975 WRITE_UINT32 (ptr, sizeof (MonoArray));
976 g_assert (table->builtin_types->array_type->type_info != 0);
977 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
978 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
979 *ptr++ = sizeof (array.max_length);
980 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
981 *ptr++ = klass->rank;
982 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
983 *ptr++ = sizeof (MonoArrayBounds);
984 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
985 *ptr++ = sizeof (bounds.lower_bound);
986 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
987 *ptr++ = sizeof (bounds.length);
988 WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
992 case MONO_TYPE_VALUETYPE:
993 case MONO_TYPE_CLASS:
994 case MONO_TYPE_OBJECT:
995 return write_class (table, klass);
998 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
999 WRITE_UINT32 (ptr, sizeof (gpointer));
1000 WRITE_UINT32 (ptr, write_type (table, type->data.type));
1004 /* g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type); */
1005 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
1006 WRITE_UINT32 (ptr, klass->instance_size);
1007 WRITE_UINT32 (ptr, write_class (table, klass));
1011 size = ptr - buffer;
1012 offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
1013 memcpy (ptr, buffer, size);
1018 MonoReflectionMethod *
1019 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
1023 method = mono_get_method (mono_assembly_get_image (assembly->assembly), token, NULL);
1025 return mono_method_get_object (mono_domain_get (), method, NULL);
1029 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
1031 return method->method->token;
1034 MonoReflectionType *
1035 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
1039 klass = mono_class_get (mono_assembly_get_image (assembly->assembly), token);
1041 g_warning (G_STRLOC ": %x", token);
1045 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
1048 MonoReflectionType *
1049 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
1057 MONO_CHECK_ARG_NULL (assembly);
1058 MONO_CHECK_ARG_NULL (signature);
1060 domain = mono_domain_get();
1061 image = mono_assembly_get_image (assembly->assembly);
1063 ptr = mono_array_addr (signature, char, 0);
1064 g_assert (*ptr++ == 0x07);
1065 len = mono_metadata_decode_value (ptr, &ptr);
1066 g_assert (len == 1);
1068 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1070 return mono_type_get_object (domain, type);
1074 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
1076 if (mono_debugger_event_handler)
1077 (* mono_debugger_event_handler) (event, data, arg);
1081 mono_debugger_cleanup (void)
1083 /* Do nothing yet. */
1087 * Debugger breakpoint interface.
1089 * This interface is used to insert breakpoints on methods which are not yet JITed.
1090 * The debugging code keeps a list of all such breakpoints and automatically inserts the
1091 * breakpoint when the method is JITed.
1094 static GPtrArray *breakpoints = NULL;
1097 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
1099 static int last_breakpoint_id = 0;
1100 MonoDebuggerBreakpointInfo *info;
1102 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1104 info->index = ++last_breakpoint_id;
1107 breakpoints = g_ptr_array_new ();
1109 g_ptr_array_add (breakpoints, info);
1115 mono_debugger_remove_breakpoint (int breakpoint_id)
1122 for (i = 0; i < breakpoints->len; i++) {
1123 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1125 if (info->index != breakpoint_id)
1128 mono_method_desc_free (info->desc);
1129 g_ptr_array_remove (breakpoints, info);
1138 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1140 MonoMethodDesc *desc;
1142 desc = mono_method_desc_new (method_name, include_namespace);
1146 return mono_debugger_insert_breakpoint_full (desc);
1150 mono_debugger_method_has_breakpoint (MonoMethod *method)
1154 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1157 for (i = 0; i < breakpoints->len; i++) {
1158 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1160 if (!mono_method_desc_full_match (info->desc, method))
1170 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
1172 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
1176 mono_debugger_unhandled_exception (gpointer addr, MonoObject *exc)
1178 if (!mono_debugger_initialized)
1181 // Prevent the object from being finalized.
1182 last_exception = exc;
1183 mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION, exc, addr);
1188 get_exception_message (MonoObject *exc)
1190 char *message = NULL;
1196 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1197 klass = exc->vtable->klass;
1199 while (klass && method == NULL) {
1200 for (i = 0; i < klass->method.count; ++i) {
1201 method = klass->methods [i];
1202 if (!strcmp ("ToString", method->name) &&
1203 method->signature->param_count == 0 &&
1204 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1205 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1212 klass = klass->parent;
1217 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1219 message = mono_string_to_utf8 (str);
1226 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1231 if (method->klass->valuetype && (obj != NULL))
1232 obj = mono_value_box (mono_domain_get (), method->klass, obj);
1234 if (!strcmp (method->name, ".ctor")) {
1235 retval = obj = mono_object_new (mono_domain_get (), method->klass);
1237 mono_runtime_invoke (method, obj, params, exc);
1239 retval = mono_runtime_invoke (method, obj, params, exc);
1241 if (!exc || (*exc == NULL))
1244 message = get_exception_message (*exc);
1246 *exc = (MonoObject *) mono_string_new_wrapper (message);
1254 mono_debugger_lookup_type (const gchar *type_name)
1258 mono_debugger_lock ();
1260 for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1261 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1266 name = g_strdup (type_name);
1267 type = mono_reflection_type_from_name (name, symfile->image);
1272 offset = write_type (mono_debugger_symbol_table, type);
1274 mono_debugger_unlock ();
1278 mono_debugger_unlock ();
1283 mono_debugger_lookup_assembly (const gchar *name)
1285 MonoAssembly *assembly;
1286 MonoImageOpenStatus status;
1289 mono_debugger_lock ();
1292 for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1293 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1295 if (!strcmp (symfile->image_file, name)) {
1296 mono_debugger_unlock ();
1301 assembly = mono_assembly_open (name, &status);
1303 if (status != MONO_IMAGE_OK) {
1304 g_warning (G_STRLOC ": Cannot open image `%s'", name);
1305 mono_debugger_unlock ();
1309 must_reload_symtabs = TRUE;