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