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