#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);
+#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, gpointer data2) = 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
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 (void)
+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_SYMBOL_FILE_DYNAMIC_MAGIC;
- symbol_table->version = MONO_SYMBOL_FILE_DYNAMIC_VERSION;
- symbol_table->total_size = sizeof (MonoDebuggerSymbolTable);
-
- mono_debugger_symbol_table = symbol_table;
- mono_debugger_initialized = TRUE;
-
- mono_debugger_unlock ();
-}
-
-MonoDebuggerSymbolFile *
-mono_debugger_add_symbol_file (MonoSymbolFile *symfile)
-{
- MonoDebuggerSymbolFile *info;
-
- g_assert (mono_debugger_initialized);
-
- info = allocate_symbol_file_entry (mono_debugger_symbol_table);
- info->symfile = symfile;
- info->image_file = symfile->image_file;
-
- mono_debugger_add_type (info, mono_defaults.object_class);
-
- return info;
+ mono_debugger_use_debugger = use_debugger;
}
void
-mono_debugger_add_type (MonoDebuggerSymbolFile *symfile, MonoClass *klass)
+mono_debugger_add_symbol_file (MonoDebugHandle *handle)
{
- MonoDebuggerClassInfo *info;
+ 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. */
- if ((klass != mono_defaults.object_class) && g_hash_table_lookup (class_table, klass)) {
- mono_debugger_unlock ();
- return;
- }
-
- symfile->generation++;
-
- 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_type (mono_debugger_symbol_table, &klass->this_arg);
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, symfile, klass);
+ mono_debugger_event (MONO_DEBUGGER_EVENT_ADD_MODULE, GPOINTER_TO_UINT (handle), 0);
mono_debugger_unlock ();
}
void
-mono_debugger_add_method (MonoDebuggerSymbolFile *symfile, MonoMethod *method)
+mono_debugger_add_builtin_types (MonoDebugHandle *symfile)
{
- MonoSymbolFileMethodAddress *address;
- MonoSymbolFileLexicalBlockEntry *block;
- MonoDebugMethodInfo *minfo;
- 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 *) method)->header;
-
- minfo = g_hash_table_lookup (symfile->symfile->method_hash, method);
- if (!minfo || !minfo->jit)
- return;
-
- size = sizeof (MonoSymbolFileMethodAddress);
-
- num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
- has_this = minfo->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 (minfo->jit->line_numbers) {
- line_offset = size;
- line_size = minfo->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 (minfo, block->start_offset);
- block_table [i].end_address = _mono_debug_address_from_il_offset (minfo, 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->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;
- address->line_number_offset = line_offset;
-
- line_table = (MonoDebugLineNumberEntry *) (ptr + line_offset);
- memcpy (line_table, minfo->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 ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
- (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
- (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 (minfo->jit->this_var)
- *var_table++ = *minfo->jit->this_var;
- *type_table++ = write_type (mono_debugger_symbol_table, &method->klass->this_arg);
-
- if (minfo->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, minfo->jit->num_params,
- minfo->entry->num_parameters);
- G_BREAKPOINT ();
- var_table += 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]);
- }
- }
-
- if (minfo->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, minfo->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++ = minfo->jit->locals [i];
- *type_table++ = write_type (mono_debugger_symbol_table, header->locals [i]);
- }
- }
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, symfile, method);
+ 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 MonoDebuggerRangeInfo *
-allocate_range_entry (MonoDebuggerSymbolFile *symfile)
+void
+mono_debugger_start_add_type (MonoDebugHandle *symfile, MonoClass *klass)
{
- 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;
+ must_reload_symtabs = TRUE;
}
-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)
-{
- 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;
- *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;
-}
-
-static guint32
-write_simple_type (MonoDebuggerSymbolTable *table, MonoType *type)
+void
+mono_debugger_add_type (MonoDebugHandle *symfile, MonoClass *klass)
{
- guint8 buffer [BUFSIZ], *ptr = buffer;
- guint32 size, offset;
-
- 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;
-
- switch (type->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- *((gint32 *) ptr)++ = 1;
- break;
-
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- *((gint32 *) ptr)++ = 2;
- break;
-
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- *((gint32 *) ptr)++ = 4;
- break;
-
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R8:
- *((gint32 *) ptr)++ = 8;
- break;
-
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- *((gint32 *) ptr)++ = sizeof (void *);
- break;
-
- case MONO_TYPE_VOID:
- *((gint32 *) ptr)++ = 0;
- break;
-
- case MONO_TYPE_STRING: {
- MonoString string;
-
- *((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;
- }
-
- 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;
}
-/*
- * 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, *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);
-
- 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;
-
- if (klass->enumtype) {
- size = 13;
- break;
- }
-
- 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 = klass->method.count - 1; i >= 0; 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 + num_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
- num_methods * (8 + sizeof (gpointer)) + num_params * 4;
-
- if (kind == MONO_TYPE_CLASS)
- size += 4;
-
- break;
- }
-
- default:
- size = sizeof (int);
- break;
- }
-
- data_size = size;
-
- offset = allocate_type_entry (table, data_size, &ptr);
- old_ptr = ptr;
-
- g_hash_table_insert (type_table, type, GUINT_TO_POINTER (offset));
-
- switch (kind) {
- case MONO_TYPE_SZARRAY: {
- MonoArray array;
-
- *((gint32 *) ptr)++ = -size;
- *((guint32 *) ptr)++ = sizeof (MonoArray);
- *ptr++ = 2;
- *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);
- break;
- }
-
- case MONO_TYPE_ARRAY: {
- MonoArray array;
- MonoArrayBounds bounds;
-
- *((gint32 *) ptr)++ = -size;
- *((guint32 *) ptr)++ = sizeof (MonoArray);
- *ptr++ = 3;
- *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->type);
- 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;
- }
-
- break;
- }
-
- default:
- g_message (G_STRLOC ": %p - %x,%x,%x", type, type->attrs, kind, type->byref);
-
- *((gint32 *) ptr)++ = -1;
- 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 ();
- }
-
- return offset;
}
-
MonoReflectionMethod *
ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
{
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);
}
{
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;
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);
}
void
-mono_debugger_event (MonoDebuggerEvent event, gpointer data, gpointer data2)
+mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
{
if (mono_debugger_event_handler)
- (* mono_debugger_event_handler) (event, data, data2);
+ (* mono_debugger_event_handler) (event, data, arg);
}
void
static GPtrArray *breakpoints = NULL;
int
-mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc, gboolean use_trampoline)
+mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
{
static int last_breakpoint_id = 0;
MonoDebuggerBreakpointInfo *info;
info = g_new0 (MonoDebuggerBreakpointInfo, 1);
info->desc = desc;
- info->use_trampoline = use_trampoline;
info->index = ++last_breakpoint_id;
if (!breakpoints)
mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
{
MonoMethodDesc *desc;
- gboolean in_the_debugger;
desc = mono_method_desc_new (method_name, include_namespace);
if (!desc)
return 0;
- in_the_debugger = mono_debug_format == MONO_DEBUG_FORMAT_DEBUGGER;
- return mono_debugger_insert_breakpoint_full (desc, in_the_debugger);
+ return mono_debugger_insert_breakpoint_full (desc);
}
int
-mono_debugger_method_has_breakpoint (MonoMethod* method, gboolean use_trampoline)
+mono_debugger_method_has_breakpoint (MonoMethod *method)
{
int i;
for (i = 0; i < breakpoints->len; i++) {
MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
- if (info->use_trampoline != use_trampoline)
- continue;
-
if (!mono_method_desc_full_match (info->desc, method))
continue;
}
void
-mono_debugger_trampoline_breakpoint_callback (void)
+mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
+{
+ mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, GPOINTER_TO_UINT (method), index);
+}
+
+gboolean
+mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
{
- mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT_TRAMPOLINE, NULL, NULL);
+ 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)
+{
+ MonoObject *retval;
+ gchar *message;
+
+ 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;
+}
+