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