2005-07-21 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mono / metadata / mono-debug-debugger.c
index c81354f23e292103298fed9d6be492001d6ba90b..b20f440d4fa95b7df626dfc67a5b21c140de6ba0 100644 (file)
@@ -1,41 +1,66 @@
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
+#include <mono/metadata/assembly.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/appdomain.h>
+#include <mono/metadata/gc-internal.h>
+#include <mono/os/gc_wrapper.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/class-internals.h>
 #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 CLASS_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 gboolean mono_debugger_use_debugger = FALSE;
+static MonoObject *last_exception = NULL;
+
+struct _MonoDebuggerMetadataInfo {
+       int size;
+       int mono_defaults_size;
+       MonoDefaults *mono_defaults;
+       int klass_field_offset;
+       int klass_methods_offset;
+       int klass_method_count_offset;
+       int field_info_size;
+};
+
+void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
+
+#define WRITE_UINT32(ptr,value) G_STMT_START { \
+       * ((guint32 *) ptr) = value;            \
+       ptr += 4;                               \
+} G_STMT_END
 
-static GHashTable *type_table = NULL;
-static GHashTable *class_table = NULL;
+#define WRITE_POINTER(ptr,value) G_STMT_START {        \
+       * ((gpointer *) ptr) = (gpointer) (value); \
+       ptr += sizeof (gpointer);               \
+} G_STMT_END
 
-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);
+#define WRITE_STRING(ptr,value) G_STMT_START { \
+       memcpy (ptr, value, strlen (value)+1);  \
+       ptr += strlen (value)+1;                \
+} G_STMT_END
 
-MonoDebuggerSymbolTable *mono_debugger_symbol_table = NULL;
-void (*mono_debugger_event_handler) (MonoDebuggerEvent event, gpointer data, guint32 arg) = NULL;
+typedef struct {
+       gpointer stack_pointer;
+       MonoObject *exception_obj;
+       guint32 stop;
+} MonoDebuggerExceptionInfo;
 
 #ifndef PLATFORM_WIN32
 
 MonoDebuggerIOLayer mono_debugger_io_layer = {
        InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
-       EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
-       WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
+       EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
+       WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
+       GetCurrentThreadId
 };
 
 #endif
