* culture-info.h: Make defines more consistent, add calendar data
[mono.git] / mono / metadata / mono-debug-debugger.c
index 3d16b151d2d86beac4991f5507903ca823c0acdd..f8f6a8f433941f20a97fea576498c6f37255c092 100644 (file)
@@ -8,6 +8,7 @@
 #include <mono/metadata/exception.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/mono-endian.h>
 
 #define SYMFILE_TABLE_CHUNK_SIZE       16
 #define RANGE_TABLE_CHUNK_SIZE         256
 #define TYPE_TABLE_PTR_CHUNK_SIZE      256
 #define TYPE_TABLE_CHUNK_SIZE          65536
 
+static guint32 debugger_lock_level = 0;
 static CRITICAL_SECTION debugger_lock_mutex;
 static gboolean mono_debugger_initialized = FALSE;
 
+static gboolean must_reload_symtabs = FALSE;
+
+static GHashTable *images = NULL;
 static GHashTable *type_table = NULL;
 static GHashTable *class_table = NULL;
+static GHashTable *class_info_table = NULL;
 
 static MonoDebuggerRangeInfo *allocate_range_entry (MonoDebuggerSymbolFile *symfile);
 static MonoDebuggerClassInfo *allocate_class_entry (MonoDebuggerSymbolFile *symfile);
 static guint32 allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr);
 static guint32 write_type (MonoDebuggerSymbolTable *table, MonoType *type);
+static guint32 write_class (MonoDebuggerSymbolTable *table, MonoClass *klass);
 
 MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
 
+#define WRITE_UINT32(ptr,value) G_STMT_START { \
+       * ((guint32 *) ptr) = value;            \
+       ptr += 4;                               \
+} G_STMT_END
+
+#define WRITE_POINTER(ptr,value) G_STMT_START {        \
+       * ((gpointer *) ptr) = value;           \
+       ptr += sizeof (gpointer);               \
+} G_STMT_END
+
 #ifndef PLATFORM_WIN32
 
 MonoDebuggerIOLayer mono_debugger_io_layer = {
        InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
        EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
-       WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
+       WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread,
+       GetCurrentThreadId
 };
 
 #endif
@@ -42,15 +60,34 @@ MonoDebuggerIOLayer mono_debugger_io_layer = {
 void
 mono_debugger_lock (void)
 {
-       if (mono_debugger_initialized)
-               EnterCriticalSection (&debugger_lock_mutex);
+       if (!mono_debugger_initialized) {
+               debugger_lock_level++;
+               return;
+       }
+
+       EnterCriticalSection (&debugger_lock_mutex);
+       debugger_lock_level++;
 }
 
 void
 mono_debugger_unlock (void)
 {
-       if (mono_debugger_initialized)
-               LeaveCriticalSection (&debugger_lock_mutex);
+       g_assert (debugger_lock_level > 0);
+
+       if (!mono_debugger_initialized) {
+               debugger_lock_level--;
+               return;
+       }
+
+       if (debugger_lock_level == 1) {
+               if (must_reload_symtabs) {
+                       mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, NULL, 0);
+                       must_reload_symtabs = FALSE;
+               }
+       }
+
+       debugger_lock_level--;
+       LeaveCriticalSection (&debugger_lock_mutex);
 }
 
 static MonoDebuggerSymbolFile *
@@ -68,85 +105,272 @@ allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
        }
 
        symfile = g_new0 (MonoDebuggerSymbolFile, 1);
+       symfile->index = table->num_symbol_files;
+       symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
+       symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
        table->symbol_files [table->num_symbol_files++] = symfile;
        return symfile;
 }
 
 void
-mono_debugger_initialize (void)
+mono_debugger_initialize (MonoDomain *domain)
 {
        MonoDebuggerSymbolTable *symbol_table;
 
        g_assert (!mono_debugger_initialized);
 
        InitializeCriticalSection (&debugger_lock_mutex);
+       mono_debugger_initialized = TRUE;
 
        mono_debugger_lock ();
 
        symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
-       symbol_table->magic = MONO_SYMBOL_FILE_DYNAMIC_MAGIC;
-       symbol_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
+       symbol_table->magic = MONO_DEBUGGER_MAGIC;
+       symbol_table->version = MONO_DEBUGGER_VERSION;
        symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
 
+       symbol_table->domain = domain;
+
+       images = g_hash_table_new (g_direct_hash, g_direct_equal);
+       type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+       class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+       class_info_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+
        mono_debugger_symbol_table = symbol_table;
-       mono_debugger_initialized = TRUE;
 
        mono_debugger_unlock ();
 }
 
 MonoDebuggerSymbolFile *
