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>
12 #define SYMFILE_TABLE_CHUNK_SIZE 16
13 #define RANGE_TABLE_CHUNK_SIZE 256
14 #define CLASS_TABLE_CHUNK_SIZE 256
15 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
16 #define TYPE_TABLE_CHUNK_SIZE 65536
18 static CRITICAL_SECTION debugger_lock_mutex;
19 static gboolean mono_debugger_initialized = FALSE;
21 static GHashTable *images = NULL;
22 static GHashTable *type_table = NULL;
23 static GHashTable *class_table = NULL;
24 static GHashTable *class_info_table = NULL;
26 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
27 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
28 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
29 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
30 static guint32 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass);
32 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
33 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
35 #define WRITE_UINT32(ptr,value) G_STMT_START { \
36 * ((guint32 *) ptr) = value; \
40 #define WRITE_POINTER(ptr,value) G_STMT_START { \
41 * ((gpointer *) ptr) = value; \
42 ptr += sizeof (gpointer); \
45 #ifndef PLATFORM_WIN32
47 MonoDebuggerIOLayer mono_debugger_io_layer = {
48 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
49 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
50 WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
56 mono_debugger_lock (void)
58 if (mono_debugger_initialized)
59 EnterCriticalSection (&debugger_lock_mutex);
63 mono_debugger_unlock (void)
65 if (mono_debugger_initialized)
66 LeaveCriticalSection (&debugger_lock_mutex);
69 static MonoDebuggerSymbolFile *
70 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
72 MonoDebuggerSymbolFile *symfile;
74 if (!table->symbol_files)
75 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
76 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
77 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
78 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
80 table->symbol_files = g_realloc (table->symbol_files, size);
83 symfile = g_new0 (MonoDebuggerSymbolFile, 1);
84 symfile->index = table->num_symbol_files;
85 symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
86 symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
87 table->symbol_files [table->num_symbol_files++] = symfile;
92 mono_debugger_initialize (MonoDomain *domain)
94 MonoDebuggerSymbolTable *symbol_table;
96 g_assert (!mono_debugger_initialized);
98 InitializeCriticalSection (&debugger_lock_mutex);
100 mono_debugger_lock ();
102 symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
103 symbol_table->magic = MONO_DEBUGGER_MAGIC;
104 symbol_table->version = MONO_DEBUGGER_VERSION;
105 symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
107 symbol_table->domain = domain;
109 images = g_hash_table_new (g_direct_hash, g_direct_equal);
110 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
111 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
112 class_info_table = g_hash_table_new (g_direct_hash, g_direct_equal);
114 mono_debugger_symbol_table = symbol_table;
115 mono_debugger_initialized = TRUE;
117 mono_debugger_unlock ();
120 MonoDebuggerSymbolFile *
121 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
123 MonoDebuggerSymbolFile *info;
125 g_assert (mono_debugger_initialized);
126 mono_debugger_lock ();
128 info = g_hash_table_lookup (images, handle->image);
132 info = allocate_symbol_file_entry (mono_debugger_symbol_table);
133 info->symfile = handle->symfile;
134 info->image = handle->image;
135 info->image_file = handle->image_file;
137 g_hash_table_insert (images, handle->image, info);
138 mono_debugger_unlock ();
144 write_builtin_type (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerBuiltinTypeInfo *info)
146 guint8 buffer [BUFSIZ], *ptr = buffer;
149 g_assert (!klass->init_pending);
150 mono_class_init (klass);
152 switch (klass->byval_arg.type) {
154 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
155 WRITE_UINT32 (ptr, 0);
159 case MONO_TYPE_BOOLEAN:
171 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
172 WRITE_UINT32 (ptr, klass->instance_size - sizeof (MonoObject));
176 case MONO_TYPE_STRING: {
179 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
180 WRITE_UINT32 (ptr, klass->instance_size);
182 *ptr++ = (guint8*)&string.length - (guint8*)&string;
183 *ptr++ = sizeof (string.length);
184 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
191 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
192 WRITE_UINT32 (ptr, sizeof (void *));
196 case MONO_TYPE_VALUETYPE:
197 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
198 WRITE_UINT32 (ptr, klass->instance_size);
202 case MONO_TYPE_CLASS:
203 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
204 WRITE_UINT32 (ptr, klass->instance_size);
208 case MONO_TYPE_OBJECT:
209 g_assert (klass == mono_defaults.object_class);
210 *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
211 WRITE_UINT32 (ptr, klass->instance_size);
216 g_error (G_STRLOC ": Unknown builtin type %s.%s - %d", klass->name_space, klass->name, klass->byval_arg.type);
220 info->cinfo->type_info = info->type_info = allocate_type_entry (table, size, &info->type_data);
221 memcpy (info->type_data, buffer, size);
224 static MonoDebuggerBuiltinTypeInfo *
225 add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
227 MonoDebuggerClassInfo *cinfo;
228 MonoDebuggerBuiltinTypeInfo *info;
230 cinfo = g_new0 (MonoDebuggerClassInfo, 1);
231 cinfo->klass = klass;
233 cinfo->token = klass->element_class->type_token;
234 cinfo->rank = klass->rank;
236 cinfo->token = klass->type_token;
238 g_hash_table_insert (class_info_table, klass, cinfo);
240 info = g_new0 (MonoDebuggerBuiltinTypeInfo, 1);
244 write_builtin_type (mono_debugger_symbol_table, klass, info);
249 add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo *info)
251 info->class_info = write_class (mono_debugger_symbol_table, info->klass);
252 * (guint32 *) (info->type_data + 5) = info->class_info;
255 MonoDebuggerBuiltinTypes *
256 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
258 MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
260 mono_debugger_symbol_table->corlib = symfile;
261 mono_debugger_symbol_table->builtin_types = types;
263 types->total_size = sizeof (MonoDebuggerBuiltinTypes);
264 types->type_info_size = sizeof (MonoDebuggerBuiltinTypeInfo);
266 types->object_type = add_builtin_type (symfile, mono_defaults.object_class);
267 types->byte_type = add_builtin_type (symfile, mono_defaults.byte_class);
268 types->void_type = add_builtin_type (symfile, mono_defaults.void_class);
269 types->boolean_type = add_builtin_type (symfile, mono_defaults.boolean_class);
270 types->sbyte_type = add_builtin_type (symfile, mono_defaults.sbyte_class);
271 types->int16_type = add_builtin_type (symfile, mono_defaults.int16_class);
272 types->uint16_type = add_builtin_type (symfile, mono_defaults.uint16_class);
273 types->int32_type = add_builtin_type (symfile, mono_defaults.int32_class);
274 types->uint32_type = add_builtin_type (symfile, mono_defaults.uint32_class);
275 types->int_type = add_builtin_type (symfile, mono_defaults.int_class);
276 types->uint_type = add_builtin_type (symfile, mono_defaults.uint_class);
277 types->int64_type = add_builtin_type (symfile, mono_defaults.int64_class);
278 types->uint64_type = add_builtin_type (symfile, mono_defaults.uint64_class);
279 types->single_type = add_builtin_type (symfile, mono_defaults.single_class);
280 types->double_type = add_builtin_type (symfile, mono_defaults.double_class);
281 types->char_type = add_builtin_type (symfile, mono_defaults.char_class);
282 types->string_type = add_builtin_type (symfile, mono_defaults.string_class);
284 types->enum_type = add_builtin_type (symfile, mono_defaults.enum_class);
285 types->array_type = add_builtin_type (symfile, mono_defaults.array_class);
286 types->exception_type = add_builtin_type (symfile, mono_defaults.exception_class);
288 add_builtin_type_2 (types->object_type);
289 add_builtin_type_2 (types->byte_type);
290 add_builtin_type_2 (types->void_type);
291 add_builtin_type_2 (types->boolean_type);
292 add_builtin_type_2 (types->sbyte_type);
293 add_builtin_type_2 (types->int16_type);
294 add_builtin_type_2 (types->uint16_type);
295 add_builtin_type_2 (types->int32_type);
296 add_builtin_type_2 (types->uint32_type);
297 add_builtin_type_2 (types->int_type);
298 add_builtin_type_2 (types->uint_type);
299 add_builtin_type_2 (types->int64_type);
300 add_builtin_type_2 (types->uint64_type);
301 add_builtin_type_2 (types->single_type);
302 add_builtin_type_2 (types->double_type);
303 add_builtin_type_2 (types->char_type);
304 add_builtin_type_2 (types->string_type);
305 add_builtin_type_2 (types->enum_type);
306 add_builtin_type_2 (types->array_type);
307 add_builtin_type_2 (types->exception_type);
313 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
315 MonoDebuggerClassInfo *cinfo;
317 mono_debugger_lock ();
319 cinfo = g_hash_table_lookup (class_info_table, klass);
321 mono_debugger_unlock ();
325 symfile->generation++;
327 cinfo = allocate_class_entry (symfile);
328 cinfo->klass = klass;
330 cinfo->token = klass->element_class->type_token;
331 cinfo->rank = klass->rank;
333 cinfo->token = klass->type_token;
334 g_hash_table_insert (class_info_table, klass, cinfo);
336 cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
338 mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, NULL, 0);
339 mono_debugger_unlock ();
343 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
344 MonoDebugMethodJitInfo *jit)
346 MonoSymbolFileMethodAddress *address;
347 MonoSymbolFileLexicalBlockEntry *block;
348 MonoDebugVarInfo *var_table;
349 MonoDebuggerRangeInfo *range;
350 MonoMethodHeader *header;
351 guint32 size, num_variables, variable_size, variable_offset;
352 guint32 type_size, type_offset, *type_index_table, has_this;
353 guint32 line_size, line_offset, block_offset, block_size;
354 MonoDebugLexicalBlockEntry *block_table;
355 MonoDebugLineNumberEntry *line_table;
360 if (!symfile->symfile->method_hash)
363 header = ((MonoMethodNormal *) minfo->method)->header;
365 symfile->generation++;
367 size = sizeof (MonoSymbolFileMethodAddress);
369 num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
370 has_this = jit->this_var != NULL;
372 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
373 variable_offset = size;
374 size += variable_size;
376 type_size = (num_variables + 1) * sizeof (gpointer);
380 if (jit->line_numbers) {
382 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
386 block_size = minfo->entry->num_lexical_blocks * sizeof (MonoSymbolFileLexicalBlockEntry);
390 address = g_malloc0 (size);
391 ptr = (guint8 *) address;
393 block = (MonoSymbolFileLexicalBlockEntry *)
394 (symfile->symfile->raw_contents + minfo->entry->lexical_block_table_offset);
395 block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
397 for (i = 0; i < minfo->entry->num_lexical_blocks; i++, block++) {
398 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, block->start_offset);
399 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, block->end_offset);
402 address->size = size;
403 address->has_this = has_this;
404 address->start_address = jit->code_start;
405 address->end_address = jit->code_start + jit->code_size;
406 address->method_start_address = address->start_address + jit->prologue_end;
407 address->method_end_address = address->start_address + jit->epilogue_begin;
408 address->wrapper_address = jit->wrapper_addr;
409 address->variable_table_offset = variable_offset;
410 address->type_table_offset = type_offset;
411 address->lexical_block_table_offset = block_offset;
413 if (jit->line_numbers) {
414 address->num_line_numbers = jit->line_numbers->len;
415 address->line_number_offset = line_offset;
417 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
418 memcpy (line_table, jit->line_numbers->data, line_size);
421 range = allocate_range_entry (symfile);
422 range->index = minfo->index;
423 range->start_address = address->start_address;
424 range->end_address = address->end_address;
425 range->dynamic_data = address;
426 range->dynamic_size = size;
428 if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
429 (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
430 (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
433 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
434 type_table = (guint32 *) (ptr + type_offset);
436 type_index_table = (guint32 *)
437 (symfile->symfile->raw_contents + minfo->entry->type_index_table_offset);
440 *var_table++ = *jit->this_var;
441 *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
443 if (jit->num_params != minfo->entry->num_parameters) {
444 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
445 minfo->method->klass->name, minfo->method->name, jit->num_params,
446 minfo->entry->num_parameters);
447 var_table += minfo->entry->num_parameters;
449 for (i = 0; i < jit->num_params; i++) {
450 *var_table++ = jit->params [i];
451 *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
455 if (jit->num_locals < minfo->entry->num_locals) {
456 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
457 minfo->method->klass->name, minfo->method->name, jit->num_locals,
458 minfo->entry->num_locals);
459 var_table += minfo->entry->num_locals;
461 g_assert ((header != NULL) || (minfo->entry->num_locals == 0));
462 for (i = 0; i < minfo->entry->num_locals; i++) {
463 *var_table++ = jit->locals [i];
464 *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
468 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, NULL, 0);
471 static MonoDebuggerRangeInfo *
472 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
474 MonoDebuggerRangeInfo *retval;
475 guint32 size, chunks;
477 if (!symfile->range_table) {
478 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
479 symfile->range_table = g_malloc0 (size);
480 symfile->num_range_entries = 1;
481 return symfile->range_table;
484 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
485 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
486 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
488 symfile->range_table = g_realloc (symfile->range_table, size);
491 retval = symfile->range_table + symfile->num_range_entries;
492 symfile->num_range_entries++;
496 static MonoDebuggerClassInfo *
497 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
499 MonoDebuggerClassInfo *retval;
500 guint32 size, chunks;
502 if (!symfile->class_table) {
503 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
504 symfile->class_table = g_malloc0 (size);
505 symfile->num_class_entries = 1;
506 return symfile->class_table;
509 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
510 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
511 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
513 symfile->class_table = g_realloc (symfile->class_table, size);
516 retval = symfile->class_table + symfile->num_class_entries;
517 symfile->num_class_entries++;
522 * Allocate a new entry of size `size' in the type table.
523 * Returns the global offset which is to be used to reference this type and
524 * a pointer (in the `ptr' argument) which is to be used to write the type.
527 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
532 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
533 g_assert (ptr != NULL);
535 /* Initialize things if necessary. */
536 if (!table->current_type_table) {
537 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
538 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
539 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
540 table->type_table_offset = 1;
544 /* First let's check whether there's still enough room in the current_type_table. */
545 if (table->type_table_offset + size + 4 < table->type_table_size) {
546 retval = table->type_table_offset;
547 table->type_table_offset += size + 4;
548 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
549 *(gint32 *) data = size;
550 data += sizeof(gint32);
555 /* Add the current_type_table to the type_tables vector and ... */
556 if (!table->type_tables) {
557 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
558 table->type_tables = g_malloc0 (tsize);
561 if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
562 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
563 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
565 table->type_tables = g_realloc (table->type_tables, tsize);
568 table->type_tables [table->num_type_tables++] = table->current_type_table;
570 /* .... allocate a new current_type_table. */
571 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
572 table->type_table_start = table->type_table_offset = table->type_table_size;
573 table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
579 property_is_static (MonoProperty *prop)
587 return method->flags & METHOD_ATTRIBUTE_STATIC;
591 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
593 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
594 GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL;
595 int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
596 int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
597 int num_ctors = 0, num_ctor_params = 0;
598 guint32 size, data_size, offset;
599 GHashTable *method_slots = NULL;
602 g_assert (!klass->init_pending);
603 mono_class_init (klass);
605 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
609 if (klass->enumtype) {
610 offset = allocate_type_entry (table, 13, &ptr);
611 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
613 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
614 WRITE_UINT32 (ptr, klass->instance_size);
615 WRITE_UINT32 (ptr, table->builtin_types->enum_type->type_info);
616 WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
620 for (i = 0; i < klass->field.count; i++)
621 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
626 for (i = 0; i < klass->property.count; i++)
627 if (!property_is_static (&klass->properties [i]))
630 ++num_static_properties;
632 method_slots = g_hash_table_new (NULL, NULL);
633 methods = g_ptr_array_new ();
634 static_methods = g_ptr_array_new ();
635 ctors = g_ptr_array_new ();
637 for (i = 0; i < klass->method.count; i++) {
638 MonoMethod *method = klass->methods [i];
640 if (!strcmp (method->name, ".cctor"))
642 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
645 if (!strcmp (method->name, ".ctor")) {
647 num_ctor_params += method->signature->param_count;
648 g_ptr_array_add (ctors, method);
652 if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
654 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
656 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
658 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
659 ++num_static_methods;
660 num_static_params += method->signature->param_count;
661 g_ptr_array_add (static_methods, method);
664 num_params += method->signature->param_count;
665 g_ptr_array_add (methods, method);
669 g_hash_table_destroy (method_slots);
671 size = 66 + sizeof (gpointer) + num_fields * 8 + num_static_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
672 num_static_properties * (4 + 2 * sizeof (gpointer)) + num_methods * (8 + sizeof (gpointer)) + num_params * 4 +
673 num_static_methods * (8 + sizeof (gpointer)) + num_static_params * 4 + num_ctors * (8 + sizeof (gpointer)) +
678 offset = allocate_type_entry (table, data_size, &ptr);
681 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
683 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
685 if (klass->valuetype)
686 base_offset = - sizeof (MonoObject);
688 WRITE_UINT32 (ptr, klass->instance_size + base_offset);
689 *ptr++ = klass->valuetype;
690 WRITE_POINTER (ptr, klass);
691 WRITE_UINT32 (ptr, num_fields);
692 WRITE_UINT32 (ptr, num_fields * 8);
693 WRITE_UINT32 (ptr, num_static_fields);
694 WRITE_UINT32 (ptr, num_static_fields * 8);
695 WRITE_UINT32 (ptr, num_properties);
696 WRITE_UINT32 (ptr, num_properties * (4 + 2 * sizeof (gpointer)));
697 WRITE_UINT32 (ptr, num_static_properties);
698 WRITE_UINT32 (ptr, num_static_properties * (4 + 2 * sizeof (gpointer)));
699 WRITE_UINT32 (ptr, num_methods);
700 WRITE_UINT32 (ptr, num_methods * (4 + 2 * sizeof (gpointer)) + num_params * sizeof (gpointer));
701 WRITE_UINT32 (ptr, num_static_methods);
702 WRITE_UINT32 (ptr, num_static_methods * (4 + 2 * sizeof (gpointer)) + num_static_params * sizeof (gpointer));
703 WRITE_UINT32 (ptr, num_ctors);
704 WRITE_UINT32 (ptr, num_ctors * (4 + 2 * sizeof (gpointer)) + num_ctor_params * sizeof (gpointer));
706 for (i = 0; i < klass->field.count; i++) {
707 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
710 WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
711 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
714 for (i = 0; i < klass->property.count; i++) {
715 if (property_is_static (&klass->properties [i]))
718 if (klass->properties [i].get)
719 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
721 WRITE_UINT32 (ptr, 0);
722 WRITE_POINTER (ptr, klass->properties [i].get);
723 WRITE_POINTER (ptr, klass->properties [i].set);
726 for (i = 0; i < methods->len; i++) {
727 MonoMethod *method = g_ptr_array_index (methods, i);
730 WRITE_POINTER (ptr, method);
731 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
732 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
734 WRITE_UINT32 (ptr, 0);
735 WRITE_UINT32 (ptr, method->signature->param_count);
736 for (j = 0; j < method->signature->param_count; j++)
737 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
740 g_ptr_array_free (methods, FALSE);
742 for (i = 0; i < klass->field.count; i++) {
743 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
746 WRITE_UINT32 (ptr, klass->fields [i].offset);
747 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
750 for (i = 0; i < klass->property.count; i++) {
751 if (!property_is_static (&klass->properties [i]))
754 if (klass->properties [i].get)
755 WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
757 WRITE_UINT32 (ptr, 0);
758 WRITE_POINTER (ptr, klass->properties [i].get);
759 WRITE_POINTER (ptr, klass->properties [i].set);
762 for (i = 0; i < static_methods->len; i++) {
763 MonoMethod *method = g_ptr_array_index (static_methods, i);
766 WRITE_POINTER (ptr, method);
767 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
768 WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
770 WRITE_UINT32 (ptr, 0);
771 WRITE_UINT32 (ptr, method->signature->param_count);
772 for (j = 0; j < method->signature->param_count; j++)
773 WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
776 g_ptr_array_free (static_methods, FALSE);
778 for (i = 0; i < ctors->len; i++) {
779 MonoMethod *ctor = g_ptr_array_index (ctors, i);
782 WRITE_POINTER (ptr, ctor);
783 WRITE_UINT32 (ptr, 0);
784 WRITE_UINT32 (ptr, ctor->signature->param_count);
785 for (j = 0; j < ctor->signature->param_count; j++)
786 WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
789 g_ptr_array_free (ctors, FALSE);
791 if (klass->parent && (klass->parent != mono_defaults.object_class))
792 WRITE_UINT32 (ptr, write_class (table, klass->parent));
794 WRITE_UINT32 (ptr, 0);
796 if (ptr - old_ptr != data_size) {
797 g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
799 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
800 g_assert_not_reached ();
807 * Adds type `type' to the type table and returns its offset.
810 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
812 guint8 buffer [BUFSIZ], *ptr = buffer;
813 guint32 size, offset;
816 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
820 klass = mono_class_from_mono_type (type);
821 if (klass->init_pending)
823 mono_class_init (klass);
825 switch (type->type) {
827 return table->builtin_types->void_type->type_info;
829 case MONO_TYPE_BOOLEAN:
830 return table->builtin_types->boolean_type->type_info;
833 return table->builtin_types->sbyte_type->type_info;
836 return table->builtin_types->byte_type->type_info;
839 return table->builtin_types->char_type->type_info;
842 return table->builtin_types->int16_type->type_info;
845 return table->builtin_types->uint16_type->type_info;
848 return table->builtin_types->int32_type->type_info;
851 return table->builtin_types->uint32_type->type_info;
854 return table->builtin_types->int64_type->type_info;
857 return table->builtin_types->uint64_type->type_info;
860 return table->builtin_types->single_type->type_info;
863 return table->builtin_types->double_type->type_info;
865 case MONO_TYPE_STRING:
866 return table->builtin_types->string_type->type_info;
869 return table->builtin_types->int_type->type_info;
872 return table->builtin_types->uint_type->type_info;
874 case MONO_TYPE_SZARRAY: {
877 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
878 WRITE_UINT32 (ptr, sizeof (MonoArray));
879 g_assert (table->builtin_types->array_type->type_info != 0);
880 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
881 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
882 *ptr++ = sizeof (array.max_length);
883 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
884 WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
888 case MONO_TYPE_ARRAY: {
890 MonoArrayBounds bounds;
892 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
893 WRITE_UINT32 (ptr, sizeof (MonoArray));
894 g_assert (table->builtin_types->array_type->type_info != 0);
895 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
896 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
897 *ptr++ = sizeof (array.max_length);
898 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
899 *ptr++ = klass->rank;
900 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
901 *ptr++ = sizeof (MonoArrayBounds);
902 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
903 *ptr++ = sizeof (bounds.lower_bound);
904 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
905 *ptr++ = sizeof (bounds.length);
906 WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
910 case MONO_TYPE_VALUETYPE:
911 case MONO_TYPE_CLASS:
912 case MONO_TYPE_OBJECT:
913 return write_class (table, klass);
916 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
917 WRITE_UINT32 (ptr, sizeof (gpointer));
918 WRITE_UINT32 (ptr, write_type (table, type->data.type));
922 g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type);
923 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
924 WRITE_UINT32 (ptr, klass->instance_size);
925 WRITE_UINT32 (ptr, write_class (table, klass));
930 offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
931 memcpy (ptr, buffer, size);
936 MonoReflectionMethod *
937 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
941 method = mono_get_method (assembly->assembly->image, token, NULL);
943 return mono_method_get_object (mono_domain_get (), method, NULL);
947 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
949 return method->method->token;
953 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
957 klass = mono_class_get (assembly->assembly->image, token);
959 g_warning (G_STRLOC ": %x", token);
963 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
967 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
975 MONO_CHECK_ARG_NULL (assembly);
976 MONO_CHECK_ARG_NULL (signature);
978 domain = mono_domain_get();
979 image = assembly->assembly->image;
981 ptr = mono_array_addr (signature, char, 0);
982 g_assert (*ptr++ == 0x07);
983 len = mono_metadata_decode_value (ptr, &ptr);
986 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
988 return mono_type_get_object (domain, type);
992 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
994 if (mono_debugger_event_handler)
995 (* mono_debugger_event_handler) (event, data, arg);
999 mono_debugger_cleanup (void)
1001 /* Do nothing yet. */
1005 * Debugger breakpoint interface.
1007 * This interface is used to insert breakpoints on methods which are not yet JITed.
1008 * The debugging code keeps a list of all such breakpoints and automatically inserts the
1009 * breakpoint when the method is JITed.
1012 static GPtrArray *breakpoints = NULL;
1015 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
1017 static int last_breakpoint_id = 0;
1018 MonoDebuggerBreakpointInfo *info;
1020 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1022 info->index = ++last_breakpoint_id;
1025 breakpoints = g_ptr_array_new ();
1027 g_ptr_array_add (breakpoints, info);
1033 mono_debugger_remove_breakpoint (int breakpoint_id)
1040 for (i = 0; i < breakpoints->len; i++) {
1041 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1043 if (info->index != breakpoint_id)
1046 mono_method_desc_free (info->desc);
1047 g_ptr_array_remove (breakpoints, info);
1056 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1058 MonoMethodDesc *desc;
1060 desc = mono_method_desc_new (method_name, include_namespace);
1064 return mono_debugger_insert_breakpoint_full (desc);
1068 mono_debugger_method_has_breakpoint (MonoMethod *method)
1072 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1075 for (i = 0; i < breakpoints->len; i++) {
1076 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1078 if (!mono_method_desc_full_match (info->desc, method))
1088 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
1090 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
1094 get_exception_message (MonoObject *exc)
1096 char *message = NULL;
1102 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1103 klass = exc->vtable->klass;
1105 while (klass && method == NULL) {
1106 for (i = 0; i < klass->method.count; ++i) {
1107 method = klass->methods [i];
1108 if (!strcmp ("ToString", method->name) &&
1109 method->signature->param_count == 0 &&
1110 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1111 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1118 klass = klass->parent;
1123 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1125 message = mono_string_to_utf8 (str);
1132 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1137 if (method->klass->valuetype && (obj != NULL))
1138 obj = mono_value_box (mono_domain_get (), method->klass, obj);
1140 if (!strcmp (method->name, ".ctor")) {
1141 retval = obj = mono_object_new (mono_domain_get (), method->klass);
1143 mono_runtime_invoke (method, obj, params, exc);
1145 retval = mono_runtime_invoke (method, obj, params, exc);
1150 message = get_exception_message (*exc);
1152 *exc = (MonoObject *) mono_string_new_wrapper (message);
1160 mono_debugger_lookup_type (const gchar *type_name)
1164 mono_debugger_lock ();
1166 for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1167 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1171 type = mono_reflection_type_from_name (type_name, symfile->image);
1175 offset = write_type (mono_debugger_symbol_table, type);
1177 mono_debugger_unlock ();
1181 mono_debugger_unlock ();