11a6a184b1f37eed40896eddf08c7aa43962e34c
[mono.git] / mono / metadata / mono-debug-debugger.c
1 #include <config.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <mono/metadata/metadata.h>
5 #include <mono/metadata/tabledefs.h>
6 #include <mono/metadata/tokentype.h>
7 #include <mono/metadata/appdomain.h>
8 #include <mono/metadata/exception.h>
9 #include <mono/metadata/mono-debug.h>
10 #include <mono/metadata/mono-debug-debugger.h>
11 #include <mono/metadata/mono-endian.h>
12
13 #define SYMFILE_TABLE_CHUNK_SIZE        16
14 #define RANGE_TABLE_CHUNK_SIZE          256
15 #define CLASS_TABLE_CHUNK_SIZE          256
16 #define TYPE_TABLE_PTR_CHUNK_SIZE       256
17 #define TYPE_TABLE_CHUNK_SIZE           65536
18
19 static guint32 debugger_lock_level = 0;
20 static CRITICAL_SECTION debugger_lock_mutex;
21 static gboolean mono_debugger_initialized = FALSE;
22
23 static gboolean must_reload_symtabs = FALSE;
24
25 static GHashTable *images = NULL;
26 static GHashTable *type_table = NULL;
27 static GHashTable *class_table = NULL;
28 static GHashTable *class_info_table = NULL;
29
30 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
31 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
32 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
33 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
34 static guint32 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass);
35
36 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
37 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
38
39 #define WRITE_UINT32(ptr,value) G_STMT_START {  \
40         * ((guint32 *) ptr) = value;            \
41         ptr += 4;                               \
42 } G_STMT_END
43
44 #define WRITE_POINTER(ptr,value) G_STMT_START { \
45         * ((gpointer *) ptr) = value;           \
46         ptr += sizeof (gpointer);               \
47 } G_STMT_END
48
49 #ifndef PLATFORM_WIN32
50
51 MonoDebuggerIOLayer mono_debugger_io_layer = {
52         InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
53         EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
54         WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
55         GetCurrentThreadId
56 };
57
58 #endif
59
60 void
61 mono_debugger_lock (void)
62 {
63         if (!mono_debugger_initialized) {
64                 debugger_lock_level++;
65                 return;
66         }
67
68         EnterCriticalSection (&debugger_lock_mutex);
69         debugger_lock_level++;
70 }
71
72 void
73 mono_debugger_unlock (void)
74 {
75         g_assert (debugger_lock_level > 0);
76
77         if (!mono_debugger_initialized) {
78                 debugger_lock_level--;
79                 return;
80         }
81
82         if (debugger_lock_level == 1) {
83                 if (must_reload_symtabs) {
84                         mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, NULL, 0);
85                         must_reload_symtabs = FALSE;
86                 }
87         }
88
89         debugger_lock_level--;
90         LeaveCriticalSection (&debugger_lock_mutex);
91 }
92
93 static MonoDebuggerSymbolFile *
94 allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
95 {
96         MonoDebuggerSymbolFile *symfile;
97
98         if (!table->symbol_files)
99                 table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
100         else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
101                 guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
102                 guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
103
104                 table->symbol_files = g_realloc (table->symbol_files, size);
105         }
106
107         symfile = g_new0 (MonoDebuggerSymbolFile, 1);
108         symfile->index = table->num_symbol_files;
109         symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
110         symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
111         table->symbol_files [table->num_symbol_files++] = symfile;
112         return symfile;
113 }
114
115 void
116 mono_debugger_initialize (MonoDomain *domain)
117 {
118         MonoDebuggerSymbolTable *symbol_table;
119
120         g_assert (!mono_debugger_initialized);
121
122         InitializeCriticalSection (&debugger_lock_mutex);
123         mono_debugger_initialized = TRUE;
124
125         mono_debugger_lock ();
126
127         symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
128         symbol_table->magic = MONO_DEBUGGER_MAGIC;
129         symbol_table->version = MONO_DEBUGGER_VERSION;
130         symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
131
132         symbol_table->domain = domain;
133
134         images = g_hash_table_new (g_direct_hash, g_direct_equal);
135         type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
136         class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
137         class_info_table = g_hash_table_new (g_direct_hash, g_direct_equal);
138
139         mono_debugger_symbol_table = symbol_table;
140
141         mono_debugger_unlock ();
142 }
143
144 MonoDebuggerSymbolFile *
145 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
146 {
147         MonoDebuggerSymbolFile *info;
148
149         g_assert (mono_debugger_initialized);
150         mono_debugger_lock ();
151
152         info = g_hash_table_lookup (images, handle->image);
153         if (info) {
154                 mono_debugger_unlock ();
155                 return info;
156         }
157
158         info = allocate_symbol_file_entry (mono_debugger_symbol_table);
159         info->symfile = handle->symfile;
160         info->image = handle->image;
161         info->image_file = handle->image_file;
162
163         g_hash_table_insert (images, handle->image, info);
164         mono_debugger_unlock ();
165
166         return info;
167 }
168
169 static void
170 write_builtin_type (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerBuiltinTypeInfo *info)
171 {
172         guint8 buffer [BUFSIZ], *ptr = buffer;
173         guint32 size;
174
175         g_assert (!klass->init_pending);
176         mono_class_init (klass);
177
178         switch (klass->byval_arg.type) {
179         case MONO_TYPE_VOID:
180                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
181                 WRITE_UINT32 (ptr, 0);
182                 ptr += 4;
183                 break;
184
185         case MONO_TYPE_BOOLEAN:
186         case MONO_TYPE_I1:
187         case MONO_TYPE_U1:
188         case MONO_TYPE_CHAR:
189         case MONO_TYPE_I2:
190         case MONO_TYPE_U2:
191         case MONO_TYPE_I4:
192         case MONO_TYPE_U4:
193         case MONO_TYPE_R4:
194         case MONO_TYPE_I8:
195         case MONO_TYPE_U8:
196         case MONO_TYPE_R8:
197                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
198                 WRITE_UINT32 (ptr, klass->instance_size - sizeof (MonoObject));
199                 ptr += 4;
200                 break;
201
202         case MONO_TYPE_STRING: {
203                 MonoString string;
204
205                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
206                 WRITE_UINT32 (ptr, klass->instance_size);
207                 ptr += 4;
208                 *ptr++ = (guint8*)&string.length - (guint8*)&string;
209                 *ptr++ = sizeof (string.length);
210                 *ptr++ = (guint8*)&string.chars - (guint8*)&string;
211
212                 break;
213         }
214
215         case MONO_TYPE_I:
216         case MONO_TYPE_U:
217                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
218                 WRITE_UINT32 (ptr, sizeof (void *));
219                 ptr += 4;
220                 break;
221
222         case MONO_TYPE_VALUETYPE:
223                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
224                 WRITE_UINT32 (ptr, klass->instance_size);
225                 ptr += 4;
226                 break;
227
228         case MONO_TYPE_CLASS:
229                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
230                 WRITE_UINT32 (ptr, klass->instance_size);
231                 ptr += 4;
232                 break;
233
234         case MONO_TYPE_OBJECT:
235                 g_assert (klass == mono_defaults.object_class);
236                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
237                 WRITE_UINT32 (ptr, klass->instance_size);
238                 ptr += 4;
239                 break;
240
241         default:
242                 g_error (G_STRLOC ": Unknown builtin type %s.%s - %d", klass->name_space, klass->name, klass->byval_arg.type);
243         }
244
245         size = ptr - buffer;
246         info->cinfo->type_info = info->type_info = allocate_type_entry (table, size, &info->type_data);
247         memcpy (info->type_data, buffer, size);
248 }
249
250 static MonoDebuggerBuiltinTypeInfo *
251 add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
252 {
253         MonoDebuggerClassInfo *cinfo;
254         MonoDebuggerBuiltinTypeInfo *info;
255
256         cinfo = g_new0 (MonoDebuggerClassInfo, 1);
257         cinfo->klass = klass;
258         if (klass->rank) {
259                 cinfo->token = klass->element_class->type_token;
260                 cinfo->rank = klass->rank;
261         } else
262                 cinfo->token = klass->type_token;
263
264         g_hash_table_insert (class_info_table, klass, cinfo);
265
266         info = g_new0 (MonoDebuggerBuiltinTypeInfo, 1);
267         info->klass = klass;
268         info->cinfo = cinfo;
269
270         write_builtin_type (mono_debugger_symbol_table, klass, info);
271         return info;
272 }
273
274 static void
275 add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo *info)
276 {
277         info->class_info = write_class (mono_debugger_symbol_table, info->klass);
278         * (guint32 *) (info->type_data + 5) = info->class_info;
279 }
280
281 MonoDebuggerBuiltinTypes *
282 mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
283 {
284         MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
285
286         mono_debugger_symbol_table->corlib = symfile;
287         mono_debugger_symbol_table->builtin_types = types;
288
289         types->total_size = sizeof (MonoDebuggerBuiltinTypes);
290         types->type_info_size = sizeof (MonoDebuggerBuiltinTypeInfo);
291
292         types->object_type = add_builtin_type (symfile, mono_defaults.object_class);
293         types->byte_type = add_builtin_type (symfile, mono_defaults.byte_class);
294         types->void_type = add_builtin_type (symfile, mono_defaults.void_class);
295         types->boolean_type = add_builtin_type (symfile, mono_defaults.boolean_class);
296         types->sbyte_type = add_builtin_type (symfile, mono_defaults.sbyte_class);
297         types->int16_type = add_builtin_type (symfile, mono_defaults.int16_class);
298         types->uint16_type = add_builtin_type (symfile, mono_defaults.uint16_class);
299         types->int32_type = add_builtin_type (symfile, mono_defaults.int32_class);
300         types->uint32_type = add_builtin_type (symfile, mono_defaults.uint32_class);
301         types->int_type = add_builtin_type (symfile, mono_defaults.int_class);
302         types->uint_type = add_builtin_type (symfile, mono_defaults.uint_class);
303         types->int64_type = add_builtin_type (symfile, mono_defaults.int64_class);
304         types->uint64_type = add_builtin_type (symfile, mono_defaults.uint64_class);
305         types->single_type = add_builtin_type (symfile, mono_defaults.single_class);
306         types->double_type = add_builtin_type (symfile, mono_defaults.double_class);
307         types->char_type = add_builtin_type (symfile, mono_defaults.char_class);
308         types->string_type = add_builtin_type (symfile, mono_defaults.string_class);
309
310         types->enum_type = add_builtin_type (symfile, mono_defaults.enum_class);
311         types->array_type = add_builtin_type (symfile, mono_defaults.array_class);
312         types->exception_type = add_builtin_type (symfile, mono_defaults.exception_class);
313
314         add_builtin_type_2 (types->object_type);
315         add_builtin_type_2 (types->byte_type);
316         add_builtin_type_2 (types->void_type);
317         add_builtin_type_2 (types->boolean_type);
318         add_builtin_type_2 (types->sbyte_type);
319         add_builtin_type_2 (types->int16_type);
320         add_builtin_type_2 (types->uint16_type);
321         add_builtin_type_2 (types->int32_type);
322         add_builtin_type_2 (types->uint32_type);
323         add_builtin_type_2 (types->int_type);
324         add_builtin_type_2 (types->uint_type);
325         add_builtin_type_2 (types->int64_type);
326         add_builtin_type_2 (types->uint64_type);
327         add_builtin_type_2 (types->single_type);
328         add_builtin_type_2 (types->double_type);
329         add_builtin_type_2 (types->char_type);
330         add_builtin_type_2 (types->string_type);
331         add_builtin_type_2 (types->enum_type);
332         add_builtin_type_2 (types->array_type);
333         add_builtin_type_2 (types->exception_type);
334
335         return types;
336 }
337
338 void
339 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
340 {
341         MonoDebuggerClassInfo *cinfo;
342
343         mono_debugger_lock ();
344
345         cinfo = g_hash_table_lookup (class_info_table, klass);
346         if (cinfo) {
347                 mono_debugger_unlock ();
348                 return;
349         }
350
351         symfile->generation++;
352
353         cinfo = allocate_class_entry (symfile);
354         cinfo->klass = klass;
355         if (klass->rank) {
356                 cinfo->token = klass->element_class->type_token;
357                 cinfo->rank = klass->rank;
358         } else
359                 cinfo->token = klass->type_token;
360         g_hash_table_insert (class_info_table, klass, cinfo);
361
362         cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
363
364         must_reload_symtabs = TRUE;
365         mono_debugger_unlock ();
366 }
367
368 void
369 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
370                           MonoDebugMethodJitInfo *jit)
371 {
372         MonoSymbolFileMethodAddress *address;
373         MonoSymbolFileLexicalBlockEntry *block;
374         MonoDebugVarInfo *var_table;
375         MonoDebuggerRangeInfo *range;
376         MonoMethodHeader *header;
377         guint32 size, num_variables, variable_size, variable_offset;
378         guint32 type_size, type_offset, *type_index_table, has_this;
379         guint32 line_size, line_offset, block_offset, block_size;
380         MonoDebugLexicalBlockEntry *block_table;
381         MonoDebugLineNumberEntry *line_table;
382         guint32 *type_table;
383         guint8 *ptr;
384         int i;
385
386         if (!symfile->symfile->method_hash)
387                 return;
388
389         header = ((MonoMethodNormal *) minfo->method)->header;
390
391         symfile->generation++;
392
393         size = sizeof (MonoSymbolFileMethodAddress);
394
395         num_variables = read32(&(minfo->entry->_num_parameters)) + read32(&(minfo->entry->_num_locals));
396         has_this = jit->this_var != NULL;
397
398         variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
399         variable_offset = size;
400         size += variable_size;
401
402         type_size = (num_variables + 1) * sizeof (gpointer);
403         type_offset = size;
404         size += type_size;
405
406         if (jit->line_numbers) {
407                 line_offset = size;
408                 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
409                 size += line_size;
410         }
411
412         block_size = read32(&(minfo->entry->_num_lexical_blocks)) * sizeof (MonoSymbolFileLexicalBlockEntry);
413         block_offset = size;
414         size += block_size;
415
416         address = g_malloc0 (size);
417         ptr = (guint8 *) address;
418
419         block = (MonoSymbolFileLexicalBlockEntry *)
420                 (symfile->symfile->raw_contents + read32(&(minfo->entry->_lexical_block_table_offset)));
421         block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
422
423         for (i = 0; i < read32(&(minfo->entry->_num_lexical_blocks)); i++, block++) {
424                 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_start_offset)));
425                 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_end_offset)));
426         }
427
428         address->size = size;
429         address->has_this = has_this;
430         address->start_address = jit->code_start;
431         address->end_address = jit->code_start + jit->code_size;
432         address->method_start_address = address->start_address + jit->prologue_end;
433         address->method_end_address = address->start_address + jit->epilogue_begin;
434         address->wrapper_address = jit->wrapper_addr;
435         address->variable_table_offset = variable_offset;
436         address->type_table_offset = type_offset;
437         address->lexical_block_table_offset = block_offset;
438
439         if (jit->line_numbers) {
440                 address->num_line_numbers = jit->line_numbers->len;
441                 address->line_number_offset = line_offset;
442
443                 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
444                 memcpy (line_table, jit->line_numbers->data, line_size);
445         }
446
447         range = allocate_range_entry (symfile);
448         range->index = minfo->index;
449         range->start_address = address->start_address;
450         range->end_address = address->end_address;
451         range->dynamic_data = address;
452         range->dynamic_size = size;
453
454         if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
455             (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
456             (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
457                 return;
458
459         var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
460         type_table = (guint32 *) (ptr + type_offset);
461
462         type_index_table = (guint32 *)
463                 (symfile->symfile->raw_contents + read32(&(minfo->entry->_type_index_table_offset)));
464
465         if (jit->this_var)
466                 *var_table++ = *jit->this_var;
467         *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
468
469         if (jit->num_params != read32(&(minfo->entry->_num_parameters))) {
470                 g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
471                            minfo->method->klass->name, minfo->method->name, jit->num_params,
472                            read32(&(minfo->entry->_num_parameters)));
473                 var_table += read32(&(minfo->entry->_num_parameters));
474         } else {
475                 for (i = 0; i < jit->num_params; i++) {
476                         *var_table++ = jit->params [i];
477                         *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
478                 }
479         }
480
481         if (jit->num_locals < read32(&(minfo->entry->_num_locals))) {
482                 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
483                            minfo->method->klass->name, minfo->method->name, jit->num_locals,
484                            read32(&(minfo->entry->_num_locals)));
485                 var_table += read32(&(minfo->entry->_num_locals));
486         } else {
487                 g_assert ((header != NULL) || (minfo->entry->_num_locals == 0));
488                 for (i = 0; i < read32(&(minfo->entry->_num_locals)); i++) {
489                         *var_table++ = jit->locals [i];
490                         *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
491                 }
492         }
493
494         must_reload_symtabs = TRUE;
495 }
496
497 static MonoDebuggerRangeInfo *
498 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
499 {
500         MonoDebuggerRangeInfo *retval;
501         guint32 size, chunks;
502
503         if (!symfile->range_table) {
504                 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
505                 symfile->range_table = g_malloc0 (size);
506                 symfile->num_range_entries = 1;
507                 return symfile->range_table;
508         }
509
510         if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
511                 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
512                 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
513
514                 symfile->range_table = g_realloc (symfile->range_table, size);
515         }
516
517         retval = symfile->range_table + symfile->num_range_entries;
518         symfile->num_range_entries++;
519         return retval;
520 }
521
522 static MonoDebuggerClassInfo *
523 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
524 {
525         MonoDebuggerClassInfo *retval;
526         guint32 size, chunks;
527
528         if (!symfile->class_table) {
529                 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
530                 symfile->class_table = g_malloc0 (size);
531                 symfile->num_class_entries = 1;
532                 return symfile->class_table;
533         }
534
535         if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
536                 chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
537                 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
538
539                 symfile->class_table = g_realloc (symfile->class_table, size);
540         }
541
542         retval = symfile->class_table + symfile->num_class_entries;
543         symfile->num_class_entries++;
544         return retval;
545 }
546
547 /*
548  * Allocate a new entry of size `size' in the type table.
549  * Returns the global offset which is to be used to reference this type and
550  * a pointer (in the `ptr' argument) which is to be used to write the type.
551  */
552 static guint32
553 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
554 {
555         guint32 retval;
556         guint8 *data;
557
558         g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
559         g_assert (ptr != NULL);
560
561         /* Initialize things if necessary. */
562         if (!table->current_type_table) {
563                 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
564                 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
565                 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
566                 table->type_table_offset = 1;
567         }
568
569  again:
570         /* First let's check whether there's still enough room in the current_type_table. */
571         if (table->type_table_offset + size + 4 < table->type_table_size) {
572                 retval = table->type_table_offset;
573                 table->type_table_offset += size + 4;
574                 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
575                 *(gint32 *) data = size;
576                 data += sizeof(gint32);
577                 *ptr = data;
578                 return retval;
579         }
580
581         /* Add the current_type_table to the type_tables vector and ... */
582         if (!table->type_tables) {
583                 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
584                 table->type_tables = g_malloc0 (tsize);
585         }
586
587         if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
588                 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
589                 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
590
591                 table->type_tables = g_realloc (table->type_tables, tsize);
592         }
593
594         table->type_tables [table->num_type_tables++] = table->current_type_table;
595
596         /* .... allocate a new current_type_table. */
597         table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
598         table->type_table_start = table->type_table_offset = table->type_table_size;
599         table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
600
601         goto again;
602 }
603
604 static gboolean
605 property_is_static (MonoProperty *prop)
606 {
607         MonoMethod *method;
608
609         method = prop->get;
610         if (!method)
611                 method = prop->set;
612
613         return method->flags & METHOD_ATTRIBUTE_STATIC;
614 }
615
616 static guint32
617 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
618 {
619         guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
620         GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL;
621         int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
622         int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
623         int num_ctors = 0, num_ctor_params = 0;
624         guint32 size, data_size, offset;
625         GHashTable *method_slots = NULL;
626         int i;
627
628         g_assert (!klass->init_pending);
629         mono_class_init (klass);
630
631         offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
632         if (offset)
633                 return offset;
634
635         if (klass->enumtype) {
636                 offset = allocate_type_entry (table, 13, &ptr);
637                 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
638
639                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
640                 WRITE_UINT32 (ptr, klass->instance_size);
641                 WRITE_UINT32 (ptr, table->builtin_types->enum_type->type_info);
642                 WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
643                 return offset;
644         }
645
646         for (i = 0; i < klass->field.count; i++)
647                 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
648                         ++num_fields;
649                 else
650                         ++num_static_fields;
651
652         for (i = 0; i < klass->property.count; i++)
653                 if (!property_is_static (&klass->properties [i]))
654                         ++num_properties;
655                 else
656                         ++num_static_properties;
657
658         method_slots = g_hash_table_new (NULL, NULL);
659         methods = g_ptr_array_new ();
660         static_methods = g_ptr_array_new ();
661         ctors = g_ptr_array_new ();
662
663         for (i = 0; i < klass->method.count; i++) {
664                 MonoMethod *method = klass->methods [i];
665
666                 if (!strcmp (method->name, ".cctor"))
667                         continue;
668                 if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
669                         continue;
670
671                 if (!strcmp (method->name, ".ctor")) {
672                         ++num_ctors;
673                         num_ctor_params += method->signature->param_count;
674                         g_ptr_array_add (ctors, method);
675                         continue;
676                 }
677
678                 if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
679                         continue;
680                 
681                 if (method->slot != -1) {
682                         if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
683                                 continue;
684                         g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
685                 }
686
687                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
688                         ++num_static_methods;
689                         num_static_params += method->signature->param_count;
690                         g_ptr_array_add (static_methods, method);
691                 } else {
692                         ++num_methods;
693                         num_params += method->signature->param_count;
694                         g_ptr_array_add (methods, method);
695                 }
696         }
697
698         g_hash_table_destroy (method_slots);
699
700         size = 66 + sizeof (gpointer) + num_fields * 8 + num_static_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
701                 num_static_properties * (4 + 2 * sizeof (gpointer)) + num_methods * (8 + sizeof (gpointer)) + num_params * 4 +
702                 num_static_methods * (8 + sizeof (gpointer)) + num_static_params * 4 + num_ctors * (8 + sizeof (gpointer)) +
703                 num_ctor_params * 4;
704
705         data_size = size;
706
707         offset = allocate_type_entry (table, data_size, &ptr);
708         old_ptr = ptr;
709
710         g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
711
712         *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
713
714         if (klass->valuetype)
715                 base_offset = - sizeof (MonoObject);
716
717         WRITE_UINT32 (ptr, klass->instance_size + base_offset);
718         *ptr++ = klass->valuetype;
719         WRITE_POINTER (ptr, klass);
720         WRITE_UINT32 (ptr, num_fields);
721         WRITE_UINT32 (ptr, num_fields * 8);
722         WRITE_UINT32 (ptr, num_static_fields);
723         WRITE_UINT32 (ptr, num_static_fields * 8);
724         WRITE_UINT32 (ptr, num_properties);
725         WRITE_UINT32 (ptr, num_properties * (4 + 2 * sizeof (gpointer)));
726         WRITE_UINT32 (ptr, num_static_properties);
727         WRITE_UINT32 (ptr, num_static_properties * (4 + 2 * sizeof (gpointer)));
728         WRITE_UINT32 (ptr, num_methods);
729         WRITE_UINT32 (ptr, num_methods * (4 + 2 * sizeof (gpointer)) + num_params * sizeof (gpointer));
730         WRITE_UINT32 (ptr, num_static_methods);
731         WRITE_UINT32 (ptr, num_static_methods * (4 + 2 * sizeof (gpointer)) + num_static_params * sizeof (gpointer));
732         WRITE_UINT32 (ptr, num_ctors);
733         WRITE_UINT32 (ptr, num_ctors * (4 + 2 * sizeof (gpointer)) + num_ctor_params * sizeof (gpointer));
734
735         for (i = 0; i < klass->field.count; i++) {
736                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
737                         continue;
738
739                 WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
740                 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
741         }
742
743         for (i = 0; i < klass->property.count; i++) {
744                 if (property_is_static (&klass->properties [i]))
745                         continue;
746
747                 if (klass->properties [i].get)
748                         WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
749                 else
750                         WRITE_UINT32 (ptr, 0);
751                 WRITE_POINTER (ptr, klass->properties [i].get);
752                 WRITE_POINTER (ptr, klass->properties [i].set);
753         }
754
755         for (i = 0; i < methods->len; i++) {
756                 MonoMethod *method = g_ptr_array_index (methods, i);
757                 int j;
758
759                 WRITE_POINTER (ptr, method);
760                 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
761                         WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
762                 else
763                         WRITE_UINT32 (ptr, 0);
764                 WRITE_UINT32 (ptr, method->signature->param_count);
765                 for (j = 0; j < method->signature->param_count; j++)
766                         WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
767         }
768
769         g_ptr_array_free (methods, FALSE);
770
771         for (i = 0; i < klass->field.count; i++) {
772                 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
773                         continue;
774
775                 WRITE_UINT32 (ptr, klass->fields [i].offset);
776                 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
777         }
778
779         for (i = 0; i < klass->property.count; i++) {
780                 if (!property_is_static (&klass->properties [i]))
781                         continue;
782
783                 if (klass->properties [i].get)
784                         WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
785                 else
786                         WRITE_UINT32 (ptr, 0);
787                 WRITE_POINTER (ptr, klass->properties [i].get);
788                 WRITE_POINTER (ptr, klass->properties [i].set);
789         }
790
791         for (i = 0; i < static_methods->len; i++) {
792                 MonoMethod *method = g_ptr_array_index (static_methods, i);
793                 int j;
794
795                 WRITE_POINTER (ptr, method);
796                 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
797                         WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
798                 else
799                         WRITE_UINT32 (ptr, 0);
800                 WRITE_UINT32 (ptr, method->signature->param_count);
801                 for (j = 0; j < method->signature->param_count; j++)
802                         WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
803         }
804
805         g_ptr_array_free (static_methods, FALSE);
806
807         for (i = 0; i < ctors->len; i++) {
808                 MonoMethod *ctor = g_ptr_array_index (ctors, i);
809                 int j;
810
811                 WRITE_POINTER (ptr, ctor);
812                 WRITE_UINT32 (ptr, 0);
813                 WRITE_UINT32 (ptr, ctor->signature->param_count);
814                 for (j = 0; j < ctor->signature->param_count; j++)
815                         WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
816         }
817
818         g_ptr_array_free (ctors, FALSE);
819
820         if (klass->parent && (klass->parent != mono_defaults.object_class))
821                 WRITE_UINT32 (ptr, write_class (table, klass->parent));
822         else
823                 WRITE_UINT32 (ptr, 0);
824
825         if (ptr - old_ptr != data_size) {
826                 g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
827                 if (klass)
828                         g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
829                 g_assert_not_reached ();
830         }
831
832         return offset;
833 }
834
835 /*
836  * Adds type `type' to the type table and returns its offset.
837  */
838 static guint32
839 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
840 {
841         guint8 buffer [BUFSIZ], *ptr = buffer;
842         guint32 size, offset;
843         MonoClass *klass;
844
845         offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
846         if (offset)
847                 return offset;
848
849         klass = mono_class_from_mono_type (type);
850         if (klass->init_pending)
851                 return 0;
852         mono_class_init (klass);
853
854         switch (type->type) {
855         case MONO_TYPE_VOID:
856                 return table->builtin_types->void_type->type_info;
857
858         case MONO_TYPE_BOOLEAN:
859                 return table->builtin_types->boolean_type->type_info;
860
861         case MONO_TYPE_I1:
862                 return table->builtin_types->sbyte_type->type_info;
863
864         case MONO_TYPE_U1:
865                 return table->builtin_types->byte_type->type_info;
866
867         case MONO_TYPE_CHAR:
868                 return table->builtin_types->char_type->type_info;
869
870         case MONO_TYPE_I2:
871                 return table->builtin_types->int16_type->type_info;
872
873         case MONO_TYPE_U2:
874                 return table->builtin_types->uint16_type->type_info;
875
876         case MONO_TYPE_I4:
877                 return table->builtin_types->int32_type->type_info;
878
879         case MONO_TYPE_U4:
880                 return table->builtin_types->uint32_type->type_info;
881
882         case MONO_TYPE_I8:
883                 return table->builtin_types->int64_type->type_info;
884
885         case MONO_TYPE_U8:
886                 return table->builtin_types->uint64_type->type_info;
887
888         case MONO_TYPE_R4:
889                 return table->builtin_types->single_type->type_info;
890
891         case MONO_TYPE_R8:
892                 return table->builtin_types->double_type->type_info;
893
894         case MONO_TYPE_STRING:
895                 return table->builtin_types->string_type->type_info;
896
897         case MONO_TYPE_I:
898                 return table->builtin_types->int_type->type_info;
899
900         case MONO_TYPE_U:
901                 return table->builtin_types->uint_type->type_info;
902
903         case MONO_TYPE_SZARRAY: {
904                 MonoArray array;
905
906                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
907                 WRITE_UINT32 (ptr, sizeof (MonoArray));
908                 g_assert (table->builtin_types->array_type->type_info != 0);
909                 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
910                 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
911                 *ptr++ = sizeof (array.max_length);
912                 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
913                 WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
914                 break;
915         }
916
917         case MONO_TYPE_ARRAY: {
918                 MonoArray array;
919                 MonoArrayBounds bounds;
920
921                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
922                 WRITE_UINT32 (ptr, sizeof (MonoArray));
923                 g_assert (table->builtin_types->array_type->type_info != 0);
924                 WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
925                 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
926                 *ptr++ = sizeof (array.max_length);
927                 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
928                 *ptr++ = klass->rank;
929                 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
930                 *ptr++ = sizeof (MonoArrayBounds);
931                 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
932                 *ptr++ = sizeof (bounds.lower_bound);
933                 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
934                 *ptr++ = sizeof (bounds.length);
935                 WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
936                 break;
937         }
938
939         case MONO_TYPE_VALUETYPE:
940         case MONO_TYPE_CLASS:
941         case MONO_TYPE_OBJECT:
942                 return write_class (table, klass);
943
944         case MONO_TYPE_PTR:
945                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
946                 WRITE_UINT32 (ptr, sizeof (gpointer));
947                 WRITE_UINT32 (ptr, write_type (table, type->data.type));
948                 break;
949
950         default:
951                 /* g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type); */
952                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
953                 WRITE_UINT32 (ptr, klass->instance_size);
954                 WRITE_UINT32 (ptr, write_class (table, klass));
955                 break;
956         }
957
958         size = ptr - buffer;
959         offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
960         memcpy (ptr, buffer, size);
961
962         return offset;
963 }
964
965 MonoReflectionMethod *
966 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
967 {
968         MonoMethod *method;
969
970         method = mono_get_method (assembly->assembly->image, token, NULL);
971
972         return mono_method_get_object (mono_domain_get (), method, NULL);
973 }
974
975 int
976 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
977 {
978         return method->method->token;
979 }
980
981 MonoReflectionType *
982 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
983 {
984         MonoClass *klass;
985
986         klass = mono_class_get (assembly->assembly->image, token);
987         if (!klass) {
988                 g_warning (G_STRLOC ": %x", token);
989                 return NULL;
990         }
991
992         return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
993 }
994
995 MonoReflectionType *
996 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
997 {
998         MonoDomain *domain; 
999         MonoImage *image;
1000         MonoType *type;
1001         const char *ptr;
1002         int len = 0;
1003
1004         MONO_CHECK_ARG_NULL (assembly);
1005         MONO_CHECK_ARG_NULL (signature);
1006
1007         domain = mono_domain_get();
1008         image = assembly->assembly->image;
1009
1010         ptr = mono_array_addr (signature, char, 0);
1011         g_assert (*ptr++ == 0x07);
1012         len = mono_metadata_decode_value (ptr, &ptr);
1013         g_assert (len == 1);
1014
1015         type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1016
1017         return mono_type_get_object (domain, type);
1018 }
1019
1020 void
1021 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
1022 {
1023         if (mono_debugger_event_handler)
1024                 (* mono_debugger_event_handler) (event, data, arg);
1025 }
1026
1027 void
1028 mono_debugger_cleanup (void)
1029 {
1030         /* Do nothing yet. */
1031 }
1032
1033 /*
1034  * Debugger breakpoint interface.
1035  *
1036  * This interface is used to insert breakpoints on methods which are not yet JITed.
1037  * The debugging code keeps a list of all such breakpoints and automatically inserts the
1038  * breakpoint when the method is JITed.
1039  */
1040
1041 static GPtrArray *breakpoints = NULL;
1042
1043 int
1044 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
1045 {
1046         static int last_breakpoint_id = 0;
1047         MonoDebuggerBreakpointInfo *info;
1048
1049         info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1050         info->desc = desc;
1051         info->index = ++last_breakpoint_id;
1052
1053         if (!breakpoints)
1054                 breakpoints = g_ptr_array_new ();
1055
1056         g_ptr_array_add (breakpoints, info);
1057
1058         return info->index;
1059 }
1060
1061 int
1062 mono_debugger_remove_breakpoint (int breakpoint_id)
1063 {
1064         int i;
1065
1066         if (!breakpoints)
1067                 return 0;
1068
1069         for (i = 0; i < breakpoints->len; i++) {
1070                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1071
1072                 if (info->index != breakpoint_id)
1073                         continue;
1074
1075                 mono_method_desc_free (info->desc);
1076                 g_ptr_array_remove (breakpoints, info);
1077                 g_free (info);
1078                 return 1;
1079         }
1080
1081         return 0;
1082 }
1083
1084 int
1085 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1086 {
1087         MonoMethodDesc *desc;
1088
1089         desc = mono_method_desc_new (method_name, include_namespace);
1090         if (!desc)
1091                 return 0;
1092
1093         return mono_debugger_insert_breakpoint_full (desc);
1094 }
1095
1096 int
1097 mono_debugger_method_has_breakpoint (MonoMethod *method)
1098 {
1099         int i;
1100
1101         if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1102                 return 0;
1103
1104         for (i = 0; i < breakpoints->len; i++) {
1105                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1106
1107                 if (!mono_method_desc_full_match (info->desc, method))
1108                         continue;
1109
1110                 return info->index;
1111         }
1112
1113         return 0;
1114 }
1115
1116 void
1117 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
1118 {
1119         mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
1120 }
1121
1122 static gchar *
1123 get_exception_message (MonoObject *exc)
1124 {
1125         char *message = NULL;
1126         MonoString *str; 
1127         MonoMethod *method;
1128         MonoClass *klass;
1129         gint i;
1130
1131         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1132                 klass = exc->vtable->klass;
1133                 method = NULL;
1134                 while (klass && method == NULL) {
1135                         for (i = 0; i < klass->method.count; ++i) {
1136                                 method = klass->methods [i];
1137                                 if (!strcmp ("ToString", method->name) &&
1138                                     method->signature->param_count == 0 &&
1139                                     method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1140                                     method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1141                                         break;
1142                                 }
1143                                 method = NULL;
1144                         }
1145                         
1146                         if (method == NULL)
1147                                 klass = klass->parent;
1148                 }
1149
1150                 g_assert (method);
1151
1152                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1153                 if (str)
1154                         message = mono_string_to_utf8 (str);
1155         }
1156
1157         return message;
1158 }
1159
1160 MonoObject *
1161 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1162 {
1163         MonoObject *retval;
1164         gchar *message;
1165
1166         if (method->klass->valuetype && (obj != NULL))
1167                 obj = mono_value_box (mono_domain_get (), method->klass, obj);
1168
1169         if (!strcmp (method->name, ".ctor")) {
1170                 retval = obj = mono_object_new (mono_domain_get (), method->klass);
1171
1172                 mono_runtime_invoke (method, obj, params, exc);
1173         } else
1174                 retval = mono_runtime_invoke (method, obj, params, exc);
1175
1176         if (*exc == NULL)
1177                 return retval;
1178
1179         message = get_exception_message (*exc);
1180         if (message) {
1181                 *exc = (MonoObject *) mono_string_new_wrapper (message);
1182                 g_free (message);
1183         }
1184
1185         return retval;
1186 }
1187
1188 guint32
1189 mono_debugger_lookup_type (const gchar *type_name)
1190 {
1191         int i;
1192
1193         mono_debugger_lock ();
1194
1195         for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1196                 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1197                 MonoType *type;
1198                 guint32 offset;
1199                 gchar *name;
1200
1201                 name = g_strdup (type_name);
1202                 type = mono_reflection_type_from_name (name, symfile->image);
1203                 g_free (name);
1204                 if (!type)
1205                         continue;
1206
1207                 offset = write_type (mono_debugger_symbol_table, type);
1208
1209                 mono_debugger_unlock ();
1210                 return offset;
1211         }
1212
1213         mono_debugger_unlock ();
1214         return 0;
1215 }
1216
1217 gint32
1218 mono_debugger_lookup_assembly (const gchar *name)
1219 {
1220         MonoAssembly *assembly;
1221         MonoImageOpenStatus status;
1222         int i;
1223
1224         mono_debugger_lock ();
1225
1226  again:
1227         for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1228                 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1229
1230                 if (!strcmp (symfile->image_file, name)) {
1231                         mono_debugger_unlock ();
1232                         return i;
1233                 }
1234         }
1235
1236         assembly = mono_assembly_open (name, &status);
1237
1238         if (status != MONO_IMAGE_OK) {
1239                 g_warning (G_STRLOC ": Cannot open image `%s'", name);
1240                 mono_debugger_unlock ();
1241                 return -1;
1242         }
1243
1244         must_reload_symtabs = TRUE;
1245         goto again;
1246 }