-mono_debugger_add_symbol_file (MonoSymbolFile *symfile)
+mono_debugger_add_symbol_file (MonoDebugHandle *handle)
 {
        MonoDebuggerSymbolFile *info;
 
        g_assert (mono_debugger_initialized);
+       mono_debugger_lock ();
+
+       info = g_hash_table_lookup (images, handle->image);
+       if (info) {
+               mono_debugger_unlock ();
+               return info;
+       }
 
        info = allocate_symbol_file_entry (mono_debugger_symbol_table);
-       info->symfile = symfile;
-       info->image_file = symfile->image_file;
+       info->symfile = handle->symfile;
+       info->image = handle->image;
+       info->image_file = handle->image_file;
+
+       g_hash_table_insert (images, handle->image, info);
+       mono_debugger_unlock ();
+
+       return info;
+}
+
+static void
+write_builtin_type (MonoDebuggerSymbolTable *table, MonoClass *klass, MonoDebuggerBuiltinTypeInfo *info)
+{
+       guint8 buffer [BUFSIZ], *ptr = buffer;
+       guint32 size;
+
+       g_assert (!klass->init_pending);
+       mono_class_init (klass);
+
+       switch (klass->byval_arg.type) {
+       case MONO_TYPE_VOID:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
+               WRITE_UINT32 (ptr, 0);
+               ptr += 4;
+               break;
+
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_CHAR:
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+       case MONO_TYPE_R4:
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_R8:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
+               WRITE_UINT32 (ptr, klass->instance_size - sizeof (MonoObject));
+               ptr += 4;
+               break;
+
+       case MONO_TYPE_STRING: {
+               MonoString string;
+
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               ptr += 4;
+               *ptr++ = (guint8*)&string.length - (guint8*)&string;
+               *ptr++ = sizeof (string.length);
+               *ptr++ = (guint8*)&string.chars - (guint8*)&string;
+
+               break;
+       }
+
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
+               WRITE_UINT32 (ptr, sizeof (void *));
+               ptr += 4;
+               break;
+
+       case MONO_TYPE_VALUETYPE:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               ptr += 4;
+               break;
 
-       mono_debugger_add_type (info, mono_defaults.object_class);
+       case MONO_TYPE_CLASS:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               ptr += 4;
+               break;
+
+       case MONO_TYPE_OBJECT:
+               g_assert (klass == mono_defaults.object_class);
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               ptr += 4;
+               break;
+
+       default:
+               g_error (G_STRLOC ": Unknown builtin type %s.%s - %d", klass->name_space, klass->name, klass->byval_arg.type);
+       }
+
+       size = ptr - buffer;
+       info->cinfo->type_info = info->type_info = allocate_type_entry (table, size, &info->type_data);
+       memcpy (info->type_data, buffer, size);
+}
+
+static MonoDebuggerBuiltinTypeInfo *
+add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
+{
+       MonoDebuggerClassInfo *cinfo;
+       MonoDebuggerBuiltinTypeInfo *info;
 
+       cinfo = g_new0 (MonoDebuggerClassInfo, 1);
+       cinfo->klass = klass;
+       if (klass->rank) {
+               cinfo->token = klass->element_class->type_token;
+               cinfo->rank = klass->rank;
+       } else
+               cinfo->token = klass->type_token;
+
+       g_hash_table_insert (class_info_table, klass, cinfo);
+
+       info = g_new0 (MonoDebuggerBuiltinTypeInfo, 1);
+       info->klass = klass;
+       info->cinfo = cinfo;
+
+       write_builtin_type (mono_debugger_symbol_table, klass, info);
        return info;
 }
 
+static void
+add_builtin_type_2 (MonoDebuggerBuiltinTypeInfo *info)
+{
+       info->class_info = write_class (mono_debugger_symbol_table, info->klass);
+       * (guint32 *) (info->type_data + 5) = info->class_info;
+}
+
+MonoDebuggerBuiltinTypes *
+mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
+{
+       MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
+
+       mono_debugger_symbol_table->corlib = symfile;
+       mono_debugger_symbol_table->builtin_types = types;
+
+       types->total_size = sizeof (MonoDebuggerBuiltinTypes);
+       types->type_info_size = sizeof (MonoDebuggerBuiltinTypeInfo);
+
+       types->object_type = add_builtin_type (symfile, mono_defaults.object_class);
+       types->byte_type = add_builtin_type (symfile, mono_defaults.byte_class);
+       types->void_type = add_builtin_type (symfile, mono_defaults.void_class);
+       types->boolean_type = add_builtin_type (symfile, mono_defaults.boolean_class);
+       types->sbyte_type = add_builtin_type (symfile, mono_defaults.sbyte_class);
+       types->int16_type = add_builtin_type (symfile, mono_defaults.int16_class);
+       types->uint16_type = add_builtin_type (symfile, mono_defaults.uint16_class);
+       types->int32_type = add_builtin_type (symfile, mono_defaults.int32_class);
+       types->uint32_type = add_builtin_type (symfile, mono_defaults.uint32_class);
+       types->int_type = add_builtin_type (symfile, mono_defaults.int_class);
+       types->uint_type = add_builtin_type (symfile, mono_defaults.uint_class);
+       types->int64_type = add_builtin_type (symfile, mono_defaults.int64_class);
+       types->uint64_type = add_builtin_type (symfile, mono_defaults.uint64_class);
+       types->single_type = add_builtin_type (symfile, mono_defaults.single_class);
+       types->double_type = add_builtin_type (symfile, mono_defaults.double_class);
+       types->char_type = add_builtin_type (symfile, mono_defaults.char_class);
+       types->string_type = add_builtin_type (symfile, mono_defaults.string_class);
+
+       types->enum_type = add_builtin_type (symfile, mono_defaults.enum_class);
+       types->array_type = add_builtin_type (symfile, mono_defaults.array_class);
+       types->exception_type = add_builtin_type (symfile, mono_defaults.exception_class);
+
+       add_builtin_type_2 (types->object_type);
+       add_builtin_type_2 (types->byte_type);
+       add_builtin_type_2 (types->void_type);
+       add_builtin_type_2 (types->boolean_type);
+       add_builtin_type_2 (types->sbyte_type);
+       add_builtin_type_2 (types->int16_type);
+       add_builtin_type_2 (types->uint16_type);
+       add_builtin_type_2 (types->int32_type);
+       add_builtin_type_2 (types->uint32_type);
+       add_builtin_type_2 (types->int_type);
+       add_builtin_type_2 (types->uint_type);
+       add_builtin_type_2 (types->int64_type);
+       add_builtin_type_2 (types->uint64_type);
+       add_builtin_type_2 (types->single_type);
+       add_builtin_type_2 (types->double_type);
+       add_builtin_type_2 (types->char_type);
+       add_builtin_type_2 (types->string_type);
+       add_builtin_type_2 (types->enum_type);
+       add_builtin_type_2 (types->array_type);
+       add_builtin_type_2 (types->exception_type);
+
+       return types;
+}
+
 void
 mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
 {
-       MonoDebuggerClassInfo *info;
+       MonoDebuggerClassInfo *cinfo;
 
        mono_debugger_lock ();
 
-       if (!class_table)
-               class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-       /* We write typeof (object) into each symbol file's type table. */
-       if ((klass != mono_defaults.object_class) && g_hash_table_lookup (class_table, klass)) {
+       cinfo = g_hash_table_lookup (class_info_table, klass);
+       if (cinfo) {
                mono_debugger_unlock ();
                return;
        }
 
        symfile->generation++;
 
-       info = allocate_class_entry (symfile);
-       info->klass = klass;
+       cinfo = allocate_class_entry (symfile);
+       cinfo->klass = klass;
        if (klass->rank) {
-               info->token = klass->element_class->type_token;
-               info->rank = klass->rank;
+               cinfo->token = klass->element_class->type_token;
+               cinfo->rank = klass->rank;
        } else
-               info->token = klass->type_token;
-       info->type_info = write_type (mono_debugger_symbol_table, &klass->this_arg);
+               cinfo->token = klass->type_token;
+       g_hash_table_insert (class_info_table, klass, cinfo);
 
-       mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, NULL, 0);
+       cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
+
+       must_reload_symtabs = TRUE;
        mono_debugger_unlock ();
 }
 
 void
-mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
+mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
+                         MonoDebugMethodJitInfo *jit)
 {
        MonoSymbolFileMethodAddress *address;
        MonoSymbolFileLexicalBlockEntry *block;
-       MonoDebugMethodInfo *minfo;
        MonoDebugVarInfo *var_table;
        MonoDebuggerRangeInfo *range;
        MonoMethodHeader *header;
@@ -162,18 +386,14 @@ mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
        if (!symfile->symfile->method_hash)
                return;
 
-       header = ((MonoMethodNormal *) method)->header;
-
-       minfo = g_hash_table_lookup (symfile->symfile->method_hash, method);
-       if (!minfo || !minfo->jit)
-               return;
+       header = ((MonoMethodNormal *) minfo->method)->header;
 
        symfile->generation++;
 
        size = sizeof (MonoSymbolFileMethodAddress);
 
-       num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
-       has_this = minfo->jit->this_var != NULL;
+       num_variables = read32(&(minfo->entry->_num_parameters)) + read32(&(minfo->entry->_num_locals));
+       has_this = jit->this_var != NULL;
 
        variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
        variable_offset = size;
@@ -183,13 +403,13 @@ mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
        type_offset = size;
        size += type_size;
 
-       if (minfo->jit->line_numbers) {
+       if (jit->line_numbers) {
                line_offset = size;
-               line_size = minfo->jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
+               line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
                size += line_size;
        }
 
-       block_size = minfo->entry->num_lexical_blocks * sizeof (MonoSymbolFileLexicalBlockEntry);
+       block_size = read32(&(minfo->entry->_num_lexical_blocks)) * sizeof (MonoSymbolFileLexicalBlockEntry);
        block_offset = size;
        size += block_size;
 
@@ -197,31 +417,31 @@ mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
        ptr = (guint8 *) address;
 
        block = (MonoSymbolFileLexicalBlockEntry *)
-               (symfile->symfile->raw_contents + minfo->entry->lexical_block_table_offset);
+               (symfile->symfile->raw_contents + read32(&(minfo->entry->_lexical_block_table_offset)));
        block_table = (MonoDebugLexicalBlockEntry *) (ptr + block_offset);
 
-       for (i = 0; i < minfo->entry->num_lexical_blocks; i++, block++) {
-               block_table [i].start_address = _mono_debug_address_from_il_offset (minfo, block->start_offset);
-               block_table [i].end_address = _mono_debug_address_from_il_offset (minfo, block->end_offset);
+       for (i = 0; i < read32(&(minfo->entry->_num_lexical_blocks)); i++, block++) {
+               block_table [i].start_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_start_offset)));
+               block_table [i].end_address = _mono_debug_address_from_il_offset (jit, read32(&(block->_end_offset)));
        }
 
        address->size = size;
        address->has_this = has_this;
-       address->start_address = minfo->jit->code_start;
-       address->end_address = minfo->jit->code_start + minfo->jit->code_size;
-       address->method_start_address = address->start_address + minfo->jit->prologue_end;
-       address->method_end_address = address->start_address + minfo->jit->epilogue_begin;
-       address->wrapper_address = minfo->jit->wrapper_addr;
+       address->start_address = jit->code_start;
+       address->end_address = jit->code_start + jit->code_size;
+       address->method_start_address = address->start_address + jit->prologue_end;
+       address->method_end_address = address->start_address + jit->epilogue_begin;
+       address->wrapper_address = jit->wrapper_addr;
        address->variable_table_offset = variable_offset;
        address->type_table_offset = type_offset;
        address->lexical_block_table_offset = block_offset;
 
