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