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 *type_table = NULL;
22 static GHashTable *class_table = NULL;
24 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
25 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
26 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
27 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
29 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
30 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
32 #ifndef PLATFORM_WIN32
34 MonoDebuggerIOLayer mono_debugger_io_layer = {
35 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
36 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
37 WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
43 mono_debugger_lock (void)
45 if (mono_debugger_initialized)
46 EnterCriticalSection (&debugger_lock_mutex);
50 mono_debugger_unlock (void)
52 if (mono_debugger_initialized)
53 LeaveCriticalSection (&debugger_lock_mutex);
56 static MonoDebuggerSymbolFile *
57 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
59 MonoDebuggerSymbolFile *symfile;
61 if (!table->symbol_files)
62 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
63 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
64 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
65 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
67 table->symbol_files = g_realloc (table->symbol_files, size);
70 symfile = g_new0 (MonoDebuggerSymbolFile, 1);
71 table->symbol_files [table->num_symbol_files++] = symfile;
76 mono_debugger_initialize (MonoDomain *domain)
78 MonoDebuggerSymbolTable *symbol_table;
80 g_assert (!mono_debugger_initialized);
82 InitializeCriticalSection (&debugger_lock_mutex);
84 mono_debugger_lock ();
86 symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
87 symbol_table->magic = MONO_DEBUGGER_MAGIC;
88 symbol_table->version = MONO_DEBUGGER_VERSION;
89 symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
91 symbol_table->domain = domain;
93 mono_debugger_symbol_table = symbol_table;
94 mono_debugger_initialized = TRUE;
96 mono_debugger_unlock ();
99 MonoDebuggerSymbolFile *
100 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
102 MonoDebuggerSymbolFile *info;
104 g_assert (mono_debugger_initialized);
106 info = allocate_symbol_file_entry (mono_debugger_symbol_table);
107 info->symfile = handle->symfile;
108 info->image = handle->image;
109 info->image_file = handle->image_file;
111 mono_debugger_add_type (info, mono_defaults.object_class);
116 static MonoDebuggerClassInfo *
117 _mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
119 MonoDebuggerClassInfo *info;
121 info = allocate_class_entry (symfile);
124 info->token = klass->element_class->type_token;
125 info->rank = klass->rank;
127 info->token = klass->type_token;
128 info->type_info = write_type (mono_debugger_symbol_table, &klass->this_arg);
132 MonoDebuggerBuiltinTypes *
133 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
135 MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
137 types->total_size = sizeof (MonoDebuggerBuiltinTypes);
138 types->object_class = _mono_debugger_add_type (symfile, mono_defaults.object_class);
139 types->byte_class = _mono_debugger_add_type (symfile, mono_defaults.byte_class);
140 types->void_class = _mono_debugger_add_type (symfile, mono_defaults.void_class);
141 types->boolean_class = _mono_debugger_add_type (symfile, mono_defaults.boolean_class);
142 types->sbyte_class = _mono_debugger_add_type (symfile, mono_defaults.sbyte_class);
143 types->int16_class = _mono_debugger_add_type (symfile, mono_defaults.int16_class);
144 types->uint16_class = _mono_debugger_add_type (symfile, mono_defaults.uint16_class);
145 types->int32_class = _mono_debugger_add_type (symfile, mono_defaults.int32_class);
146 types->uint32_class = _mono_debugger_add_type (symfile, mono_defaults.uint32_class);
147 types->int_class = _mono_debugger_add_type (symfile, mono_defaults.int_class);
148 types->uint_class = _mono_debugger_add_type (symfile, mono_defaults.uint_class);
149 types->int64_class = _mono_debugger_add_type (symfile, mono_defaults.int64_class);
150 types->uint64_class = _mono_debugger_add_type (symfile, mono_defaults.uint64_class);
151 types->single_class = _mono_debugger_add_type (symfile, mono_defaults.single_class);
152 types->double_class = _mono_debugger_add_type (symfile, mono_defaults.double_class);
153 types->char_class = _mono_debugger_add_type (symfile, mono_defaults.char_class);
154 types->string_class = _mono_debugger_add_type (symfile, mono_defaults.string_class);
155 types->enum_class = _mono_debugger_add_type (symfile, mono_defaults.enum_class);
156 types->array_class = _mono_debugger_add_type (symfile, mono_defaults.array_class);
158 mono_debugger_symbol_table->corlib = symfile;
159 mono_debugger_symbol_table->builtin_types = types;
165 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
169 mono_debugger_lock ();
172 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
174 /* We write typeof (object) into each symbol file's type table. */
175 info = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
176 if ((info != 0) && (klass != mono_defaults.object_class)) {
177 mono_debugger_unlock ();
181 symfile->generation++;
182 _mono_debugger_add_type (symfile, klass);
183 mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, NULL, 0);
184 mono_debugger_unlock ();
188 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
189 MonoDebugMethodJitInfo *jit)
191 MonoSymbolFileMethodAddress *address;
192 MonoSymbolFileLexicalBlockEntry *block;
193 MonoDebugVarInfo *var_table;
194 MonoDebuggerRangeInfo *range;
195 MonoMethodHeader *header;
196 guint32 size, num_variables, variable_size, variable_offset;
197 guint32 type_size, type_offset, *type_index_table, has_this;
198 guint32 line_size, line_offset, block_offset, block_size;
199 MonoDebugLexicalBlockEntry *block_table;
200 MonoDebugLineNumberEntry *line_table;
205 if (!symfile->symfile->method_hash)
208 header = ((MonoMethodNormal *) minfo->method)->header;
210 symfile->generation++;
212 size = sizeof (MonoSymbolFileMethodAddress);
214 num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
215 has_this = jit->this_var != NULL;
217 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
218 variable_offset = size;
219 size += variable_size;
221 type_size = (num_variables + 1) * sizeof (gpointer);
225 if (jit->line_numbers) {
227 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
231 block_size = minfo->entry->num_lexical_blocks * sizeof (MonoSymbolFileLexicalBlockEntry);
235 address = g_malloc0 (size);
236 ptr = (guint8 *) address;
238 block = (MonoSymbolFileLexicalBlockEntry *)
239 (symfile->symfile->raw_contents + minfo->entry->lexical_block_table_offset);
240 block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
242 for (i = 0; i < minfo->entry->num_lexical_blocks; i++, block++) {
243 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, block->start_offset);
244 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, block->end_offset);
247 address->size = size;
248 address->has_this = has_this;
249 address->start_address = jit->code_start;
250 address->end_address = jit->code_start + jit->code_size;
251 address->method_start_address = address->start_address + jit->prologue_end;
252 address->method_end_address = address->start_address + jit->epilogue_begin;
253 address->wrapper_address = jit->wrapper_addr;
254 address->variable_table_offset = variable_offset;
255 address->type_table_offset = type_offset;
256 address->lexical_block_table_offset = block_offset;
258 if (jit->line_numbers) {
259 address->num_line_numbers = jit->line_numbers->len;
260 address->line_number_offset = line_offset;
262 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
263 memcpy (line_table, jit->line_numbers->data, line_size);
266 range = allocate_range_entry (symfile);
267 range->index = minfo->index;
268 range->start_address = address->start_address;
269 range->end_address = address->end_address;
270 range->dynamic_data = address;
271 range->dynamic_size = size;
273 if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
274 (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
275 (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
278 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
279 type_table = (guint32 *) (ptr + type_offset);
281 type_index_table = (guint32 *)
282 (symfile->symfile->raw_contents + minfo->entry->type_index_table_offset);
285 *var_table++ = *jit->this_var;
286 *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
288 if (jit->num_params != minfo->entry->num_parameters) {
289 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
290 minfo->method->klass->name, minfo->method->name, jit->num_params,
291 minfo->entry->num_parameters);
292 var_table += minfo->entry->num_parameters;
294 for (i = 0; i < jit->num_params; i++) {
295 *var_table++ = jit->params [i];
296 *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
300 if (jit->num_locals < minfo->entry->num_locals) {
301 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
302 minfo->method->klass->name, minfo->method->name, jit->num_locals,
303 minfo->entry->num_locals);
304 var_table += minfo->entry->num_locals;
306 g_assert ((header != NULL) || (minfo->entry->num_locals == 0));
307 for (i = 0; i < minfo->entry->num_locals; i++) {
308 *var_table++ = jit->locals [i];
309 *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
313 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, NULL, 0);
316 static MonoDebuggerRangeInfo *
317 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
319 MonoDebuggerRangeInfo *retval;
320 guint32 size, chunks;
322 symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
324 if (!symfile->range_table) {
325 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
326 symfile->range_table = g_malloc0 (size);
327 symfile->num_range_entries = 1;
328 return symfile->range_table;
331 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
332 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
333 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
335 symfile->range_table = g_realloc (symfile->range_table, size);
338 retval = symfile->range_table + symfile->num_range_entries;
339 symfile->num_range_entries++;
343 static MonoDebuggerClassInfo *
344 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
346 MonoDebuggerClassInfo *retval;
347 guint32 size, chunks;
349 symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
351 if (!symfile->class_table) {
352 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
353 symfile->class_table = g_malloc0 (size);
354 symfile->num_class_entries = 1;
355 return symfile->class_table;
358 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
359 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
360 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
362 symfile->class_table = g_realloc (symfile->class_table, size);
365 retval = symfile->class_table + symfile->num_class_entries;
366 symfile->num_class_entries++;
371 * Allocate a new entry of size `size' in the type table.
372 * Returns the global offset which is to be used to reference this type and
373 * a pointer (in the `ptr' argument) which is to be used to write the type.
376 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
381 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
382 g_assert (ptr != NULL);
384 /* Initialize things if necessary. */
385 if (!table->current_type_table) {
386 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
387 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
388 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
389 table->type_table_offset = 1;
393 /* First let's check whether there's still enough room in the current_type_table. */
394 if (table->type_table_offset + size + 4 < table->type_table_size) {
395 retval = table->type_table_offset;
396 table->type_table_offset += size + 4;
397 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
398 *(gint32 *) data = size;
399 data += sizeof(gint32);
404 /* Add the current_type_table to the type_tables vector and ... */
405 if (!table->type_tables) {
406 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
407 table->type_tables = g_malloc0 (tsize);
410 if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
411 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
412 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
414 table->type_tables = g_realloc (table->type_tables, tsize);
417 table->type_tables [table->num_type_tables++] = table->current_type_table;
419 /* .... allocate a new current_type_table. */
420 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
421 table->type_table_start = table->type_table_offset = table->type_table_size;
422 table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
428 write_simple_type (MonoDebuggerSymbolTable *table, MonoType *type)
430 guint8 buffer [BUFSIZ], *ptr = buffer;
431 guint32 size, offset;
434 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
436 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
440 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
441 *((gpointer *) ptr)++ = mono_class_from_mono_type (type);
443 switch (type->type) {
444 case MONO_TYPE_BOOLEAN:
447 *((gint32 *) ptr)++ = 1;
453 *((gint32 *) ptr)++ = 2;
459 *((gint32 *) ptr)++ = 4;
465 *((gint32 *) ptr)++ = 8;
469 *((gint32 *) ptr)++ = 0;
477 offset = allocate_type_entry (table, size, &ptr);
478 memcpy (ptr, buffer, size);
480 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
486 * Adds type `type' to the type table and returns its offset.
489 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
491 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
492 GPtrArray *methods = NULL;
493 int num_fields = 0, num_properties = 0, num_methods = 0;
494 int num_params = 0, kind;
495 guint32 size, data_size, offset;
496 MonoClass *klass = NULL;
499 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
501 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
503 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
507 offset = write_simple_type (table, type);
512 if (kind == MONO_TYPE_OBJECT) {
513 klass = mono_defaults.object_class;
514 kind = MONO_TYPE_CLASS;
515 } else if ((kind == MONO_TYPE_VALUETYPE) || (kind == MONO_TYPE_CLASS)) {
516 klass = type->data.klass;
517 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
523 case MONO_TYPE_STRING:
524 size = 8 + 2 * sizeof (gpointer);
527 case MONO_TYPE_SZARRAY:
528 size = 12 + sizeof (gpointer);
531 case MONO_TYPE_ARRAY:
532 size = 19 + sizeof (gpointer);
537 size = 5 + sizeof (gpointer);
540 case MONO_TYPE_VALUETYPE:
541 case MONO_TYPE_CLASS: {
542 GHashTable *method_slots = NULL;
545 if (klass->init_pending) {
550 mono_class_init (klass);
552 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
556 if (klass->enumtype) {
557 size = 9 + sizeof (gpointer);
561 for (i = 0; i < klass->field.count; i++)
562 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
565 for (i = 0; i < klass->property.count; i++)
566 if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
569 method_slots = g_hash_table_new (NULL, NULL);
570 methods = g_ptr_array_new ();
572 for (i = klass->method.count - 1; i >= 0; i--) {
573 MonoMethod *method = klass->methods [i];
575 if (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)
577 if (method->flags & (METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_SPECIAL_NAME))
579 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
581 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
583 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
586 num_params += method->signature->param_count;
588 g_ptr_array_add (methods, method);
591 g_hash_table_destroy (method_slots);
593 size = 29 + sizeof (gpointer) + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
594 num_methods * (8 + sizeof (gpointer)) + num_params * 4;
596 if (kind == MONO_TYPE_CLASS)
609 offset = allocate_type_entry (table, data_size, &ptr);
612 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
615 case MONO_TYPE_STRING: {
618 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
619 klass = mono_class_from_mono_type (type);
620 *((gpointer *) ptr)++ = klass;
621 *((guint32 *) ptr)++ = sizeof (MonoString);
622 *((gpointer *) ptr)++ = mono_class_vtable (table->domain, klass);
623 *ptr++ = (guint8*)&string.length - (guint8*)&string;
624 *ptr++ = sizeof (string.length);
625 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
629 case MONO_TYPE_SZARRAY: {
632 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
633 *((gpointer *) ptr)++ = mono_class_from_mono_type (type);
634 *((guint32 *) ptr)++ = sizeof (MonoArray);
635 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
636 *ptr++ = sizeof (array.max_length);
637 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
638 *((guint32 *) ptr)++ = write_type (table, &type->data.klass->byval_arg);
642 case MONO_TYPE_ARRAY: {
644 MonoArrayBounds bounds;
646 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
647 *((gpointer *) ptr)++ = mono_class_from_mono_type (type);
648 *((guint32 *) ptr)++ = sizeof (MonoArray);
649 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
650 *ptr++ = sizeof (array.max_length);
651 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
652 *ptr++ = type->data.array->rank;
653 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
654 *ptr++ = sizeof (MonoArrayBounds);
655 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
656 *ptr++ = sizeof (bounds.lower_bound);
657 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
658 *ptr++ = sizeof (bounds.length);
659 *((guint32 *) ptr)++ = write_type (table, &type->data.array->eklass->byval_arg);
665 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
666 *((gpointer *) ptr)++ = mono_class_from_mono_type (type);
667 *((gint32 *) ptr)++ = sizeof (void *);
670 case MONO_TYPE_VALUETYPE:
671 case MONO_TYPE_CLASS: {
672 int base_offset = kind == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
675 if (klass->init_pending) {
680 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
682 if (klass->enumtype) {
683 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
684 *((gpointer *) ptr)++ = mono_class_from_mono_type (type);
685 *((guint32 *) ptr)++ = sizeof (MonoObject);
686 *((guint32 *) ptr)++ = write_type (table, klass->enum_basetype);
690 if (type->type == MONO_TYPE_OBJECT)
691 *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
692 else if (type->type == MONO_TYPE_CLASS)
693 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
695 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
697 *((gpointer *) ptr)++ = klass;
698 *((guint32 *) ptr)++ = klass->instance_size + base_offset;
699 *((guint32 *) ptr)++ = num_fields;
700 *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
701 *((guint32 *) ptr)++ = num_properties;
702 *((guint32 *) ptr)++ = num_properties * 3 * sizeof (gpointer);
703 *((guint32 *) ptr)++ = num_methods;
704 *((guint32 *) ptr)++ = num_methods * (4 + 2 * sizeof (gpointer)) +
705 num_params * sizeof (gpointer);
706 for (i = 0; i < klass->field.count; i++) {
707 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
710 *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
711 *((guint32 *) ptr)++ = write_type (table, klass->fields [i].type);
714 for (i = 0; i < klass->property.count; i++) {
715 if (klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC)
718 if (klass->properties [i].get)
719 *((guint32 *) ptr)++ = write_type
720 (table, klass->properties [i].get->signature->ret);
722 *((guint32 *) ptr)++ = 0;
723 *((gpointer *) ptr)++ = klass->properties [i].get;
724 *((gpointer *) ptr)++ = klass->properties [i].set;
727 for (i = 0; i < methods->len; i++) {
728 MonoMethod *method = g_ptr_array_index (methods, i);
730 *((gpointer *) ptr)++ = method;
731 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
732 *((guint32 *) ptr)++ = write_type (table, method->signature->ret);
734 *((guint32 *) ptr)++ = 0;
735 *((guint32 *) ptr)++ = method->signature->param_count;
736 for (j = 0; j < method->signature->param_count; j++)
737 *((guint32 *) ptr)++ = write_type (table, method->signature->params [j]);
740 g_ptr_array_free (methods, FALSE);
742 if (kind == MONO_TYPE_CLASS) {
744 *((guint32 *) ptr)++ = write_type (table, &klass->parent->this_arg);
746 *((guint32 *) ptr)++ = 0;
753 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
758 if (ptr - old_ptr != data_size) {
759 g_warning (G_STRLOC ": %d,%d,%d - %d", ptr - old_ptr, data_size, sizeof (gpointer), kind);
761 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
762 g_assert_not_reached ();
769 MonoReflectionMethod *
770 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
774 method = mono_get_method (assembly->assembly->image, token, NULL);
776 return mono_method_get_object (mono_domain_get (), method, NULL);
780 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
782 return method->method->token;
786 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
790 klass = mono_class_get (assembly->assembly->image, token);
792 g_warning (G_STRLOC ": %x", token);
796 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
800 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
808 MONO_CHECK_ARG_NULL (assembly);
809 MONO_CHECK_ARG_NULL (signature);
811 domain = mono_domain_get();
812 image = assembly->assembly->image;
814 ptr = mono_array_addr (signature, char, 0);
815 g_assert (*ptr++ == 0x07);
816 len = mono_metadata_decode_value (ptr, &ptr);
819 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
821 return mono_type_get_object (domain, type);
825 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
827 if (mono_debugger_event_handler)
828 (* mono_debugger_event_handler) (event, data, arg);
832 mono_debugger_cleanup (void)
834 /* Do nothing yet. */
838 * Debugger breakpoint interface.
840 * This interface is used to insert breakpoints on methods which are not yet JITed.
841 * The debugging code keeps a list of all such breakpoints and automatically inserts the
842 * breakpoint when the method is JITed.
845 static GPtrArray *breakpoints = NULL;
848 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
850 static int last_breakpoint_id = 0;
851 MonoDebuggerBreakpointInfo *info;
853 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
855 info->index = ++last_breakpoint_id;
858 breakpoints = g_ptr_array_new ();
860 g_ptr_array_add (breakpoints, info);
866 mono_debugger_remove_breakpoint (int breakpoint_id)
873 for (i = 0; i < breakpoints->len; i++) {
874 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
876 if (info->index != breakpoint_id)
879 mono_method_desc_free (info->desc);
880 g_ptr_array_remove (breakpoints, info);
889 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
891 MonoMethodDesc *desc;
893 desc = mono_method_desc_new (method_name, include_namespace);
897 return mono_debugger_insert_breakpoint_full (desc);
901 mono_debugger_method_has_breakpoint (MonoMethod *method)
905 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
908 for (i = 0; i < breakpoints->len; i++) {
909 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
911 if (!mono_method_desc_full_match (info->desc, method))
921 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
923 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);