@@ -43,663 +68,77 @@ MonoDebuggerIOLayer mono_debugger_io_layer = {
 void
 mono_debugger_lock (void)
 {
-       if (mono_debugger_initialized)
-               EnterCriticalSection (&debugger_lock_mutex);
+       EnterCriticalSection (&debugger_lock_mutex);
+       debugger_lock_level++;
 }
 
 void
 mono_debugger_unlock (void)
 {
-       if (mono_debugger_initialized)
-               LeaveCriticalSection (&debugger_lock_mutex);
-}
-
-static MonoDebuggerSymbolFile *
-allocate_symbol_file_entry (MonoDebuggerSymbolTable *table)
-{
-       MonoDebuggerSymbolFile *symfile;
-
-       if (!table->symbol_files)
-               table->symbol_files = g_new0 (MonoDebuggerSymbolFile *, SYMFILE_TABLE_CHUNK_SIZE);
-       else if (!((table->num_symbol_files + 1) % SYMFILE_TABLE_CHUNK_SIZE)) {
-               guint32 chunks = (table->num_symbol_files + 1) / SYMFILE_TABLE_CHUNK_SIZE;
-               guint32 size = sizeof (MonoDebuggerSymbolFile *) * SYMFILE_TABLE_CHUNK_SIZE * (chunks + 1);
-
-               table->symbol_files = g_realloc (table->symbol_files, size);
+       if (debugger_lock_level == 1) {
+               if (must_reload_symtabs && mono_debugger_use_debugger) {
+                       mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, 0, 0);
+                       must_reload_symtabs = FALSE;
+               }
        }
 
-       symfile = g_new0 (MonoDebuggerSymbolFile, 1);
-       table->symbol_files [table->num_symbol_files++] = symfile;
-       return symfile;
+       debugger_lock_level--;
+       LeaveCriticalSection (&debugger_lock_mutex);
 }
 
 void
-mono_debugger_initialize (MonoDomain *domain)
+mono_debugger_initialize (gboolean use_debugger)
 {
-       MonoDebuggerSymbolTable *symbol_table;
-
-       g_assert (!mono_debugger_initialized);
+       MONO_GC_REGISTER_ROOT (last_exception);
+       
+       g_assert (!mono_debugger_use_debugger);
 
        InitializeCriticalSection (&debugger_lock_mutex);
-
-       mono_debugger_lock ();
-
-       symbol_table = g_new0 (MonoDebuggerSymbolTable, 1);
-       symbol_table->magic = MONO_DEBUGGER_MAGIC;
-       symbol_table->version = MONO_DEBUGGER_VERSION;
-       symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
-
-       symbol_table->domain = domain;
-
-       mono_debugger_symbol_table = symbol_table;
-       mono_debugger_initialized = TRUE;
-
-       mono_debugger_unlock ();
-}
-
-MonoDebuggerSymbolFile *
-mono_debugger_add_symbol_file (MonoDebugHandle *handle)
-{
-       MonoDebuggerSymbolFile *info;
-
-       g_assert (mono_debugger_initialized);
-
-       info = allocate_symbol_file_entry (mono_debugger_symbol_table);
-       info->symfile = handle->symfile;
-       info->image = handle->image;
-       info->image_file = handle->image_file;
-
-       mono_debugger_add_type (info, mono_defaults.object_class);
-
-       return info;
-}
-
-static MonoDebuggerClassInfo *
-add_builtin_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
-{
-       MonoDebuggerClassInfo *info;
-
-       info = allocate_class_entry (symfile);
-       info->klass = klass;
-       if (klass->rank) {
-               info->token = klass->element_class->type_token;
-               info->rank = klass->rank;
-       } else
-               info->token = klass->type_token;
-       info->type_info = write_class (mono_debugger_symbol_table, klass);
-
-       return info;
-}
-
-MonoDebuggerBuiltinTypes *
-mono_debugger_add_builtin_types (MonoDebuggerSymbolFile *symfile)
-{
-       MonoDebuggerBuiltinTypes *types = g_new0 (MonoDebuggerBuiltinTypes, 1);
-
-       types->total_size = sizeof (MonoDebuggerBuiltinTypes);
-       types->object_class = add_builtin_type (symfile, mono_defaults.object_class);
-       types->byte_class = add_builtin_type (symfile, mono_defaults.byte_class);
-       types->void_class = add_builtin_type (symfile, mono_defaults.void_class);
-       types->boolean_class = add_builtin_type (symfile, mono_defaults.boolean_class);
-       types->sbyte_class = add_builtin_type (symfile, mono_defaults.sbyte_class);
-       types->int16_class = add_builtin_type (symfile, mono_defaults.int16_class);
-       types->uint16_class = add_builtin_type (symfile, mono_defaults.uint16_class);
-       types->int32_class = add_builtin_type (symfile, mono_defaults.int32_class);
-       types->uint32_class = add_builtin_type (symfile, mono_defaults.uint32_class);
-       types->int_class = add_builtin_type (symfile, mono_defaults.int_class);
-       types->uint_class = add_builtin_type (symfile, mono_defaults.uint_class);
-       types->int64_class = add_builtin_type (symfile, mono_defaults.int64_class);
-       types->uint64_class = add_builtin_type (symfile, mono_defaults.uint64_class);
-       types->single_class = add_builtin_type (symfile, mono_defaults.single_class);
-       types->double_class = add_builtin_type (symfile, mono_defaults.double_class);
-       types->char_class = add_builtin_type (symfile, mono_defaults.char_class);
-       types->string_class = add_builtin_type (symfile, mono_defaults.string_class);
-       types->enum_class = add_builtin_type (symfile, mono_defaults.enum_class);
-       types->array_class = add_builtin_type (symfile, mono_defaults.array_class);
-
-       mono_debugger_symbol_table->corlib = symfile;
-       mono_debugger_symbol_table->builtin_types = types;
-
-       return types;
+       mono_debugger_use_debugger = use_debugger;
 }
 
 void
-mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
+mono_debugger_add_symbol_file (MonoDebugHandle *handle)
 {
-       guint32 info;
-       MonoDebuggerClassInfo *cinfo;
+       g_assert (mono_debugger_use_debugger);
 
        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. */
-       info = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
-       if ((info != 0) && (klass != mono_defaults.object_class)) {
-               mono_debugger_unlock ();
-               return;
-       }
-
-       symfile->generation++;
-
-       cinfo = allocate_class_entry (symfile);
-       cinfo->klass = klass;
-       if (klass->rank) {
-               cinfo->token = klass->element_class->type_token;
-               cinfo->rank = klass->rank;
-       } else
-               cinfo->token = klass->type_token;
-       cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
-
-       mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, NULL, 0);
+       mono_debugger_event (MONO_DEBUGGER_EVENT_ADD_MODULE, GPOINTER_TO_UINT (handle), 0);
        mono_debugger_unlock ();
 }
 
 void
-mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoDebugMethodInfo *minfo,
-                         MonoDebugMethodJitInfo *jit)
-{
-       MonoSymbolFileMethodAddress *address;
-       MonoSymbolFileLexicalBlockEntry *block;
-       MonoDebugVarInfo *var_table;
-       MonoDebuggerRangeInfo *range;
-       MonoMethodHeader *header;
-       guint32 size, num_variables, variable_size, variable_offset;
-       guint32 type_size, type_offset, *type_index_table, has_this;
-       guint32 line_size, line_offset, block_offset, block_size;
-       MonoDebugLexicalBlockEntry *block_table;
-       MonoDebugLineNumberEntry *line_table;
-       guint32 *type_table;
-       guint8 *ptr;
-       int i;
-
-       if (!symfile->symfile->method_hash)
-               return;
-
-       header = ((MonoMethodNormal *) minfo->method)->header;
-
-       symfile->generation++;
-
-       size = sizeof (MonoSymbolFileMethodAddress);
-
-       num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
-       has_this = jit->this_var != NULL;
-
-       variable_size = (num_variables + has_this) * sizeof (MonoDebugVarInfo);
-       variable_offset = size;
-       size += variable_size;
-
-       type_size = (num_variables + 1) * sizeof (gpointer);
-       type_offset = size;
-       size += type_size;
-
-       if (jit->line_numbers) {
-               line_offset = size;
-               line_size = jit->line_numbers->len * sizeof (MonoDebugLineNumberEntry);
-               size += line_size;
-       }
-
-       block_size = minfo->entry->num_lexical_blocks * sizeof (MonoSymbolFileLexicalBlockEntry);
-       block_offset = size;
-       size += block_size;
-
-       address = g_malloc0 (size);
-       ptr = (guint8 *) address;
-
-       block = (MonoSymbolFileLexicalBlockEntry *)
-               (symfile->symfile->raw_contents + 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 (jit, block->start_offset);
-               block_table [i].end_address = _mono_debug_address_from_il_offset (jit, block->end_offset);
-       }
-
-       address->size = size;
-       address->has_this = has_this;
-       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 (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, jit->line_numbers->data, line_size);
-       }
-
-       range = allocate_range_entry (symfile);
-       range->index = minfo->index;
-       range->start_address = address->start_address;
-       range->end_address = address->end_address;
-       range->dynamic_data = address;
-       range->dynamic_size = size;
-
-       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);
-
-       if (jit->this_var)
-               *var_table++ = *jit->this_var;
-       *type_table++ = write_type (mono_debugger_symbol_table, &minfo->method->klass->this_arg);
-
-       if (jit->num_params != 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, jit->num_params,
-                          minfo->entry->num_parameters);
-               var_table += minfo->entry->num_parameters;
-       } else {
-               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 (jit->num_locals < 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, jit->num_locals,
-                          minfo->entry->num_locals);
-               var_table += 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++ = jit->locals [i];
-                       *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
-               }
-       }
-
-       mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, NULL, 0);
-}
-
-static MonoDebuggerRangeInfo *
-allocate_range_entry (MonoDebuggerSymbolFile *symfile)
+mono_debugger_add_builtin_types (MonoDebugHandle *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);
-               symfile->num_range_entries = 1;
-               return symfile->range_table;
-       }
-
-       if (!((symfile->num_range_entries + 1) % RANGE_TABLE_CHUNK_SIZE)) {
-               chunks = (symfile->num_range_entries + 1) / RANGE_TABLE_CHUNK_SIZE;
-               size = sizeof (MonoDebuggerRangeInfo) * RANGE_TABLE_CHUNK_SIZE * (chunks + 1);
-
-               symfile->range_table = g_realloc (symfile->range_table, size);
-       }
-
-       retval = symfile->range_table + symfile->num_range_entries;
-       symfile->num_range_entries++;
-       return retval;
+       MonoDebuggerMetadataInfo *info;
+       MonoClass klass;
+
+       mono_symbol_table->corlib = symfile;
+       mono_symbol_table->metadata_info = info = g_new0 (MonoDebuggerMetadataInfo, 1);
+
+       info->size = sizeof (MonoDebuggerMetadataInfo);
+       info->mono_defaults = &mono_defaults;
+       info->mono_defaults_size = sizeof (MonoDefaults);
+       info->klass_field_offset = (guint8*)&klass.fields - (guint8*)&klass;
+       info->klass_methods_offset = (guint8*)&klass.methods - (guint8*)&klass;
+       info->klass_method_count_offset = (guint8*)&klass.method.count - (guint8*)&klass;
+       info->field_info_size = sizeof (MonoClassField);
 }
 
