c16bd77cf8739589916dcb2b969ec73e27aaadb1
[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         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, NULL, 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         if (builtin_types_initialized && !klass->init_pending)
410                 mono_class_init (klass);
411
412         centry = g_hash_table_lookup (class_info_table, klass);
413         if (!centry) {
414                 MonoDebuggerSymbolFile *symfile = _mono_debugger_get_symfile (klass->image);
415
416                 g_assert (symfile);
417                 mono_debugger_start_add_type (symfile, klass);
418                 centry = g_hash_table_lookup (class_info_table, klass);
419         }
420         g_assert (centry);
421
422         if (centry->info) {
423                 g_assert (centry->info->type_info);
424                 return centry->info->type_info;
425         }
426
427         if (!centry->type_reference) {
428                 guint8 *ptr;
429
430                 centry->type_reference = allocate_type_entry (table, 5, &ptr);
431
432                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_REFERENCE;
433                 WRITE_POINTER (ptr, klass);
434         }
435
436         return centry->type_reference;
437 }
438
439 void
440 mono_debugger_start_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
441 {
442         MonoDebuggerClassEntry *centry;
443
444         mono_debugger_lock ();
445         centry = g_hash_table_lookup (class_info_table, klass);
446         if (centry) {
447                 mono_debugger_unlock ();
448                 return;
449         }
450
451         centry = g_new0 (MonoDebuggerClassEntry, 1);
452         g_hash_table_insert (class_info_table, klass, centry);
453         mono_debugger_unlock ();
454 }
455
456 void
457 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
458 {
459         MonoDebuggerClassEntry *centry;
460
461         mono_debugger_lock ();
462         centry = g_hash_table_lookup (class_info_table, klass);
463         g_assert (centry);
464
465         if (centry->info) {
466                 mono_debugger_unlock ();
467                 return;
468         }
469
470         centry->info = allocate_class_entry (symfile);
471         centry->info->klass = klass;
472         if (klass->rank) {
473                 centry->info->token = klass->element_class->type_token;
474                 centry->info->rank = klass->rank;
475         } else
476                 centry->info->token = klass->type_token;
477
478         do_write_class (mono_debugger_symbol_table, klass, centry->info);
479
480         g_assert (centry->info && centry->info->type_info);
481
482         symfile->generation++;
483         must_reload_symtabs = TRUE;
484
485         mono_debugger_unlock ();
486 }
487
488 void
489 mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
490                           MonoDebugMethodJitInfo *jit)
491 {
492         MonoSymbolFileMethodAddress *address;
493         MonoSymbolFileLexicalBlockEntry *block;
494         MonoDebugVarInfo *var_table;
495         MonoDebuggerRangeInfo *range;
496         MonoMethodHeader *header;
497         guint32 size, num_variables, variable_size, variable_offset;
498         guint32 type_size, type_offset, *type_index_table, has_this;
499         guint32 line_size, line_offset, block_offset, block_size;
500         MonoDebugLexicalBlockEntry *block_table;
501         MonoDebugLineNumberEntry *line_table;
502         guint32 *type_table;
503         guint8 *ptr;
504         int i;
505
506         if (!symfile->symfile->method_hash)
507                 return;
508
509         header = ((MonoMethodNormal *) minfo->method)->header;
510
511         symfile->generation++;
512
513         size = sizeof (MonoSymbolFileMethodAddress);
514
515         num_variables = jit->num_params + read32(&(minfo->entry->_num_locals));
516         has_this = jit->this_var != NULL;
517
518         variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
519         variable_offset = size;
520         size += variable_size;
521
522         type_size = (num_variables + 1) * sizeof (gpointer);
523         type_offset = size;
524         size += type_size;
525
526         if (jit->line_numbers) {
527                 line_offset = size;
528                 line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
529                 size += line_size;
530         }
531
532         block_size = read32(&(minfo->entry->_num_lexical_blocks)) * sizeof (MonoSymbolFileLexicalBlockEntry);
533         block_offset = size;
534         size += block_size;
535
536         address = g_malloc0 (size);
537         ptr = (guint8 *) address;
538
539         block = (MonoSymbolFileLexicalBlockEntry *)
540                 (symfile->symfile->raw_contents + read32(&(minfo->entry->_lexical_block_table_offset)));
541         block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
542
543         for (i = 0; i < read32(&(minfo->entry->_num_lexical_blocks)); i++, block++) {
544                 block_table [i].start_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_start_offset)));
545                 block_table [i].end_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_end_offset)));
546         }
547
548         address->size = size;
549         address->has_this = has_this;
550         address->num_params = jit->num_params;
551         address->start_address = jit->code_start;
552         address->end_address = jit->code_start + jit->code_size;
553         address->method_start_address = address->start_address + jit->prologue_end;
554         address->method_end_address = address->start_address + jit->epilogue_begin;
555         address->wrapper_address = jit->wrapper_addr;
556         address->variable_table_offset = variable_offset;
557         address->type_table_offset = type_offset;
558         address->lexical_block_table_offset = block_offset;
559
560         if (jit->line_numbers) {
561                 address->num_line_numbers = jit->line_numbers->len;
562                 address->line_number_offset = line_offset;
563
564                 line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
565                 memcpy (line_table, jit->line_numbers->data, line_size);
566         }
567
568         range = allocate_range_entry (symfile);
569         range->index = minfo->index;
570         range->start_address = address->start_address;
571         range->end_address = address->end_address;
572         range->dynamic_data = address;
573         range->dynamic_size = size;
574
575         if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
576             (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
577             (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
578                 return;
579
580         var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
581         type_table = (guint32 *) (ptr + type_offset);
582
583         type_index_table = (guint32 *)
584                 (symfile->symfile->raw_contents + read32(&(minfo->entry->_type_index_table_offset)));
585
586         if (jit->this_var)
587                 *var_table++ = *jit->this_var;
588         *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
589
590         for (i = 0; i < jit->num_params; i++) {
591                 *var_table++ = jit->params [i];
592                 *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
593         }
594
595         if (jit->num_locals < read32(&(minfo->entry->_num_locals))) {
596                 g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
597                            minfo->method->klass->name, minfo->method->name, jit->num_locals,
598                            read32(&(minfo->entry->_num_locals)));
599                 var_table += read32(&(minfo->entry->_num_locals));
600         } else {
601                 g_assert ((header != NULL) || (minfo->entry->_num_locals == 0));
602                 for (i = 0; i < read32(&(minfo->entry->_num_locals)); i++) {
603                         *var_table++ = jit->locals [i];
604                         *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
605                 }
606         }
607
608         must_reload_symtabs = TRUE;
609 }
610
611 static MonoDebuggerRangeInfo *
612 allocate_range_entry (MonoDebuggerSymbolFile *symfile)
613 {
614         MonoDebuggerRangeInfo *retval;
615         guint32 size, chunks;
616
617         if (!symfile->range_table) {
618                 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
619                 symfile->range_table = g_malloc0 (size);
620                 symfile->num_range_entries = 1;
621                 return symfile->range_table;
622         }
623
624         if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
625                 chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
626                 size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
627
628                 symfile->range_table = g_realloc (symfile->range_table, size);
629         }
630
631         retval = symfile->range_table + symfile->num_range_entries;
632         symfile->num_range_entries++;
633         return retval;
634 }
635
636 static MonoDebuggerClassInfo *
637 allocate_class_entry (MonoDebuggerSymbolFile *symfile)
638 {
639         MonoDebuggerClassInfo *retval;
640         MonoDebuggerClassTable *table;
641         guint32 size;
642
643         if (!symfile->class_table_start) {
644                 table = g_new0 (MonoDebuggerClassTable, 1);
645                 symfile->class_table_start = symfile->current_class_table = table;
646
647                 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
648                 table->data = g_malloc0 (size);
649                 table->size = CLASS_TABLE_CHUNK_SIZE;
650                 table->index = 1;
651
652                 return table->data;
653         }
654
655         table = symfile->current_class_table;
656         if (table->index >= table->size) {
657                 table = g_new0 (MonoDebuggerClassTable, 1);
658
659                 symfile->current_class_table->next = table;
660                 symfile->current_class_table = table;
661
662                 size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
663                 table->data = g_malloc0 (size);
664                 table->size = CLASS_TABLE_CHUNK_SIZE;
665                 table->index = 1;
666
667                 return table->data;
668         }
669
670         retval = table->data + table->index;
671         table->index++;
672         return retval;
673 }
674
675 /*
676  * Allocate a new entry of size `size' in the type table.
677  * Returns the global offset which is to be used to reference this type and
678  * a pointer (in the `ptr' argument) which is to be used to write the type.
679  */
680 static guint32
681 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
682 {
683         guint32 retval;
684         guint8 *data;
685
686         g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
687         g_assert (ptr != NULL);
688
689         /* Initialize things if necessary. */
690         if (!table->current_type_table) {
691                 table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
692                 table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
693                 table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
694                 table->type_table_offset = MONO_DEBUGGER_TYPE_MAX + 1;
695         }
696
697  again:
698         /* First let's check whether there's still enough room in the current_type_table. */
699         if (table->type_table_offset + size + 4 < table->type_table_size) {
700                 retval = table->type_table_offset;
701                 table->type_table_offset += size + 4;
702                 data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
703                 *(gint32 *) data = size;
704                 data += sizeof(gint32);
705                 *ptr = data;
706                 return retval;
707         }
708
709         /* Add the current_type_table to the type_tables vector and ... */
710         if (!table->type_tables) {
711                 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
712                 table->type_tables = g_malloc0 (tsize);
713         }
714
715         if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
716                 guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
717                 guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
718
719                 table->type_tables = g_realloc (table->type_tables, tsize);
720         }
721
722         table->type_tables [table->num_type_tables++] = table->current_type_table;
723
724         /* .... allocate a new current_type_table. */
725         table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
726         table->type_table_start = table->type_table_offset = table->type_table_size;
727         table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
728
729         goto again;
730 }
731
732 /*
733  * Allocate a new entry of size `size' in the misc table.
734  * Returns the global offset which is to be used to reference this entry and
735  * a pointer (in the `ptr' argument) which is to be used to write the entry.
736  */
737 static guint32
738 allocate_misc_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
739 {
740         guint32 retval;
741         guint8 *data;
742
743         g_assert (size + 4 < MISC_TABLE_CHUNK_SIZE);
744         g_assert (ptr != NULL);
745
746         /* Initialize things if necessary. */
747         if (!table->current_misc_table) {
748                 table->current_misc_table = g_malloc0 (MISC_TABLE_CHUNK_SIZE);
749                 table->misc_table_size = MISC_TABLE_CHUNK_SIZE;
750                 table->misc_table_chunk_size = MISC_TABLE_CHUNK_SIZE;
751                 table->misc_table_offset = 1;
752         }
753
754  again:
755         /* First let's check whether there's still enough room in the current_misc_table. */
756         if (table->misc_table_offset + size + 4 < table->misc_table_size) {
757                 retval = table->misc_table_offset;
758                 table->misc_table_offset += size + 4;
759                 data = ((guint8 *) table->current_misc_table) + retval - table->misc_table_start;
760                 *(gint32 *) data = size;
761                 data += sizeof(gint32);
762                 *ptr = data;
763                 return retval;
764         }
765
766         /* Add the current_misc_table to the misc_tables vector and ... */
767         if (!table->misc_tables) {
768                 guint32 tsize = sizeof (gpointer) * MISC_TABLE_PTR_CHUNK_SIZE;
769                 table->misc_tables = g_malloc0 (tsize);
770         }
771
772         if (!((table->num_misc_tables + 1) % MISC_TABLE_PTR_CHUNK_SIZE)) {
773                 guint32 chunks = (table->num_misc_tables + 1) / MISC_TABLE_PTR_CHUNK_SIZE;
774                 guint32 tsize = sizeof (gpointer) * MISC_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
775
776                 table->misc_tables = g_realloc (table->misc_tables, tsize);
777         }
778
779         table->misc_tables [table->num_misc_tables++] = table->current_misc_table;
780
781         /* .... allocate a new current_misc_table. */
782         table->current_misc_table = g_malloc0 (MISC_TABLE_CHUNK_SIZE);
783         table->misc_table_start = table->misc_table_offset = table->misc_table_size;
784         table->misc_table_size += MISC_TABLE_CHUNK_SIZE;
785
786         goto again;
787 }
788
789 static gboolean
790 property_is_static (MonoProperty *prop)
791 {
792         MonoMethod *method;
793
794         method = prop->get;
795         if (!method)
796                 method = prop->set;
797
798         return method->flags & METHOD_ATTRIBUTE_STATIC;
799 }
800
801 static gboolean
802 event_is_static (MonoEvent *ev)
803 {
804         MonoMethod *method;
805
806         method = ev->add;
807
808         return method->flags & METHOD_ATTRIBUTE_STATIC;
809 }
810
811 static guint32
812 do_write_class (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerClassInfo *cinfo)
813 {
814         guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
815         GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL, *cctors = NULL;
816         int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
817         int num_events = 0, num_static_events = 0;
818         int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
819         int num_ctors = 0, num_ctor_params = 0;
820         int num_cctors = 0;
821         int field_info_size = 0, static_field_info_size = 0, property_info_size = 0, event_info_size = 0, static_event_info_size = 0;
822         int static_property_info_size = 0, method_info_size = 0, static_method_info_size = 0;
823         int ctor_info_size = 0, cctor_info_size = 0, iface_info_size = 0;
824         guint32 size, data_size, offset, data_offset;
825         GHashTable *method_slots = NULL;
826         int i;
827
828         if (klass->init_pending)
829                 g_warning (G_STRLOC ": %p - %s.%s", klass, klass->name_space, klass->name);
830         g_assert (!klass->init_pending);
831         mono_class_init (klass);
832
833         offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
834         if (offset)
835                 return offset;
836
837         if (klass->enumtype) {
838                 offset = allocate_type_entry (table, 13, &ptr);
839                 if (cinfo)
840                         cinfo->type_info = offset;
841                 g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
842
843                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
844                 WRITE_UINT32 (ptr, klass->instance_size);
845                 WRITE_UINT32 (ptr, MONO_DEBUGGER_TYPE_ENUM);
846                 WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
847                 return offset;
848         }
849
850         for (i = 0; i < klass->field.count; i++)
851                 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
852                         ++num_fields;
853                 else
854                         ++num_static_fields;
855
856         for (i = 0; i < klass->property.count; i++)
857                 if (!property_is_static (&klass->properties [i]))
858                         ++num_properties;
859                 else
860                         ++num_static_properties;
861
862         for (i = 0; i < klass->event.count; i++)
863                 if (!event_is_static (&klass->events [i]))
864                         ++num_events;
865                 else
866                         ++num_static_events;
867
868         method_slots = g_hash_table_new (NULL, NULL);
869         methods = g_ptr_array_new ();
870         static_methods = g_ptr_array_new ();
871         ctors = g_ptr_array_new ();
872         cctors = g_ptr_array_new ();
873
874         for (i = 0; i < klass->method.count; i++) {
875                 MonoMethod *method = klass->methods [i];
876
877                 if (!strcmp (method->name, ".cctor")) {
878                         ++num_cctors;
879                         g_ptr_array_add (cctors, method);
880                         continue;
881                 }
882
883                 if (!strcmp (method->name, ".ctor")) {
884                         ++num_ctors;
885                         num_ctor_params += method->signature->param_count;
886                         g_ptr_array_add (ctors, method);
887                         continue;
888                 }
889
890                 if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
891                         continue;
892                 
893                 if (method->slot != -1) {
894                         if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
895                                 continue;
896                         g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
897                 }
898
899                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
900                         ++num_static_methods;
901                         num_static_params += method->signature->param_count;
902                         g_ptr_array_add (static_methods, method);
903                 } else {
904                         ++num_methods;
905                         num_params += method->signature->param_count;
906                         g_ptr_array_add (methods, method);
907                 }
908         }
909
910         g_hash_table_destroy (method_slots);
911
912         field_info_size = num_fields * 8;
913         static_field_info_size = num_static_fields * 8;
914         property_info_size = num_properties * (4 + 2 * sizeof (gpointer));
915         static_property_info_size = num_static_properties * (4 + 2 * sizeof (gpointer));
916         event_info_size = num_events * (4 + 2 * sizeof (gpointer));
917         static_event_info_size = num_static_events * (4 + 2 * sizeof (gpointer));
918         method_info_size = num_methods * (2 * 4 + sizeof (gpointer)) + num_params * 4;
919         static_method_info_size = num_static_methods * (2 * 4 + sizeof (gpointer)) +
920                 num_static_params * 4;
921         ctor_info_size = num_ctors * (2 * 4 + sizeof (gpointer)) + num_ctor_params * 4;
922         cctor_info_size = num_cctors * (2 * 4 + sizeof (gpointer));
923         iface_info_size = klass->interface_count * 4;
924
925         size = 98 + sizeof (gpointer) + field_info_size + static_field_info_size +
926                 property_info_size + static_property_info_size + event_info_size +
927                 static_event_info_size + method_info_size + static_method_info_size +
928                 ctor_info_size + cctor_info_size + iface_info_size;
929
930         data_size = size;
931
932         offset = allocate_type_entry (table, data_size, &ptr);
933         old_ptr = ptr;
934
935         if (cinfo)
936                 cinfo->type_info = offset;
937
938         g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
939
940         *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
941
942         if (klass->valuetype)
943                 base_offset = - sizeof (MonoObject);
944
945         WRITE_UINT32 (ptr, klass->instance_size + base_offset);
946         *ptr++ = klass->valuetype;
947         WRITE_POINTER (ptr, klass);
948         data_offset = 0;
949         WRITE_UINT32 (ptr, num_fields);
950         WRITE_UINT32 (ptr, data_offset);
951         data_offset += field_info_size;
952         WRITE_UINT32 (ptr, num_properties);
953         WRITE_UINT32 (ptr, data_offset);
954         data_offset += property_info_size;
955         WRITE_UINT32 (ptr, num_events);
956         WRITE_UINT32 (ptr, data_offset);
957         data_offset += event_info_size;
958         WRITE_UINT32 (ptr, num_methods);
959         WRITE_UINT32 (ptr, data_offset);
960         data_offset += method_info_size;
961         WRITE_UINT32 (ptr, num_static_fields);
962         WRITE_UINT32 (ptr, data_offset);
963         data_offset += static_field_info_size;
964         WRITE_UINT32 (ptr, num_static_properties);
965         WRITE_UINT32 (ptr, data_offset);
966         data_offset += static_property_info_size;
967         WRITE_UINT32 (ptr, num_static_events);
968         WRITE_UINT32 (ptr, data_offset);
969         data_offset += static_event_info_size;
970         WRITE_UINT32 (ptr, num_static_methods);
971         WRITE_UINT32 (ptr, data_offset);
972         data_offset += static_method_info_size;
973         WRITE_UINT32 (ptr, num_ctors);
974         WRITE_UINT32 (ptr, data_offset);
975         data_offset += ctor_info_size;
976         WRITE_UINT32 (ptr, num_cctors);
977         WRITE_UINT32 (ptr, data_offset);
978         data_offset += cctor_info_size;
979         WRITE_UINT32 (ptr, klass->interface_count);
980         WRITE_UINT32 (ptr, data_offset);
981         data_offset += iface_info_size;
982
983         if (klass->parent && (klass->parent != mono_defaults.object_class))
984                 WRITE_UINT32 (ptr, write_class (table, klass->parent));
985         else
986                 WRITE_UINT32 (ptr, 0);
987
988         for (i = 0; i < klass->field.count; i++) {
989                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
990                         continue;
991
992                 WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
993                 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
994         }
995
996         for (i = 0; i < klass->property.count; i++) {
997                 if (property_is_static (&klass->properties [i]))
998                         continue;
999
1000                 if (klass->properties [i].get)
1001                         WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
1002                 else
1003                         WRITE_UINT32 (ptr, 0);
1004                 WRITE_POINTER (ptr, klass->properties [i].get);
1005                 WRITE_POINTER (ptr, klass->properties [i].set);
1006         }
1007
1008         for (i = 0; i < klass->event.count; i++) {
1009                 if (event_is_static (&klass->events[i]))
1010                         continue;
1011
1012                 if (klass->events [i].add) {
1013                         WRITE_UINT32 (ptr, write_type (table, klass->events [i].add->signature->params[0]));
1014                 }
1015                 else {
1016                         g_warning ("event add method not defined");
1017                         WRITE_UINT32 (ptr, 0);
1018                 }
1019                 WRITE_POINTER (ptr, klass->events [i].add);
1020                 WRITE_POINTER (ptr, klass->events [i].remove);
1021                 /* raise?  other? */
1022         }
1023
1024         for (i = 0; i < methods->len; i++) {
1025                 MonoMethod *method = g_ptr_array_index (methods, i);
1026                 int j;
1027
1028                 WRITE_POINTER (ptr, method);
1029                 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
1030                         WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
1031                 else
1032                         WRITE_UINT32 (ptr, 0);
1033                 WRITE_UINT32 (ptr, method->signature->param_count);
1034                 for (j = 0; j < method->signature->param_count; j++)
1035                         WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
1036         }
1037
1038         g_ptr_array_free (methods, FALSE);
1039
1040         for (i = 0; i < klass->field.count; i++) {
1041                 if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
1042                         continue;
1043
1044                 WRITE_UINT32 (ptr, klass->fields [i].offset);
1045                 WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
1046         }
1047
1048         for (i = 0; i < klass->property.count; i++) {
1049                 if (!property_is_static (&klass->properties [i]))
1050                         continue;
1051
1052                 if (klass->properties [i].get)
1053                         WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
1054                 else
1055                         WRITE_UINT32 (ptr, 0);
1056                 WRITE_POINTER (ptr, klass->properties [i].get);
1057                 WRITE_POINTER (ptr, klass->properties [i].set);
1058         }
1059
1060         for (i = 0; i < klass->event.count; i++) {
1061                 if (!event_is_static (&klass->events[i]))
1062                         continue;
1063
1064                 if (klass->events [i].add) {
1065                         WRITE_UINT32 (ptr, write_type (table, klass->events [i].add->signature->params[0]));
1066                 }
1067                 else {
1068                         g_warning ("event add method not defined");
1069                         WRITE_UINT32 (ptr, 0);
1070                 }
1071                 WRITE_POINTER (ptr, klass->events [i].add);
1072                 WRITE_POINTER (ptr, klass->events [i].remove);
1073                 /* raise?  other? */
1074         }
1075
1076         for (i = 0; i < static_methods->len; i++) {
1077                 MonoMethod *method = g_ptr_array_index (static_methods, i);
1078                 int j;
1079
1080                 WRITE_POINTER (ptr, method);
1081                 if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
1082                         WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
1083                 else
1084                         WRITE_UINT32 (ptr, 0);
1085                 WRITE_UINT32 (ptr, method->signature->param_count);
1086                 for (j = 0; j < method->signature->param_count; j++)
1087                         WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
1088         }
1089
1090         g_ptr_array_free (static_methods, FALSE);
1091
1092         for (i = 0; i < ctors->len; i++) {
1093                 MonoMethod *ctor = g_ptr_array_index (ctors, i);
1094                 int j;
1095
1096                 WRITE_POINTER (ptr, ctor);
1097                 WRITE_UINT32 (ptr, 0);
1098                 WRITE_UINT32 (ptr, ctor->signature->param_count);
1099                 for (j = 0; j < ctor->signature->param_count; j++)
1100                         WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
1101         }
1102
1103         g_ptr_array_free (ctors, FALSE);
1104
1105         for (i = 0; i < cctors->len; i++) {
1106                 MonoMethod *cctor = g_ptr_array_index (cctors, i);
1107
1108                 WRITE_POINTER (ptr, cctor);
1109                 WRITE_UINT32 (ptr, 0);
1110                 WRITE_UINT32 (ptr, 0);
1111         }
1112
1113         g_ptr_array_free (cctors, FALSE);
1114
1115         for (i = 0; i < klass->interface_count; i++)
1116                 WRITE_UINT32 (ptr, write_class (table, klass->interfaces [i]));
1117
1118         if (ptr - old_ptr != data_size) {
1119                 g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
1120                 if (klass)
1121                         g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
1122                 g_assert_not_reached ();
1123         }
1124
1125         return offset;
1126 }
1127
1128 /*
1129  * Adds type `type' to the type table and returns its offset.
1130  */
1131 static guint32
1132 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
1133 {
1134         guint8 buffer [BUFSIZ], *ptr = buffer;
1135         guint32 size, offset;
1136         MonoClass *klass;
1137
1138         offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
1139         if (offset)
1140                 return offset;
1141
1142         klass = mono_class_from_mono_type (type);
1143         if (type->type == MONO_TYPE_CLASS)
1144                 return write_class (table, klass);
1145
1146         // mono_class_init (klass);
1147
1148         switch (type->type) {
1149         case MONO_TYPE_VOID:
1150                 return MONO_DEBUGGER_TYPE_VOID;
1151
1152         case MONO_TYPE_BOOLEAN:
1153                 return MONO_DEBUGGER_TYPE_BOOLEAN;
1154
1155         case MONO_TYPE_I1:
1156                 return MONO_DEBUGGER_TYPE_I1;
1157
1158         case MONO_TYPE_U1:
1159                 return MONO_DEBUGGER_TYPE_U1;
1160
1161         case MONO_TYPE_CHAR:
1162                 return MONO_DEBUGGER_TYPE_CHAR;
1163
1164         case MONO_TYPE_I2:
1165                 return MONO_DEBUGGER_TYPE_I2;
1166
1167         case MONO_TYPE_U2:
1168                 return MONO_DEBUGGER_TYPE_U2;
1169
1170         case MONO_TYPE_I4:
1171                 return MONO_DEBUGGER_TYPE_I4;
1172
1173         case MONO_TYPE_U4:
1174                 return MONO_DEBUGGER_TYPE_U4;
1175
1176         case MONO_TYPE_I8:
1177                 return MONO_DEBUGGER_TYPE_I8;
1178
1179         case MONO_TYPE_U8:
1180                 return MONO_DEBUGGER_TYPE_U8;
1181
1182         case MONO_TYPE_R4:
1183                 return MONO_DEBUGGER_TYPE_R4;
1184
1185         case MONO_TYPE_R8:
1186                 return MONO_DEBUGGER_TYPE_R8;
1187
1188         case MONO_TYPE_STRING:
1189                 return MONO_DEBUGGER_TYPE_STRING;
1190
1191         case MONO_TYPE_I:
1192                 return MONO_DEBUGGER_TYPE_I;
1193
1194         case MONO_TYPE_U:
1195                 return MONO_DEBUGGER_TYPE_U;
1196
1197         case MONO_TYPE_SZARRAY: {
1198                 MonoArray array;
1199
1200                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
1201                 WRITE_UINT32 (ptr, sizeof (MonoArray));
1202                 WRITE_UINT32 (ptr, MONO_DEBUGGER_TYPE_ARRAY);
1203                 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
1204                 *ptr++ = sizeof (array.max_length);
1205                 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
1206                 WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
1207                 break;
1208         }
1209
1210         case MONO_TYPE_ARRAY: {
1211                 MonoArray array;
1212                 MonoArrayBounds bounds;
1213
1214                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
1215                 WRITE_UINT32 (ptr, sizeof (MonoArray));
1216                 WRITE_UINT32 (ptr, MONO_DEBUGGER_TYPE_ARRAY);
1217                 *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
1218                 *ptr++ = sizeof (array.max_length);
1219                 *ptr++ = (guint8*)&array.vector - (guint8*)&array;
1220                 *ptr++ = klass->rank;
1221                 *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
1222                 *ptr++ = sizeof (MonoArrayBounds);
1223                 *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
1224                 *ptr++ = sizeof (bounds.lower_bound);
1225                 *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
1226                 *ptr++ = sizeof (bounds.length);
1227                 WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
1228                 break;
1229         }
1230
1231         case MONO_TYPE_VALUETYPE:
1232         case MONO_TYPE_CLASS:
1233         case MONO_TYPE_GENERICINST:
1234         case MONO_TYPE_OBJECT:
1235                 return write_class (table, klass);
1236
1237         case MONO_TYPE_PTR:
1238                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
1239                 WRITE_UINT32 (ptr, sizeof (gpointer));
1240                 WRITE_UINT32 (ptr, write_type (table, type->data.type));
1241                 break;
1242
1243         default:
1244                 /* g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type); */
1245                 *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
1246                 WRITE_UINT32 (ptr, klass->instance_size);
1247                 WRITE_UINT32 (ptr, write_class (table, klass));
1248                 break;
1249         }
1250
1251         size = ptr - buffer;
1252         offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
1253         memcpy (ptr, buffer, size);
1254
1255         return offset;
1256 }
1257
1258 MonoReflectionMethod *
1259 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
1260 {
1261         MonoMethod *method;
1262
1263         method = mono_get_method (mono_assembly_get_image (assembly->assembly), token, NULL);
1264
1265         return mono_method_get_object (mono_domain_get (), method, NULL);
1266 }
1267
1268 int
1269 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
1270 {
1271         return method->method->token;
1272 }
1273
1274 MonoReflectionType *
1275 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
1276 {
1277         MonoClass *klass;
1278
1279         klass = mono_class_get (mono_assembly_get_image (assembly->assembly), token);
1280         if (!klass) {
1281                 g_warning (G_STRLOC ": %x", token);
1282                 return NULL;
1283         }
1284
1285         return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
1286 }
1287
1288 MonoReflectionType *
1289 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
1290 {
1291         MonoDomain *domain; 
1292         MonoImage *image;
1293         MonoType *type;
1294         const char *ptr;
1295         int len = 0;
1296
1297         MONO_CHECK_ARG_NULL (assembly);
1298         MONO_CHECK_ARG_NULL (signature);
1299
1300         domain = mono_domain_get();
1301         image = mono_assembly_get_image (assembly->assembly);
1302
1303         ptr = mono_array_addr (signature, char, 0);
1304         g_assert (*ptr++ == 0x07);
1305         len = mono_metadata_decode_value (ptr, &ptr);
1306         g_assert (len == 1);
1307
1308         type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
1309
1310         return mono_type_get_object (domain, type);
1311 }
1312
1313 void
1314 mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
1315 {
1316         if (mono_debugger_event_handler)
1317                 (* mono_debugger_event_handler) (event, data, arg);
1318 }
1319
1320 void
1321 mono_debugger_cleanup (void)
1322 {
1323         /* Do nothing yet. */
1324 }
1325
1326 /*
1327  * Debugger breakpoint interface.
1328  *
1329  * This interface is used to insert breakpoints on methods which are not yet JITed.
1330  * The debugging code keeps a list of all such breakpoints and automatically inserts the
1331  * breakpoint when the method is JITed.
1332  */
1333
1334 static GPtrArray *breakpoints = NULL;
1335
1336 int
1337 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
1338 {
1339         static int last_breakpoint_id = 0;
1340         MonoDebuggerBreakpointInfo *info;
1341
1342         info = g_new0 (MonoDebuggerBreakpointInfo, 1);
1343         info->desc = desc;
1344         info->index = ++last_breakpoint_id;
1345
1346         if (!breakpoints)
1347                 breakpoints = g_ptr_array_new ();
1348
1349         g_ptr_array_add (breakpoints, info);
1350
1351         return info->index;
1352 }
1353
1354 int
1355 mono_debugger_remove_breakpoint (int breakpoint_id)
1356 {
1357         int i;
1358
1359         if (!breakpoints)
1360                 return 0;
1361
1362         for (i = 0; i < breakpoints->len; i++) {
1363                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1364
1365                 if (info->index != breakpoint_id)
1366                         continue;
1367
1368                 mono_method_desc_free (info->desc);
1369                 g_ptr_array_remove (breakpoints, info);
1370                 g_free (info);
1371                 return 1;
1372         }
1373
1374         return 0;
1375 }
1376
1377 int
1378 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
1379 {
1380         MonoMethodDesc *desc;
1381
1382         desc = mono_method_desc_new (method_name, include_namespace);
1383         if (!desc)
1384                 return 0;
1385
1386         return mono_debugger_insert_breakpoint_full (desc);
1387 }
1388
1389 int
1390 mono_debugger_method_has_breakpoint (MonoMethod *method)
1391 {
1392         int i;
1393
1394         if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
1395                 return 0;
1396
1397         for (i = 0; i < breakpoints->len; i++) {
1398                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
1399
1400                 if (!mono_method_desc_full_match (info->desc, method))
1401                         continue;
1402
1403                 return info->index;
1404         }
1405
1406         return 0;
1407 }
1408
1409 void
1410 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
1411 {
1412         mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
1413 }
1414
1415 gboolean
1416 mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
1417 {
1418         if (!mono_debugger_initialized)
1419                 return FALSE;
1420
1421         // Prevent the object from being finalized.
1422         last_exception = exc;
1423         mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION, exc, addr);
1424         return TRUE;
1425 }
1426
1427 void
1428 mono_debugger_handle_exception (gpointer addr, gpointer stack, MonoObject *exc)
1429 {
1430         MonoDebuggerExceptionInfo info;
1431
1432         if (!mono_debugger_initialized)
1433                 return;
1434
1435         // Prevent the object from being finalized.
1436         last_exception = exc;
1437
1438         info.stack_pointer = stack;
1439         info.exception_obj = exc;
1440         info.stop = 0;
1441
1442         mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION, &info, addr);
1443 }
1444
1445 gboolean
1446 mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
1447 {
1448         MonoDebuggerExceptionInfo info;
1449
1450         if (!mono_debugger_initialized)
1451                 return FALSE;
1452
1453         // Prevent the object from being finalized.
1454         last_exception = exc;
1455
1456         info.stack_pointer = stack;
1457         info.exception_obj = exc;
1458         info.stop = 0;
1459
1460         mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, &info, addr);
1461         return info.stop != 0;
1462 }
1463
1464 static gchar *
1465 get_exception_message (MonoObject *exc)
1466 {
1467         char *message = NULL;
1468         MonoString *str; 
1469         MonoMethod *method;
1470         MonoClass *klass;
1471         gint i;
1472
1473         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1474                 klass = exc->vtable->klass;
1475                 method = NULL;
1476                 while (klass && method == NULL) {
1477                         for (i = 0; i < klass->method.count; ++i) {
1478                                 method = klass->methods [i];
1479                                 if (!strcmp ("ToString", method->name) &&
1480                                     method->signature->param_count == 0 &&
1481                                     method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1482                                     method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1483                                         break;
1484                                 }
1485                                 method = NULL;
1486                         }
1487                         
1488                         if (method == NULL)
1489                                 klass = klass->parent;
1490                 }
1491
1492                 g_assert (method);
1493
1494                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1495                 if (str)
1496                         message = mono_string_to_utf8 (str);
1497         }
1498
1499         return message;
1500 }
1501
1502 MonoObject *
1503 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1504 {
1505         MonoObject *retval;
1506         gchar *message;
1507
1508         if (!strcmp (method->name, ".ctor")) {
1509                 retval = obj = mono_object_new (mono_domain_get (), method->klass);
1510
1511                 mono_runtime_invoke (method, obj, params, exc);
1512         } else
1513                 retval = mono_runtime_invoke (method, obj, params, exc);
1514
1515         if (!exc || (*exc == NULL))
1516                 return retval;
1517
1518         message = get_exception_message (*exc);
1519         if (message) {
1520                 *exc = (MonoObject *) mono_string_new_wrapper (message);
1521                 g_free (message);
1522         }
1523
1524         return retval;
1525 }
1526
1527 guint32
1528 mono_debugger_lookup_type (const gchar *type_name)
1529 {
1530         int i;
1531
1532         mono_debugger_lock ();
1533
1534         for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1535                 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1536                 MonoType *type;
1537                 guint32 offset;
1538                 gchar *name;
1539
1540                 name = g_strdup (type_name);
1541                 type = mono_reflection_type_from_name (name, symfile->image);
1542                 g_free (name);
1543                 if (!type)
1544                         continue;
1545
1546                 offset = write_type (mono_debugger_symbol_table, type);
1547
1548                 mono_debugger_unlock ();
1549                 return offset;
1550         }
1551
1552         mono_debugger_unlock ();
1553         return 0;
1554 }
1555
1556 gint32
1557 mono_debugger_lookup_assembly (const gchar *name)
1558 {
1559         MonoAssembly *assembly;
1560         MonoImageOpenStatus status;
1561         int i;
1562
1563         mono_debugger_lock ();
1564
1565  again:
1566         for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
1567                 MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
1568
1569                 if (!strcmp (symfile->image_file, name)) {
1570                         mono_debugger_unlock ();
1571                         return i;
1572                 }
1573         }
1574
1575         assembly = mono_assembly_open (name, &status);
1576
1577         if (status != MONO_IMAGE_OK) {
1578                 g_warning (G_STRLOC ": Cannot open image `%s'", name);
1579                 mono_debugger_unlock ();
1580                 return -1;
1581         }
1582
1583         must_reload_symtabs = TRUE;
1584         goto again;
1585 }
1586
1587 void
1588 mono_debugger_add_wrapper (MonoMethod *wrapper, MonoDebugMethodJitInfo *jit, gpointer addr)
1589 {
1590         guint32 size, offset;
1591         guint8 *ptr;
1592
1593         if (!mono_debugger_symbol_table)
1594                 return;
1595
1596         size = strlen (wrapper->name) + 5 + 5 * sizeof (gpointer);
1597
1598         offset = allocate_misc_entry (mono_debugger_symbol_table, size, &ptr);
1599
1600         WRITE_UINT32 (ptr, MONO_DEBUGGER_MISC_ENTRY_TYPE_WRAPPER);
1601         WRITE_STRING (ptr, wrapper->name);
1602         WRITE_POINTER (ptr, jit->code_start);
1603         WRITE_POINTER (ptr, jit->code_start + jit->code_size);
1604         WRITE_POINTER (ptr, addr);
1605         WRITE_POINTER (ptr, jit->code_start + jit->prologue_end);
1606         WRITE_POINTER (ptr, jit->code_start + jit->epilogue_begin);
1607 }