#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;
MonoDebuggerIOLayer mono_debugger_io_layer = {
InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
EnterCriticalSection, LeaveCriticalSection, WaitForSingleObject, SignalObjectAndWait,
- WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread
+ WaitForMultipleObjects, CreateSemaphore, ReleaseSemaphore, CreateThread,
+ GetCurrentThreadId
};
#endif
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 *
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;
}
g_assert (!mono_debugger_initialized);
InitializeCriticalSection (&debugger_lock_mutex);
+ mono_debugger_initialized = TRUE;
mono_debugger_lock ();
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 ();
}
mono_debugger_lock ();
info = g_hash_table_lookup (images, handle->image);
- if (info)
+ if (info) {
+ mono_debugger_unlock ();
return info;
+ }
info = allocate_symbol_file_entry (mono_debugger_symbol_table);
info->symfile = handle->symfile;
cinfo->type_info = write_class (mono_debugger_symbol_table, klass);
- mono_debugger_event (MONO_DEBUGGER_EVENT_TYPE_ADDED, NULL, 0);
+ must_reload_symtabs = TRUE;
mono_debugger_unlock ();
}
size = sizeof (MonoSymbolFileMethodAddress);
- num_variables = minfo->entry->num_parameters + minfo->entry->num_locals;
+ 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);
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;
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 (jit, block->start_offset);
- block_table [i].end_address = _mono_debug_address_from_il_offset (jit, 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;
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 (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) {
+ 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, jit->num_params,
- minfo->entry->num_parameters);
- var_table += minfo->entry->num_parameters;
+ read32(&(minfo->entry->_num_parameters)));
+ var_table += read32(&(minfo->entry->_num_parameters));
} else {
for (i = 0; i < jit->num_params; i++) {
*var_table++ = jit->params [i];
}
}
- if (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, jit->num_locals,
- minfo->entry->num_locals);
- var_table += minfo->entry->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++) {
+ 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 *
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);
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);
write_class (MonoDebuggerSymbolTable *table, MonoClass *klass)
{
guint8 buffer [BUFSIZ], *ptr = buffer, *old_ptr;
- GPtrArray *methods = NULL, *static_methods = NULL;
+ 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;
method_slots = g_hash_table_new (NULL, NULL);
methods = g_ptr_array_new ();
static_methods = g_ptr_array_new ();
+ ctors = 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_SPECIAL_NAME)
+ if (!strcmp (method->name, ".cctor"))
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)))
+
+ if (!strcmp (method->name, ".ctor")) {
+ ++num_ctors;
+ num_ctor_params += method->signature->param_count;
+ g_ptr_array_add (ctors, method);
continue;
- g_hash_table_insert (method_slots, GUINT_TO_POINTER (method->slot), method);
+ }
+
+ 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;
g_hash_table_destroy (method_slots);
- size = 58 + sizeof (gpointer) + num_fields * 8 + num_static_fields * 8 + num_properties * (4 + 2 * sizeof (gpointer)) +
+ 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_static_methods * (8 + sizeof (gpointer)) + num_static_params * 4 + num_ctors * (8 + sizeof (gpointer)) +
+ num_ctor_params * 4;
data_size = size;
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, 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
if (method->klass->valuetype && (obj != NULL))
obj = mono_value_box (mono_domain_get (), method->klass, obj);
- retval = 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 == NULL)
return retval;
MonoDebuggerSymbolFile *symfile = mono_debugger_symbol_table->symbol_files [i];
MonoType *type;
guint32 offset;
+ gchar *name;
- type = mono_reflection_type_from_name (type_name, symfile->image);
+ name = g_strdup (type_name);
+ type = mono_reflection_type_from_name (name, symfile->image);
+ g_free (name);
if (!type)
continue;
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;
+}