-       if (minfo->jit->line_numbers) {
-               address->num_line_numbers = minfo->jit->line_numbers->len;
+       if (jit->line_numbers) {
+               address->num_line_numbers = jit->line_numbers->len;
                address->line_number_offset = line_offset;
 
                line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
-               memcpy (line_table, minfo->jit->line_numbers->data, line_size);
+               memcpy (line_table, jit->line_numbers->data, line_size);
        }
 
        range = allocate_range_entry (symfile);
@@ -231,48 +451,47 @@ mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
        range->dynamic_data = address;
        range->dynamic_size = size;
 
-       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
-           (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
-           (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+       if ((minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+           (minfo->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
+           (minfo->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                return;
 
        var_table = (MonoDebugVarInfo *) (ptr + variable_offset);
        type_table = (guint32 *) (ptr + type_offset);
 
        type_index_table = (guint32 *)
-               (symfile->symfile->raw_contents + minfo->entry->type_index_table_offset);
+               (symfile->symfile->raw_contents + read32(&(minfo->entry->_type_index_table_offset)));
 
-       if (minfo->jit->this_var)
-               *var_table++ = *minfo->jit->this_var;
-       *type_table++ = write_type (mono_debugger_symbol_table, &method->klass->this_arg);
+       if (jit->this_var)
+               *var_table++ = *jit->this_var;
+       *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
 
-       if (minfo->jit->num_params != minfo->entry->num_parameters) {
+       if (jit->num_params != read32(&(minfo->entry->_num_parameters))) {
                g_warning (G_STRLOC ": Method %s.%s has %d parameters, but symbol file claims it has %d.",
-                          minfo->method->klass->name, minfo->method->name, minfo->jit->num_params,
-                          minfo->entry->num_parameters);
-               G_BREAKPOINT ();
-               var_table += minfo->entry->num_parameters;
+                          minfo->method->klass->name, minfo->method->name, jit->num_params,
+                          read32(&(minfo->entry->_num_parameters)));
+               var_table += read32(&(minfo->entry->_num_parameters));
        } else {
-               for (i = 0; i < minfo->jit->num_params; i++) {
-                       *var_table++ = minfo->jit->params [i];
-                       *type_table++ = write_type (mono_debugger_symbol_table, method->signature->params [i]);
+               for (i = 0; i < jit->num_params; i++) {
+                       *var_table++ = jit->params [i];
+                       *type_table++ = write_type (mono_debugger_symbol_table, minfo->method->signature->params [i]);
                }
        }
 
-       if (minfo->jit->num_locals < minfo->entry->num_locals) {
+       if (jit->num_locals < read32(&(minfo->entry->_num_locals))) {
                g_warning (G_STRLOC ": Method %s.%s has %d locals, but symbol file claims it has %d.",
-                          minfo->method->klass->name, minfo->method->name, minfo->jit->num_locals,
-                          minfo->entry->num_locals);
-               var_table += minfo->entry->num_locals;
+                          minfo->method->klass->name, minfo->method->name, jit->num_locals,
+                          read32(&(minfo->entry->_num_locals)));
+               var_table += read32(&(minfo->entry->_num_locals));
        } else {
-               g_assert ((header != NULL) || (minfo->entry->num_locals == 0));
-               for (i = 0; i < minfo->entry->num_locals; i++) {
-                       *var_table++ = minfo->jit->locals [i];
+               g_assert ((header != NULL) || (minfo->entry->_num_locals == 0));
+               for (i = 0; i < read32(&(minfo->entry->_num_locals)); i++) {
+                       *var_table++ = jit->locals [i];
                        *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
                }
        }
 
-       mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, NULL, 0);
+       must_reload_symtabs = TRUE;
 }
 
 static MonoDebuggerRangeInfo *
@@ -281,8 +500,6 @@ allocate_range_entry (MonoDebuggerSymbolFile *symfile)
        MonoDebuggerRangeInfo *retval;
        guint32 size, chunks;
 
-       symfile->range_entry_size = sizeof (MonoDebuggerRangeInfo);
-
        if (!symfile->range_table) {
                size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE;
                symfile->range_table = g_malloc0 (size);
@@ -308,8 +525,6 @@ allocate_class_entry (MonoDebuggerSymbolFile *symfile)
        MonoDebuggerClassInfo *retval;
        guint32 size, chunks;
 
-       symfile->class_entry_size = sizeof (MonoDebuggerClassInfo);
-
        if (!symfile->class_table) {
                size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE;
                symfile->class_table = g_malloc0 (size);
@@ -357,7 +572,8 @@ allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
                retval = table->type_table_offset;
                table->type_table_offset += size + 4;
                data = ((guint8 *) table->current_type_table) + retval - table->type_table_start;
-               *((gint32 *) data)++ = size;
+               *(gint32 *) data = size;
+               data += sizeof(gint32);
                *ptr = data;
                return retval;
        }
@@ -385,74 +601,233 @@ allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
        goto again;
 }
 
+static gboolean
+property_is_static (MonoProperty *prop)
+{
+       MonoMethod *method;
+
+       method = prop->get;
+       if (!method)
+               method = prop->set;
+
+       return method->flags & METHOD_ATTRIBUTE_STATIC;
+}
+
 static guint32
-write_simple_type (MonoDebuggerSymbolTable *table, MonoType *type)
+write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
 {
-       guint8 buffer [BUFSIZ], *ptr = buffer;
-       guint32 size, offset;
+       guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
+       GPtrArray *methods = NULL, *static_methods = NULL, *ctors = NULL;
+       int num_fields = 0, num_static_fields = 0, num_properties = 0, num_static_properties = 0;
+       int num_methods = 0, num_static_methods = 0, num_params = 0, num_static_params = 0, base_offset = 0;
+       int num_ctors = 0, num_ctor_params = 0;
+       guint32 size, data_size, offset;
+       GHashTable *method_slots = NULL;
+       int i;
 
-       if (!type_table)
-               type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+       g_assert (!klass->init_pending);
+       mono_class_init (klass);
 
-       offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
+       offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
        if (offset)
                return offset;
 
-       switch (type->type) {
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-               *((gint32 *) ptr)++ = 1;
-               break;
+       if (klass->enumtype) {
+               offset = allocate_type_entry (table, 13, &ptr);
+               g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
 
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-               *((gint32 *) ptr)++ = 2;
-               break;
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               WRITE_UINT32 (ptr, table->builtin_types->enum_type->type_info);
+               WRITE_UINT32 (ptr, write_type (table, klass->enum_basetype));
+               return offset;
+       }
 
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-       case MONO_TYPE_R4:
-               *((gint32 *) ptr)++ = 4;
-               break;
+       for (i = 0; i < klass->field.count; i++)
+               if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+                       ++num_fields;
+               else
+                       ++num_static_fields;
 
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-       case MONO_TYPE_R8:
-               *((gint32 *) ptr)++ = 8;
-               break;
+       for (i = 0; i < klass->property.count; i++)
+               if (!property_is_static (&klass->properties [i]))
+                       ++num_properties;
+               else
+                       ++num_static_properties;
 
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-               *((gint32 *) ptr)++ = sizeof (void *);
-               break;
+       method_slots = g_hash_table_new (NULL, NULL);
+       methods = g_ptr_array_new ();
+       static_methods = g_ptr_array_new ();
+       ctors = g_ptr_array_new ();
 
-       case MONO_TYPE_VOID:
-               *((gint32 *) ptr)++ = 0;
-               break;
+       for (i = 0; i < klass->method.count; i++) {
+               MonoMethod *method = klass->methods [i];
 
-       case MONO_TYPE_STRING: {
-               MonoString string;
+               if (!strcmp (method->name, ".cctor"))
+                       continue;
+               if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
+                       continue;
 
-               *((gint32 *) ptr)++ = -8;
-               *((guint32 *) ptr)++ = sizeof (MonoString);
-               *ptr++ = 1;
-               *ptr++ = (guint8*)&string.length - (guint8*)&string;
-               *ptr++ = sizeof (string.length);
-               *ptr++ = (guint8*)&string.chars - (guint8*)&string;
-               break;
+               if (!strcmp (method->name, ".ctor")) {
+                       ++num_ctors;
+                       num_ctor_params += method->signature->param_count;
+                       g_ptr_array_add (ctors, method);
+                       continue;
+               }
+
+               if (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME)
+                       continue;
+               
+               if (method->slot != -1) {
+                       if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
+                               continue;
+                       g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
+               }
+
+               if (method->flags & METHOD_ATTRIBUTE_STATIC) {
+                       ++num_static_methods;
+                       num_static_params += method->signature->param_count;
+                       g_ptr_array_add (static_methods, method);
+               } else {
+                       ++num_methods;
+                       num_params += method->signature->param_count;
+                       g_ptr_array_add (methods, method);
+               }
        }
 
-       default:
-               return 0;
+       g_hash_table_destroy (method_slots);
+
+       size = 66 + sizeof (gpointer) + num_fields * 8 + num_static_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
+               num_static_properties * (4 + 2 * sizeof (gpointer)) + num_methods * (8 + sizeof (gpointer)) + num_params * 4 +
+               num_static_methods * (8 + sizeof (gpointer)) + num_static_params * 4 + num_ctors * (8 + sizeof (gpointer)) +
+               num_ctor_params * 4;
+
+       data_size = size;
+
+       offset = allocate_type_entry (table, data_size, &ptr);
+       old_ptr = ptr;
+
+       g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
+
+       *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS_INFO;
+
+       if (klass->valuetype)
+               base_offset = - sizeof (MonoObject);
+
+       WRITE_UINT32 (ptr, klass->instance_size + base_offset);
+       *ptr++ = klass->valuetype;
+       WRITE_POINTER (ptr, klass);
+       WRITE_UINT32 (ptr, num_fields);
+       WRITE_UINT32 (ptr, num_fields * 8);
+       WRITE_UINT32 (ptr, num_static_fields);
+       WRITE_UINT32 (ptr, num_static_fields * 8);
+       WRITE_UINT32 (ptr, num_properties);
+       WRITE_UINT32 (ptr, num_properties * (4 + 2 * sizeof (gpointer)));
+       WRITE_UINT32 (ptr, num_static_properties);
+       WRITE_UINT32 (ptr, num_static_properties * (4 + 2 * sizeof (gpointer)));
+       WRITE_UINT32 (ptr, num_methods);
+       WRITE_UINT32 (ptr, num_methods * (4 + 2 * sizeof (gpointer)) + num_params * sizeof (gpointer));
+       WRITE_UINT32 (ptr, num_static_methods);
+       WRITE_UINT32 (ptr, num_static_methods * (4 + 2 * sizeof (gpointer)) + num_static_params * sizeof (gpointer));
+       WRITE_UINT32 (ptr, num_ctors);
+       WRITE_UINT32 (ptr, num_ctors * (4 + 2 * sizeof (gpointer)) + num_ctor_params * sizeof (gpointer));
+
+       for (i = 0; i < klass->field.count; i++) {
+               if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+                       continue;
+
+               WRITE_UINT32 (ptr, klass->fields [i].offset + base_offset);
+               WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
        }
 
-       size = ptr - buffer;
-       offset = allocate_type_entry (table, size, &ptr);
-       memcpy (ptr, buffer, size);
+       for (i = 0; i < klass->property.count; i++) {
+               if (property_is_static (&klass->properties [i]))
+                       continue;
+
+               if (klass->properties [i].get)
+                       WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
+               else
+                       WRITE_UINT32 (ptr, 0);
+               WRITE_POINTER (ptr, klass->properties [i].get);
+               WRITE_POINTER (ptr, klass->properties [i].set);
+       }
 
-       g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
+       for (i = 0; i < methods->len; i++) {
+               MonoMethod *method = g_ptr_array_index (methods, i);
+               int j;
+
+               WRITE_POINTER (ptr, method);
+               if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
+                       WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
+               else
+                       WRITE_UINT32 (ptr, 0);
+               WRITE_UINT32 (ptr, method->signature->param_count);
+               for (j = 0; j < method->signature->param_count; j++)
+                       WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
+       }
+
+       g_ptr_array_free (methods, FALSE);
+
+       for (i = 0; i < klass->field.count; i++) {
+               if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+                       continue;
+
+               WRITE_UINT32 (ptr, klass->fields [i].offset);
+               WRITE_UINT32 (ptr, write_type (table, klass->fields [i].type));
+       }
+
+       for (i = 0; i < klass->property.count; i++) {
+               if (!property_is_static (&klass->properties [i]))
+                       continue;
+
+               if (klass->properties [i].get)
+                       WRITE_UINT32 (ptr, write_type (table, klass->properties [i].get->signature->ret));
+               else
+                       WRITE_UINT32 (ptr, 0);
+               WRITE_POINTER (ptr, klass->properties [i].get);
+               WRITE_POINTER (ptr, klass->properties [i].set);
+       }
+
+       for (i = 0; i < static_methods->len; i++) {
+               MonoMethod *method = g_ptr_array_index (static_methods, i);
+               int j;
+
+               WRITE_POINTER (ptr, method);
+               if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
+                       WRITE_UINT32 (ptr, write_type (table, method->signature->ret));
+               else
+                       WRITE_UINT32 (ptr, 0);
+               WRITE_UINT32 (ptr, method->signature->param_count);
+               for (j = 0; j < method->signature->param_count; j++)
+                       WRITE_UINT32 (ptr, write_type (table, method->signature->params [j]));
+       }
+
+       g_ptr_array_free (static_methods, FALSE);
+
+       for (i = 0; i < ctors->len; i++) {
+               MonoMethod *ctor = g_ptr_array_index (ctors, i);
+               int j;
+
+               WRITE_POINTER (ptr, ctor);
+               WRITE_UINT32 (ptr, 0);
+               WRITE_UINT32 (ptr, ctor->signature->param_count);
+               for (j = 0; j < ctor->signature->param_count; j++)
+                       WRITE_UINT32 (ptr, write_type (table, ctor->signature->params [j]));
+       }
+
+       g_ptr_array_free (ctors, FALSE);
+
+       if (klass->parent && (klass->parent != mono_defaults.object_class))
+               WRITE_UINT32 (ptr, write_class (table, klass->parent));
+       else
+               WRITE_UINT32 (ptr, 0);
+
+       if (ptr - old_ptr != data_size) {
+               g_warning (G_STRLOC ": %d,%d,%d", ptr - old_ptr, data_size, sizeof (gpointer));
+               if (klass)
+                       g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
+               g_assert_not_reached ();
+       }
 
        return offset;
 }
@@ -463,131 +838,79 @@ write_simple_type (MonoDebuggerSymbolTable *table, MonoType *type)
 static guint32
 write_type (MonoDebuggerSymbolTable *table, MonoType *type)
 {
-       guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
-       GPtrArray *methods = NULL;
-       int num_fields = 0, num_properties = 0, num_methods = 0;
-       int num_params = 0, kind;
-       guint32 size, data_size, offset;
-       MonoClass *klass = NULL;
-
-       if (!type_table)
-               type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
-       if (!class_table)
-               class_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+       guint8 buffer [BUFSIZ], *ptr = buffer;
+       guint32 size, offset;
+       MonoClass *klass;
 
        offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
        if (offset)
                return offset;
 
-       offset = write_simple_type (table, type);
-       if (offset)
-               return offset;
-
-       kind = type->type;
-       if (kind == MONO_TYPE_OBJECT) {
-               klass = mono_defaults.object_class;
-               kind = MONO_TYPE_CLASS;
-       } else if ((kind == MONO_TYPE_VALUETYPE) || (kind == MONO_TYPE_CLASS)) {
-               klass = type->data.klass;
-               offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
-               if (offset)
-                       return offset;
-       }
-
-       switch (kind) {
-       case MONO_TYPE_SZARRAY:
-               size = 16;
-               break;
-
-       case MONO_TYPE_ARRAY:
-               size = 23;
-               break;
-
-       case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS: {
-               GHashTable *method_slots = NULL;
-               int i;
-
-               if (klass->init_pending) {
-                       size = 4;
-                       break;
-               }
-
-               mono_class_init (klass);
-
-               offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
-               if (offset)
-                       return offset;
+       klass = mono_class_from_mono_type (type);
+       if (klass->init_pending)
+               return 0;
+       mono_class_init (klass);
 
-               if (klass->enumtype) {
-                       size = 13;
-                       break;
-               }
+       switch (type->type) {
+       case MONO_TYPE_VOID:
+               return table->builtin_types->void_type->type_info;
 
-               for (i = 0; i < klass->field.count; i++)
-                       if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
-                               ++num_fields;
+       case MONO_TYPE_BOOLEAN:
+               return table->builtin_types->boolean_type->type_info;
 
-               for (i = 0; i < klass->property.count; i++)
-                       if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
-                               ++num_properties;
+       case MONO_TYPE_I1:
+               return table->builtin_types->sbyte_type->type_info;
 
-               method_slots = g_hash_table_new (NULL, NULL);
-               methods = g_ptr_array_new ();
+       case MONO_TYPE_U1:
+               return table->builtin_types->byte_type->type_info;
 
-               for (i = klass->method.count - 1; i >= 0; i--) {
-                       MonoMethod *method = klass->methods [i];
+       case MONO_TYPE_CHAR:
+               return table->builtin_types->char_type->type_info;
 
-                       if (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)
-                               continue;
-                       if (method->flags & (METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_SPECIAL_NAME))
-                               continue;
-                       if (!((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))
-                               continue;
-                       if (g_hash_table_lookup (method_slots, GUINT_TO_POINTER (method->slot)))
-                               continue;
-                       g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
+       case MONO_TYPE_I2:
+               return table->builtin_types->int16_type->type_info;
 
-                       ++num_methods;
-                       num_params += method->signature->param_count;
+       case MONO_TYPE_U2:
+               return table->builtin_types->uint16_type->type_info;
 
-                       g_ptr_array_add (methods, method);
-               }
+       case MONO_TYPE_I4:
+               return table->builtin_types->int32_type->type_info;
 
-               g_hash_table_destroy (method_slots);
+       case MONO_TYPE_U4:
+               return table->builtin_types->uint32_type->type_info;
 
-               size = 34 + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
-                       num_methods * (8 + sizeof (gpointer)) + num_params * 4;
+       case MONO_TYPE_I8:
+               return table->builtin_types->int64_type->type_info;
 
-               if (kind == MONO_TYPE_CLASS)
-                       size += 4;
+       case MONO_TYPE_U8:
+               return table->builtin_types->uint64_type->type_info;
 
-               break;
-       }
+       case MONO_TYPE_R4:
+               return table->builtin_types->single_type->type_info;
 
-       default:
-               size = sizeof (int);
-               break;
-       }
+       case MONO_TYPE_R8:
+               return table->builtin_types->double_type->type_info;
 
-       data_size = size;
+       case MONO_TYPE_STRING:
+               return table->builtin_types->string_type->type_info;
 
-       offset = allocate_type_entry (table, data_size, &ptr);
-       old_ptr = ptr;
+       case MONO_TYPE_I:
+               return table->builtin_types->int_type->type_info;
 
-       g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
+       case MONO_TYPE_U:
+               return table->builtin_types->uint_type->type_info;
 
-       switch (kind) {
        case MONO_TYPE_SZARRAY: {
                MonoArray array;
 
-               *((gint32 *) ptr)++ = -size;
-               *((guint32 *) ptr)++ = sizeof (MonoArray);
-               *ptr++ = 2;
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
+               WRITE_UINT32 (ptr, sizeof (MonoArray));
+               g_assert (table->builtin_types->array_type->type_info != 0);
+               WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
                *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
                *ptr++ = sizeof (array.max_length);
                *ptr++ = (guint8*)&array.vector - (guint8*)&array;
-               *((guint32 *) ptr)++ = write_type (table, type->data.type);
+               WRITE_UINT32 (ptr, write_type (table, &type->data.klass->byval_arg));
                break;
        }
 
@@ -595,122 +918,50 @@ write_type (MonoDebuggerSymbolTable *table, MonoType *type)
                MonoArray array;
                MonoArrayBounds bounds;
 
-               *((gint32 *) ptr)++ = -size;
-               *((guint32 *) ptr)++ = sizeof (MonoArray);
-               *ptr++ = 3;
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
+               WRITE_UINT32 (ptr, sizeof (MonoArray));
+               g_assert (table->builtin_types->array_type->type_info != 0);
+               WRITE_UINT32 (ptr, table->builtin_types->array_type->type_info);
                *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
                *ptr++ = sizeof (array.max_length);
                *ptr++ = (guint8*)&array.vector - (guint8*)&array;
-               *ptr++ = type->data.array->rank;
+               *ptr++ = klass->rank;
                *ptr++ = (guint8*)&array.bounds - (guint8*)&array;
                *ptr++ = sizeof (MonoArrayBounds);
                *ptr++ = (guint8*)&bounds.lower_bound - (guint8*)&bounds;
                *ptr++ = sizeof (bounds.lower_bound);
                *ptr++ = (guint8*)&bounds.length - (guint8*)&bounds;
                *ptr++ = sizeof (bounds.length);
-               *((guint32 *) ptr)++ = write_type (table, type->data.array->type);
+               WRITE_UINT32 (ptr, write_type (table, &type->data.array->eklass->byval_arg));
                break;
        }
 
        case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS: {
-               int base_offset = kind == MONO_TYPE_CLASS ? 0 : - sizeof (MonoObject);
-               int i, j;
-
-               if (klass->init_pending) {
-                       *((gint32 *) ptr)++ = -1;
-                       break;
-               }
-
-               g_hash_table_insert (class_table, klass, GUINT_TO_POINTER (offset));
-
-               if (klass->enumtype) {
-                       *((gint32 *) ptr)++ = -size;
-                       *((guint32 *) ptr)++ = sizeof (MonoObject);
-                       *ptr++ = 4;
-                       *((guint32 *) ptr)++ = write_type (table, klass->enum_basetype);
-                       break;
-               }
-
-               *((gint32 *) ptr)++ = -size;
-
-               *((guint32 *) ptr)++ = klass->instance_size + base_offset;
-               if (type->type == MONO_TYPE_OBJECT)
-                       *ptr++ = 7;
-               else
-                       *ptr++ = kind == MONO_TYPE_CLASS ? 6 : 5;
-               *ptr++ = kind == MONO_TYPE_CLASS;
-               *((guint32 *) ptr)++ = num_fields;
-               *((guint32 *) ptr)++ = num_fields * (4 + sizeof (gpointer));
-               *((guint32 *) ptr)++ = num_properties;
-               *((guint32 *) ptr)++ = num_properties * 3 * sizeof (gpointer);
-               *((guint32 *) ptr)++ = num_methods;
-               *((guint32 *) ptr)++ = num_methods * (4 + 2 * sizeof (gpointer)) +
-                       num_params * sizeof (gpointer);
-               for (i = 0; i < klass->field.count; i++) {
-                       if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
-                               continue;
-
-                       *((guint32 *) ptr)++ = klass->fields [i].offset + base_offset;
-                       *((guint32 *) ptr)++ = write_type (table, klass->fields [i].type);
-               }
-
-               for (i = 0; i < klass->property.count; i++) {
-                       if (klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC)
-                               continue;
-
-                       if (klass->properties [i].get)
-                               *((guint32 *) ptr)++ = write_type
-                                       (table, klass->properties [i].get->signature->ret);
-                       else
-                               *((guint32 *) ptr)++ = 0;
-                       *((gpointer *) ptr)++ = klass->properties [i].get;
-                       *((gpointer *) ptr)++ = klass->properties [i].set;
-               }
-
-               for (i = 0; i < methods->len; i++) {
-                       MonoMethod *method = g_ptr_array_index (methods, i);
-
-                       *((gpointer *) ptr)++ = method;
-                       if ((method->signature->ret) && (method->signature->ret->type != MONO_TYPE_VOID))
-                               *((guint32 *) ptr)++ = write_type (table, method->signature->ret);
-                       else
-                               *((guint32 *) ptr)++ = 0;
-                       *((guint32 *) ptr)++ = method->signature->param_count;
-                       for (j = 0; j < method->signature->param_count; j++)
-                               *((guint32 *) ptr)++ = write_type (table, method->signature->params [j]);
-               }
-
-               g_ptr_array_free (methods, FALSE);
-
-               if (kind == MONO_TYPE_CLASS) {
-                       if (klass->parent)
-                               *((guint32 *) ptr)++ = write_type (table, &klass->parent->this_arg);
-                       else
-                               *((guint32 *) ptr)++ = 0;
-               }
-
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+               return write_class (table, klass);
+
+       case MONO_TYPE_PTR:
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
+               WRITE_UINT32 (ptr, sizeof (gpointer));
+               WRITE_UINT32 (ptr, write_type (table, type->data.type));
                break;
-       }
 
        default:
-               g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
-
-               *((gint32 *) ptr)++ = -1;
+               g_message (G_STRLOC ": %s.%s - %p - %d", klass->name_space, klass->name, klass, type->type);
+               *ptr++ = MONO_DEBUGGER_TYPE_KIND_UNKNOWN;
+               WRITE_UINT32 (ptr, klass->instance_size);
+               WRITE_UINT32 (ptr, write_class (table, klass));
                break;
        }
 
-       if (ptr - old_ptr != data_size) {
-               g_warning (G_STRLOC ": %d,%d - %d", ptr - old_ptr, data_size, kind);
-               if (klass)
-                       g_warning (G_STRLOC ": %s.%s", klass->name_space, klass->name);
-               g_assert_not_reached ();
-       }
+       size = ptr - buffer;
+       offset = allocate_type_entry (mono_debugger_symbol_table, size, &ptr);
+       memcpy (ptr, buffer, size);
 
        return offset;
 }
 
-
 MonoReflectionMethod *
 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
 {
@@ -867,3 +1118,129 @@ mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
 {
        mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
 }
+
+static gchar *
+get_exception_message (MonoObject *exc)
+{
+       char *message = NULL;
+       MonoString *str; 
+       MonoMethod *method;
+       MonoClass *klass;
+       gint i;
+
+       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+               klass = exc->vtable->klass;
+               method = NULL;
+               while (klass && method == NULL) {
+                       for (i = 0; i < klass->method.count; ++i) {
+                               method = klass->methods [i];
+                               if (!strcmp ("ToString", method->name) &&
+                                   method->signature->param_count == 0 &&
+                                   method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
+                                   method->flags & METHOD_ATTRIBUTE_PUBLIC) {
+                                       break;
+                               }
+                               method = NULL;
+                       }
+                       
+                       if (method == NULL)
+                               klass = klass->parent;
+               }
+
+               g_assert (method);
+
+               str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
+               if (str)
+                       message = mono_string_to_utf8 (str);
+       }
+
+       return message;
+}
+
+MonoObject *
+mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+{
+       MonoObject *retval;
+       gchar *message;
+
+       if (method->klass->valuetype && (obj != NULL))
+               obj = mono_value_box (mono_domain_get (), method->klass, obj);
+
+       if (!strcmp (method->name, ".ctor")) {
+               retval = obj = mono_object_new (mono_domain_get (), method->klass);
+
+               mono_runtime_invoke (method, obj, params, exc);
+       } else
+               retval = mono_runtime_invoke (method, obj, params, exc);
+
+       if (*exc == NULL)
+               return retval;
+
+       message = get_exception_message (*exc);
+       if (message) {
+               *exc = (MonoObject *) mono_string_new_wrapper (message);
+               g_free (message);
+       }
+
+       return retval;
+}
+
+guint32
+mono_debugger_lookup_type (const gchar *type_name)
+{
+       int i;
+
+       mono_debugger_lock ();
+
+       for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
+               MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
+               MonoType *type;
+               guint32 offset;
+               gchar *name;
+
+               name = g_strdup (type_name);
+               type = mono_reflection_type_from_name (name, symfile->image);
+               g_free (name);
+               if (!type)
+                       continue;
+
+               offset = write_type (mono_debugger_symbol_table, type);
+
+               mono_debugger_unlock ();
+               return offset;
+       }
+
+       mono_debugger_unlock ();
+       return 0;
+}
+
+gint32
+mono_debugger_lookup_assembly (const gchar *name)
+{
+       MonoAssembly *assembly;
+       MonoImageOpenStatus status;
+       int i;
+
+       mono_debugger_lock ();
+
+ again:
+       for (i = 0; i < mono_debugger_symbol_table->num_symbol_files; i++) {
+               MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
+
+               if (!strcmp (symfile->image_file, name)) {
+                       mono_debugger_unlock ();
+                       return i;
+               }
+       }
+
+       assembly = mono_assembly_open (name, &status);
+
+       if (status != MONO_IMAGE_OK) {
+               g_warning (G_STRLOC ": Cannot open image `%s'", name);
+               mono_debugger_unlock ();
+               return -1;
+       }
+
+       must_reload_symtabs = TRUE;
+       goto again;
+}