-static MonoDebuggerClassInfo *
-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);
-               symfile->num_class_entries = 1;
-               return symfile->class_table;
-       }
-
-       if (!((symfile->num_class_entries + 1) % CLASS_TABLE_CHUNK_SIZE)) {
-               chunks = (symfile->num_class_entries + 1) / CLASS_TABLE_CHUNK_SIZE;
-               size = sizeof (MonoDebuggerClassInfo) * CLASS_TABLE_CHUNK_SIZE * (chunks + 1);
-
-               symfile->class_table = g_realloc (symfile->class_table, size);
-       }
-
-       retval = symfile->class_table + symfile->num_class_entries;
-       symfile->num_class_entries++;
-       return retval;
-}
-
-/*
- * Allocate a new entry of size `size' in the type table.
- * Returns the global offset which is to be used to reference this type and
- * a pointer (in the `ptr' argument) which is to be used to write the type.
- */
-static guint32
-allocate_type_entry (MonoDebuggerSymbolTable *table, guint32 size, guint8 **ptr)
+void
+mono_debugger_start_add_type (MonoDebugHandle *symfile, MonoClass *klass)
 {
-       guint32 retval;
-       guint8 *data;
-
-       g_assert (size + 4 < TYPE_TABLE_CHUNK_SIZE);
-       g_assert (ptr != NULL);
-
-       /* Initialize things if necessary. */
-       if (!table->current_type_table) {
-               table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
-               table->type_table_size = TYPE_TABLE_CHUNK_SIZE;
-               table->type_table_chunk_size = TYPE_TABLE_CHUNK_SIZE;
-               table->type_table_offset = 1;
-       }
-
- again:
-       /* First let's check whether there's still enough room in the current_type_table. */
-       if (table->type_table_offset + size + 4 < table->type_table_size) {
-               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;
-               data += sizeof(gint32);
-               *ptr = data;
-               return retval;
-       }
-
-       /* Add the current_type_table to the type_tables vector and ... */
-       if (!table->type_tables) {
-               guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE;
-               table->type_tables = g_malloc0 (tsize);
-       }
-
-       if (!((table->num_type_tables + 1) % TYPE_TABLE_PTR_CHUNK_SIZE)) {
-               guint32 chunks = (table->num_type_tables + 1) / TYPE_TABLE_PTR_CHUNK_SIZE;
-               guint32 tsize = sizeof (gpointer) * TYPE_TABLE_PTR_CHUNK_SIZE * (chunks + 1);
-
-               table->type_tables = g_realloc (table->type_tables, tsize);
-       }
-
-       table->type_tables [table->num_type_tables++] = table->current_type_table;
-
-       /* .... allocate a new current_type_table. */
-       table->current_type_table = g_malloc0 (TYPE_TABLE_CHUNK_SIZE);
-       table->type_table_start = table->type_table_offset = table->type_table_size;
-       table->type_table_size += TYPE_TABLE_CHUNK_SIZE;
-
-       goto again;
+       must_reload_symtabs = TRUE;
 }
 
