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