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, gpointer data2) = NULL;
33 mono_debugger_lock (void)
35 if (mono_debugger_initialized)
36 EnterCriticalSection (&debugger_lock_mutex);
40 mono_debugger_unlock (void)
42 if (mono_debugger_initialized)
43 LeaveCriticalSection (&debugger_lock_mutex);
46 static MonoDebuggerSymbolFile *
47 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
49 MonoDebuggerSymbolFile *symfile;
51 if (!table->symbol_files)
52 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
53 else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
54 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
55 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
57 table->symbol_files = g_realloc (table->symbol_files, size);
60 symfile = g_new0 (MonoDebuggerSymbolFile, 1);
61 table->symbol_files [table->num_symbol_files++] = symfile;
66 mono_debugger_initialize (void)
68 MonoDebuggerSymbolTable *symbol_table;
70 g_assert (!mono_debugger_initialized);
72 mono_debugger_lock ();
74 symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
75 symbol_table->magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
76 symbol_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
77 symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
79 mono_debugger_symbol_table = symbol_table;
80 mono_debugger_initialized = TRUE;
82 mono_debugger_unlock ();
85 MonoDebuggerSymbolFile *
86 mono_debugger_add_symbol_file (MonoSymbolFile *symfile)
88 MonoDebuggerSymbolFile *info;
90 g_assert (mono_debugger_initialized);
92 info = allocate_symbol_file_entry (mono_debugger_symbol_table);
93 info->symfile = symfile;
94 info->image_file = symfile->image_file;
96 mono_debugger_add_type (info, mono_defaults.object_class);
102 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
104 MonoDebuggerClassInfo *info;
106 mono_debugger_lock ();
109 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
111 /* We write typeof (object) into each symbol file's type table. */
112 if ((klass != mono_defaults.object_class) && g_hash_table_lookup (class_table, klass)) {
113 mono_debugger_unlock ();
117 symfile->generation++;
119 info = allocate_class_entry (symfile);
122 info->token = klass->element_class->type_token;
123 info->rank = klass->rank;
125 info->token = klass->type_token;
126 info->type_info = write_type (mono_debugger_symbol_table, &klass->this_arg);
128 mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, symfile, klass);
129 mono_debugger_unlock ();
133 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
135 MonoSymbolFileMethodAddress *address;
136 MonoSymbolFileLexicalBlockEntry *block;
137 MonoDebugMethodInfo *minfo;
138 MonoDebugVarInfo *var_table;
139 MonoDebuggerRangeInfo *range;
140 MonoMethodHeader *header;
141 guint32 size, num_variables, variable_size, variable_offset;
142 guint32 type_size, type_offset, *type_index_table, has_this;
143 guint32 line_size, line_offset, block_offset, block_size;
144 MonoDebugLexicalBlockEntry *block_table;
145 MonoDebugLineNumberEntry *line_table;
150 if (!symfile->symfile->method_hash)
153 header = ((MonoMethodNormal *) method)->header;
155 minfo = g_hash_table_lookup (symfile->symfile->method_hash, method);
156 if (!minfo || !minfo->jit)
159 size = sizeof (MonoSymbolFileMethodAddress);
161 num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
162 has_this = minfo->jit->this_var != NULL;
164 variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
165 variable_offset = size;
166 size += variable_size;
168 type_size = (num_variables + 1) * sizeof (gpointer);
172 if (minfo->jit->line_numbers) {
174 line_size = minfo->jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
178 block_size = minfo->entry->num_lexical_blocks * sizeof (MonoSymbolFileLexicalBlockEntry);
182 address = g_malloc0 (size);
183 ptr = (guint8 *) address;
185 block = (MonoSymbolFileLexicalBlockEntry *)
186 (symfile->symfile->raw_contents + minfo->entry->lexical_block_table_offset);
187 block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
189 for (i = 0; i < minfo->entry->num_lexical_blocks; i++, block++) {
190 block_table [i].start_address = _mono_debug_address_from_il_offset (minfo, block->start_offset);
191 block_table [i].end_address = _mono_debug_address_from_il_offset (minfo, block->end_offset);
194 address->size = size;
195 address->has_this = has_this;
196 address->start_address = minfo->jit->code_start;
197 address->end_address = minfo->jit->code_start + minfo->jit->code_size;
198 address->method_start_address = address->start_address + minfo->jit->prologue_end;
199 address->method_end_address = address->start_address + minfo->jit->epilogue_begin;
200 address->wrapper_address = minfo->jit->wrapper_addr;
201 address->variable_table_offset = variable_offset;
202 address->type_table_offset = type_offset;
203 address->lexical_block_table_offset = block_offset;
205 if (minfo->jit->line_numbers) {
206 address->num_line_numbers = minfo->jit->line_numbers->len;
207 address->line_number_offset = line_offset;
209 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
210 memcpy (line_table, minfo->jit->line_numbers->data, line_size);
213 range = allocate_range_entry (symfile);
214 range->index = minfo->index;
215 range->start_address = address->start_address;
216 range->end_address = address->end_address;
217 range->dynamic_data = address;
218 range->dynamic_size = size;
220 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
221 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
222 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
225 var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
226 type_table = (guint32 *) (ptr + type_offset);
228 type_index_table = (guint32 *)
229 (symfile->symfile->raw_contents + minfo->entry->type_index_table_offset);
231 if (minfo->jit->this_var)
232 *var_table++ = *minfo->jit->this_var;
233 *type_table++ = write_type (mono_debugger_symbol_table, &method->klass->this_arg);
235 if (minfo->jit->num_params != minfo->entry->num_parameters) {
236 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
237 minfo->method->klass->name, minfo->method->name, minfo->jit->num_params,
238 minfo->entry->num_parameters);
240 var_table += minfo->entry->num_parameters;
242 for (i = 0; i < minfo->jit->num_params; i++) {
243 *var_table++ = minfo->jit->params [i];
244 *type_table++ = write_type (mono_debugger_symbol_table, method->signature->params [i]);
248 if (minfo->jit->num_locals < minfo->entry->num_locals) {
249 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
250 minfo->method->klass->name, minfo->method->name, minfo->jit->num_locals,
251 minfo->entry->num_locals);
252 var_table += minfo->entry->num_locals;
254 g_assert ((header != NULL) || (minfo->entry->num_locals == 0));
255 for (i = 0; i < minfo->entry->num_locals; i++) {
256 *var_table++ = minfo->jit->locals [i];
257 *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
261 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, symfile, method);
264 static MonoDebuggerRangeInfo *
265 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
267 MonoDebuggerRangeInfo *retval;
268 guint32 size, chunks;
270 symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
272 if (!symfile->range_table) {
273 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
274 symfile->range_table = g_malloc0 (size);
275 symfile->num_range_entries = 1;
276 return symfile->range_table;
279 if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
280 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
281 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
283 symfile->range_table = g_realloc (symfile->range_table, size);
286 retval = symfile->range_table + symfile->num_range_entries;
287 symfile->num_range_entries++;
291 static MonoDebuggerClassInfo *
292 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
294 MonoDebuggerClassInfo *retval;
295 guint32 size, chunks;
297 symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
299 if (!symfile->class_table) {
300 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
301 symfile->class_table = g_malloc0 (size);
302 symfile->num_class_entries = 1;
303 return symfile->class_table;
306 if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
307 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
308 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
310 symfile->class_table = g_realloc (symfile->class_table, size);
313 retval = symfile->class_table + symfile->num_class_entries;
314 symfile->num_class_entries++;
319 * Allocate a new entry of size `size' in the type table.
320 * Returns the global offset which is to be used to reference this type and
321 * a pointer (in the `ptr' argument) which is to be used to write the type.
324 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
329 g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
330 g_assert (ptr != NULL);
332 /* Initialize things if necessary. */
333 if (!table->current_type_table) {
334 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
335 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
336 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
337 table->type_table_offset = 1;
341 /* First let's check whether there's still enough room in the current_type_table. */
342 if (table->type_table_offset + size + 4 < table->type_table_size) {
343 retval = table->type_table_offset;
344 table->type_table_offset += size + 4;
345 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
346 *((gint32 *) data)++ = size;
351 /* Add the current_type_table to the type_tables vector and ... */
352 if (!table->type_tables) {
353 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
354 table->type_tables = g_malloc0 (tsize);
357 if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
358 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
359 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
361 table->type_tables = g_realloc (table->type_tables, tsize);
364 table->type_tables [table->num_type_tables++] = table->current_type_table;
366 /* .... allocate a new current_type_table. */
367 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
368 table->type_table_start = table->type_table_offset = table->type_table_size;
369 table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
375 write_simple_type (MonoDebuggerSymbolTable *table, MonoType *type)
377 guint8 buffer [BUFSIZ], *ptr = buffer;
378 guint32 size, offset;
381 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
383 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
387 switch (type->type) {
388 case MONO_TYPE_BOOLEAN:
391 *((gint32 *) ptr)++ = 1;
397 *((gint32 *) ptr)++ = 2;
403 *((gint32 *) ptr)++ = 4;
409 *((gint32 *) ptr)++ = 8;
414 *((gint32 *) ptr)++ = sizeof (void *);
418 *((gint32 *) ptr)++ = 0;
421 case MONO_TYPE_STRING: {
424 *((gint32 *) ptr)++ = -8;
425 *((guint32 *) ptr)++ = sizeof (MonoString);
427 *ptr++ = (guint8*)&string.length - (guint8*)&string;
428 *ptr++ = sizeof (string.length);
429 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
438 offset = allocate_type_entry (table, size, &ptr);
439 memcpy (ptr, buffer, size);
441 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
447 * Adds type `type' to the type table and returns its offset.
450 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
452 guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
453 GPtrArray *methods = NULL;
454 int num_fields = 0, num_properties = 0, num_methods = 0;
455 int num_params = 0, kind;
456 guint32 size, data_size, offset;
457 MonoClass *klass = NULL;
460 type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
462 class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
464 offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
468 offset = write_simple_type (table, type);
473 if (kind == MONO_TYPE_OBJECT) {
474 klass = mono_defaults.object_class;
475 kind = MONO_TYPE_CLASS;
476 } else if ((kind == MONO_TYPE_VALUETYPE) || (kind == MONO_TYPE_CLASS)) {
477 klass = type->data.klass;
478 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
484 case MONO_TYPE_SZARRAY:
488 case MONO_TYPE_ARRAY:
492 case MONO_TYPE_VALUETYPE:
493 case MONO_TYPE_CLASS: {
494 GHashTable *method_slots = NULL;
497 if (klass->init_pending) {
502 mono_class_init (klass);
504 offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
508 if (klass->enumtype) {
513 for (i = 0; i < klass->field.count; i++)
514 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
517 for (i = 0; i < klass->property.count; i++)
518 if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
521 method_slots = g_hash_table_new (NULL, NULL);
522 methods = g_ptr_array_new ();
524 for (i = klass->method.count - 1; i >= 0; i--) {
525 MonoMethod *method = klass->methods [i];
527 if (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)
529 if (method->flags & (METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_SPECIAL_NAME))
531 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
533 if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
535 g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
538 num_params += method->signature->param_count;
540 g_ptr_array_add (methods, method);
543 g_hash_table_destroy (method_slots);
545 size = 34 + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
546 num_methods * (8 + sizeof (gpointer)) + num_params * 4;
548 if (kind == MONO_TYPE_CLASS)
561 offset = allocate_type_entry (table, data_size, &ptr);
564 g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
567 case MONO_TYPE_SZARRAY: {
570 *((gint32 *) ptr)++ = -size;
571 *((guint32 *) ptr)++ = sizeof (MonoArray);
573 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
574 *ptr++ = sizeof (array.max_length);
575 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
576 *((guint32 *) ptr)++ = write_type (table, type->data.type);
580 case MONO_TYPE_ARRAY: {
582 MonoArrayBounds bounds;
584 *((gint32 *) ptr)++ = -size;
585 *((guint32 *) ptr)++ = sizeof (MonoArray);
587 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
588 *ptr++ = sizeof (array.max_length);
589 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
590 *ptr++ = type->data.array->rank;
591 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
592 *ptr++ = sizeof (MonoArrayBounds);
593 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
594 *ptr++ = sizeof (bounds.lower_bound);
595 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
596 *ptr++ = sizeof (bounds.length);
597 *((guint32 *) ptr)++ = write_type (table, type->data.array->type);
601 case MONO_TYPE_VALUETYPE:
602 case MONO_TYPE_CLASS: {
603 int base_offset = kind == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
606 if (klass->init_pending) {
607 *((gint32 *) ptr)++ = -1;
611 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
613 if (klass->enumtype) {
614 *((gint32 *) ptr)++ = -size;
615 *((guint32 *) ptr)++ = sizeof (MonoObject);
617 *((guint32 *) ptr)++ = write_type (table, klass->enum_basetype);
621 *((gint32 *) ptr)++ = -size;
623 *((guint32 *) ptr)++ = klass->instance_size + base_offset;
624 if (type->type == MONO_TYPE_OBJECT)
627 *ptr++ = kind == MONO_TYPE_CLASS ? 6 : 5;
628 *ptr++ = kind == MONO_TYPE_CLASS;
629 *((guint32 *) ptr)++ = num_fields;
630 *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
631 *((guint32 *) ptr)++ = num_properties;
632 *((guint32 *) ptr)++ = num_properties * 3 * sizeof (gpointer);
633 *((guint32 *) ptr)++ = num_methods;
634 *((guint32 *) ptr)++ = num_methods * (4 + 2 * sizeof (gpointer)) +
635 num_params * sizeof (gpointer);
636 for (i = 0; i < klass->field.count; i++) {
637 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
640 *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
641 *((guint32 *) ptr)++ = write_type (table, klass->fields [i].type);
644 for (i = 0; i < klass->property.count; i++) {
645 if (klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC)
648 if (klass->properties [i].get)
649 *((guint32 *) ptr)++ = write_type
650 (table, klass->properties [i].get->signature->ret);
652 *((guint32 *) ptr)++ = 0;
653 *((gpointer *) ptr)++ = klass->properties [i].get;
654 *((gpointer *) ptr)++ = klass->properties [i].set;
657 for (i = 0; i < methods->len; i++) {
658 MonoMethod *method = g_ptr_array_index (methods, i);
660 *((gpointer *) ptr)++ = method;
661 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
662 *((guint32 *) ptr)++ = write_type (table, method->signature->ret);
664 *((guint32 *) ptr)++ = 0;
665 *((guint32 *) ptr)++ = method->signature->param_count;
666 for (j = 0; j < method->signature->param_count; j++)
667 *((guint32 *) ptr)++ = write_type (table, method->signature->params [j]);
670 g_ptr_array_free (methods, FALSE);
672 if (kind == MONO_TYPE_CLASS) {
674 *((guint32 *) ptr)++ = write_type (table, &klass->parent->this_arg);
676 *((guint32 *) ptr)++ = 0;
683 g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
685 *((gint32 *) ptr)++ = -1;
689 if (ptr - old_ptr != data_size) {
690 g_warning (G_STRLOC ": %d,%d - %d", ptr - old_ptr, data_size, kind);
692 g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
693 g_assert_not_reached ();
700 MonoReflectionMethod *
701 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
705 method = mono_get_method (assembly->assembly->image, token, NULL);
707 return mono_method_get_object (mono_domain_get (), method, NULL);
711 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
713 return method->method->token;
717 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
721 klass = mono_class_get (assembly->assembly->image, token);
723 g_warning (G_STRLOC ": %x", token);
727 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
731 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
739 MONO_CHECK_ARG_NULL (assembly);
740 MONO_CHECK_ARG_NULL (signature);
742 domain = mono_domain_get();
743 image = assembly->assembly->image;
745 ptr = mono_array_addr (signature, char, 0);
746 g_assert (*ptr++ == 0x07);
747 len = mono_metadata_decode_value (ptr, &ptr);
750 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
752 return mono_type_get_object (domain, type);
756 mono_debugger_event (MonoDebuggerEvent event, gpointer data, gpointer data2)
758 if (mono_debugger_event_handler)
759 (* mono_debugger_event_handler) (event, data, data2);
763 mono_debugger_cleanup (void)
765 /* Do nothing yet. */
769 * Debugger breakpoint interface.
771 * This interface is used to insert breakpoints on methods which are not yet JITed.
772 * The debugging code keeps a list of all such breakpoints and automatically inserts the
773 * breakpoint when the method is JITed.
776 static GPtrArray *breakpoints = NULL;
779 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
781 static int last_breakpoint_id = 0;
782 MonoDebuggerBreakpointInfo *info;
784 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
786 info->use_trampoline = use_trampoline;
787 info->index = ++last_breakpoint_id;
790 breakpoints = g_ptr_array_new ();
792 g_ptr_array_add (breakpoints, info);
798 mono_debugger_remove_breakpoint (int breakpoint_id)
805 for (i = 0; i < breakpoints->len; i++) {
806 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
808 if (info->index != breakpoint_id)
811 mono_method_desc_free (info->desc);
812 g_ptr_array_remove (breakpoints, info);
821 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
823 MonoMethodDesc *desc;
824 gboolean in_the_debugger;
826 desc = mono_method_desc_new (method_name, include_namespace);
830 in_the_debugger = mono_debug_format == MONO_DEBUG_FORMAT_DEBUGGER;
831 return mono_debugger_insert_breakpoint_full (desc, in_the_debugger);
835 mono_debugger_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
839 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
842 for (i = 0; i < breakpoints->len; i++) {
843 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
845 if (info->use_trampoline != use_trampoline)
848 if (!mono_method_desc_full_match (info->desc, method))
858 mono_debugger_trampoline_breakpoint_callback (void)
860 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT_TRAMPOLINE, NULL, NULL);