-static guint32
-write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
+void
+mono_debugger_add_type (MonoDebugHandle *symfile, MonoClass *klass)
 {
-       guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
-       GPtrArray *methods = NULL;
-       int num_fields = 0, num_properties = 0, num_methods = 0;
-       int num_params = 0, base_offset = 0;
-       guint32 size, data_size, offset;
-       GHashTable *method_slots = NULL;
-       int i;
-
-       g_assert (!klass->init_pending);
-       mono_class_init (klass);
-
-       offset = GPOINTER_TO_UINT (g_hash_table_lookup (class_table, klass));
-       if (offset)
-               return offset;
-
-       for (i = 0; i < klass->field.count; i++)
-               if (!(klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
-                       ++num_fields;
-
-       for (i = 0; i < klass->property.count; i++)
-               if (!(klass->properties [i].attrs & FIELD_ATTRIBUTE_STATIC))
-                       ++num_properties;
-
-       method_slots = g_hash_table_new (NULL, NULL);
-       methods = g_ptr_array_new ();
-
-       for (i = 0; i < klass->method.count; i++) {
-               MonoMethod *method = klass->methods [i];
-
-               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);
-
-               ++num_methods;
-               num_params += method->signature->param_count;
-
-               g_ptr_array_add (methods, method);
-       }
-
-       g_hash_table_destroy (method_slots);
-
-       size = 34 + sizeof (gpointer) + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
-               num_methods * (8 + sizeof (gpointer)) + num_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);
-
-       *((gpointer *) ptr)++ = klass;
-       *((guint32 *) ptr)++ = klass->instance_size + base_offset;
-       *ptr++ = klass->valuetype;
-       *((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);
-               int j;
-
-               *((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 (klass->parent && (klass->parent != mono_defaults.object_class))
-               *((guint32 *) ptr)++ = write_class (table, klass->parent);
-       else
-               *((guint32 *) 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;
 }
 
-/*
- * Adds type `type' to the type table and returns its offset.
- */
-static guint32
-write_type (MonoDebuggerSymbolTable *table, MonoType *type)
+void
+mono_debugger_add_method (MonoDebugMethodJitInfo *jit)
 {
-       guint8 buffer [BUFSIZ], *ptr = buffer;
-       guint32 size, offset;
-       MonoClass *klass;
-
-       if (!type_table)
-               type_table = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-       offset = GPOINTER_TO_UINT (g_hash_table_lookup (type_table, type));
-       if (offset)
-               return offset;
-
-       klass = mono_class_from_mono_type (type);
-       if (klass->init_pending)
-               return 0;
-       mono_class_init (klass);
-
-       switch (type->type) {
-       case MONO_TYPE_VOID:
-               *ptr++ = MONO_DEBUGGER_TYPE_KIND_FUNDAMENTAL;
-               *((gpointer *) ptr)++ = klass;
-               *((gint32 *) ptr)++ = 0;
-               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;
-               *((gpointer *) ptr)++ = klass;
-               *((gint32 *) ptr)++ = klass->instance_size;
-               *((guint32 *) ptr)++ = write_class (table, klass);
-               break;
-
-       case MONO_TYPE_STRING: {
-               MonoString string;
-
-               *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRING;
-               *((gpointer *) ptr)++ = klass;
-               *((guint32 *) ptr)++ = klass->instance_size;
-               *((guint32 *) ptr)++ = write_class (table, klass);
-               *((gpointer *) ptr)++ = mono_class_vtable (table->domain, klass);
-               *ptr++ = (guint8*)&string.length - (guint8*)&string;
-               *ptr++ = sizeof (string.length);
-               *ptr++ = (guint8*)&string.chars - (guint8*)&string;
-
-               break;
-       }
-
-       case MONO_TYPE_SZARRAY: {
-               MonoArray array;
-
-               *ptr++ = MONO_DEBUGGER_TYPE_KIND_SZARRAY;
-               *((gpointer *) ptr)++ = klass;
-               *((guint32 *) ptr)++ = sizeof (MonoArray);
-               *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.klass->byval_arg);
-               break;
-       }
-
-       case MONO_TYPE_ARRAY: {
-               MonoArray array;
-               MonoArrayBounds bounds;
-
-               *ptr++ = MONO_DEBUGGER_TYPE_KIND_ARRAY;
-               *((gpointer *) ptr)++ = klass;
-               *((guint32 *) ptr)++ = sizeof (MonoArray);
-               *ptr++ = (guint8*)&array.max_length - (guint8*)&array;
-               *ptr++ = sizeof (array.max_length);
-               *ptr++ = (guint8*)&array.vector - (guint8*)&array;
-               *ptr++ = type->data.array->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->eklass->byval_arg);
-               break;
-       }
-
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-               *ptr++ = MONO_DEBUGGER_TYPE_KIND_POINTER;
-               *((gpointer *) ptr)++ = klass;
-               *((gint32 *) ptr)++ = sizeof (void *);
-               break;
-
-       case MONO_TYPE_VALUETYPE:
-       case MONO_TYPE_CLASS:
-               if (klass->enumtype) {
-                       *ptr++ = MONO_DEBUGGER_TYPE_KIND_ENUM;
-                       *((gpointer *) ptr)++ = klass;
-                       *((guint32 *) ptr)++ = klass->instance_size;
-                       *((guint32 *) ptr)++ = write_class (table, klass);
-                       *((guint32 *) ptr)++ = write_type (table, klass->enum_basetype);
-                       break;
-               }
-
-               if (type->type == MONO_TYPE_OBJECT)
-                       *ptr++ = MONO_DEBUGGER_TYPE_KIND_OBJECT;
-               else if (type->type == MONO_TYPE_CLASS)
-                       *ptr++ = MONO_DEBUGGER_TYPE_KIND_CLASS;
-               else
-                       *ptr++ = MONO_DEBUGGER_TYPE_KIND_STRUCT;
-
-               *((gpointer *) ptr)++ = klass;
-               *((guint32 *) ptr)++ = klass->instance_size;
-               *((guint32 *) ptr)++ = write_class (table, klass);
-               break;
-
-       default:
-               return 0;
-       }
-
-       size = ptr - buffer;
-       offset = allocate_type_entry (table, size, &ptr);
-       memcpy (ptr, buffer, size);
-
-       g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
-
-       return offset;
 }
 
 MonoReflectionMethod *
@@ -707,7 +146,7 @@ ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 toke
 {
        MonoMethod *method;
 
-       method = mono_get_method (assembly->assembly->image, token, NULL);
+       method = mono_get_method (mono_assembly_get_image (assembly->assembly), token, NULL);
 
        return mono_method_get_object (mono_domain_get (), method, NULL);
 }
@@ -723,7 +162,7 @@ ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
 {
        MonoClass *klass;
 
-       klass = mono_class_get (assembly->assembly->image, token);
+       klass = mono_class_get (mono_assembly_get_image (assembly->assembly), token);
        if (!klass) {
                g_warning (G_STRLOC ": %x", token);
                return NULL;
@@ -745,7 +184,7 @@ ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assemb
        MONO_CHECK_ARG_NULL (signature);
 
        domain = mono_domain_get();
-       image = assembly->assembly->image;
+       image = mono_assembly_get_image (assembly->assembly);
 
        ptr = mono_array_addr (signature, char, 0);
        g_assert (*ptr++ == 0x07);
@@ -758,7 +197,7 @@ ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assemb
 }
 
 void
-mono_debugger_event (MonoDebuggerEvent event, gpointer data, guint32 arg)
+mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
 {
        if (mono_debugger_event_handler)
                (* mono_debugger_event_handler) (event, data, arg);
@@ -856,14 +295,182 @@ mono_debugger_method_has_breakpoint (MonoMethod *method)
 void
 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
 {
-       mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, method, index);
+       mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, GPOINTER_TO_UINT (method), index);
+}
+
+gboolean
+mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
+{
+       if (!mono_debugger_use_debugger)
+               return FALSE;
+
+       // Prevent the object from being finalized.
+       last_exception = exc;
+       mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION,
+                            GPOINTER_TO_UINT (exc), GPOINTER_TO_UINT (addr));
+       return TRUE;
+}
+
+void
+mono_debugger_handle_exception (gpointer addr, gpointer stack, MonoObject *exc)
+{
+       MonoDebuggerExceptionInfo info;
+
+       if (!mono_debugger_use_debugger)
+               return;
+
+       // Prevent the object from being finalized.
+       last_exception = exc;
+
+       info.stack_pointer = stack;
+       info.exception_obj = exc;
+       info.stop = 0;
+
+       mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION, GPOINTER_TO_UINT (&info),
+                            GPOINTER_TO_UINT (addr));
+}
+
+gboolean
+mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
+{
+       MonoDebuggerExceptionInfo info;
+
+       if (!mono_debugger_use_debugger)
+               return FALSE;
+
+       // Prevent the object from being finalized.
+       last_exception = exc;
+
+       info.stack_pointer = stack;
+       info.exception_obj = exc;
+       info.stop = 0;
+
+       mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, GPOINTER_TO_UINT (&info),
+                            GPOINTER_TO_UINT (addr));
+       return info.stop != 0;
+}
+
+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) &&
+                                   mono_method_signature (method)->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)
 {
-       if (method->klass->valuetype)
-               obj = mono_value_box (mono_debugger_symbol_table->domain, method->klass, obj);
+       MonoObject *retval;
+       gchar *message;
 
-       return mono_runtime_invoke (method, obj, params, exc);
+       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 || (*exc == NULL))
+               return retval;
+
+       message = get_exception_message (*exc);
+       if (message) {
+               *exc = (MonoObject *) mono_string_new_wrapper (message);
+               g_free (message);
+       }
+
+       return retval;
 }
+
+gboolean
+mono_debugger_lookup_type (const gchar *type_name)
+{
+       int i;
+       mono_debugger_lock ();
+
+       for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
+               MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
+               MonoType *type;
+               MonoClass* klass;
+               gchar *name;
+
+               name = g_strdup (type_name);
+               type = mono_reflection_type_from_name (name, symfile->image);
+               g_free (name);
+               if (!type)
+                       continue;
+
+               klass = mono_class_from_mono_type (type);
+               if (klass)
+                       mono_class_init (klass);
+
+               mono_debugger_unlock ();
+               return TRUE;
+       }
+
+       mono_debugger_unlock ();
+       return FALSE;
+}
+
+gint32
+mono_debugger_lookup_assembly (const gchar *name)
+{
+       MonoAssembly *assembly;
+       MonoImageOpenStatus status;
+       int i;
+
+       mono_debugger_lock ();
+
+ again:
+       for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
+               MonoDebugHandle *symfile = mono_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;
+}
+