Example #1
0
static guint64
debugger_insert_method_breakpoint (guint64 method_argument, guint64 index)
{
	MonoMethod *method = GUINT_TO_POINTER ((gsize) method_argument);
	MonoDebugMethodAddressList *info;

	mono_debugger_lock ();

	if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
		const char *name = method->name;
		MonoMethod *nm = NULL;

		if (method->klass->parent == mono_defaults.multicastdelegate_class) {
			if (*name == 'I' && (strcmp (name, "Invoke") == 0))
			        nm = mono_marshal_get_delegate_invoke (method, NULL);
			else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
				nm = mono_marshal_get_delegate_begin_invoke (method);
			else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
				nm = mono_marshal_get_delegate_end_invoke (method);
		}

		if (!nm) {
			mono_debugger_unlock ();
			return 0;
		}

		method = nm;
	}

	info = mono_debugger_insert_method_breakpoint (method, index);

	mono_debugger_unlock ();
	return (guint64) (gsize) info;
}
Example #2
0
/*
 * mono_debug_lookup_locals:
 *
 *   Return information about the local variables of MINFO.
 * The result should be freed using mono_debug_free_locals ().
 */
MonoDebugLocalsInfo*
mono_debug_lookup_locals (MonoMethod *method)
{
	MonoDebugMethodInfo *minfo;
	MonoDebugLocalsInfo *res;

	if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
		return NULL;

	mono_debugger_lock ();
	minfo = mono_debug_lookup_method_internal (method);
	if (!minfo || !minfo->handle) {
		mono_debugger_unlock ();
		return NULL;
	}

	if (minfo->handle->ppdb) {
		res = mono_ppdb_lookup_locals (minfo);
	} else {
		if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
			res = NULL;
		else
			res = mono_debug_symfile_lookup_locals (minfo);
	}
	mono_debugger_unlock ();

	return res;
}
Example #3
0
static void
mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
{
    mono_debugger_lock ();
    mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
    mono_debugger_unlock ();
}
Example #4
0
/**
 * mono_debug_lookup_source_location_by_il:
 *
 *   Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
 */
MonoDebugSourceLocation *
mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain)
{
	MonoDebugMethodInfo *minfo;
	MonoDebugSourceLocation *location;

	if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
		return NULL;

	mono_debugger_lock ();
	minfo = mono_debug_lookup_method_internal (method);
	if (!minfo || !minfo->handle) {
		mono_debugger_unlock ();
		return NULL;
	}

	if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
		mono_debugger_unlock ();
		return NULL;
	}

	if (minfo->handle->ppdb)
		location = mono_ppdb_lookup_location (minfo, il_offset);
	else
		location = mono_debug_symfile_lookup_location (minfo, il_offset);
	mono_debugger_unlock ();
	return location;
}
Example #5
0
void
mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
{
	MonoMethod *declaring;
	MonoDebugDataTable *table;
	MonoDebugMethodHeader *header;
	MonoDebugMethodAddress *address;

	if (!mono_debug_initialized)
		return;

	g_assert (method->dynamic);

	mono_debugger_lock ();

	table = lookup_data_table (domain);

	declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
	g_hash_table_remove (table->method_hash, declaring);

	address = g_hash_table_lookup (table->method_address_hash, method);
	if (address) {
		header = &address->header;

		if (header->wrapper_data) {
			g_free ((char*)header->wrapper_data->method_name);
			g_free (header->wrapper_data);
		}
		g_free (address);
	}

	g_hash_table_remove (table->method_address_hash, method);

	mono_debugger_unlock ();
}
Example #6
0
void
mono_debug_domain_unload (MonoDomain *domain)
{
	MonoDebugDataTable *table;

	if (!mono_debug_initialized)
		return;

	mono_debugger_lock ();

	table = g_hash_table_lookup (data_table_hash, domain);
	if (!table) {
		g_warning (G_STRLOC ": unloading unknown domain %p / %d",
			   domain, mono_domain_get_id (domain));
		mono_debugger_unlock ();
		return;
	}

	mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
			     mono_domain_get_id (domain));

	g_hash_table_remove (data_table_hash, domain);

	mono_debugger_unlock ();
}
Example #7
0
/**
 * mono_debug_lookup_source_location:
 * @address: Native offset within the @method's machine code.
 *
 * Lookup the source code corresponding to the machine instruction located at
 * native offset @address within @method.
 *
 * The returned `MonoDebugSourceLocation' contains both file / line number
 * information and the corresponding IL offset.  It must be freed by
 * mono_debug_free_source_location().
 */
MonoDebugSourceLocation *
mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
{
	MonoDebugMethodInfo *minfo;
	MonoDebugSourceLocation *location;
	gint32 offset;

	if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
		return NULL;

	mono_debugger_lock ();
	minfo = _mono_debug_lookup_method (method);
	if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
		mono_debugger_unlock ();
		return NULL;
	}

	offset = il_offset_from_address (method, domain, address);
	if (offset < 0) {
		mono_debugger_unlock ();
		return NULL;
	}

	location = mono_debug_symfile_lookup_location (minfo, offset);
	mono_debugger_unlock ();
	return location;
}
Example #8
0
static void
debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy)
{
	mono_debugger_lock ();
	mono_debugger_remove_class_init_callback (index);
	mono_debugger_unlock ();
}
Example #9
0
static MonoDebugHandle *
mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
{
	MonoDebugHandle *handle;

	if (mono_image_is_dynamic (image))
		return NULL;

	mono_debugger_lock ();

	handle = mono_debug_get_image (image);
	if (handle != NULL) {
		mono_debugger_unlock ();
		return handle;
	}

	handle = g_new0 (MonoDebugHandle, 1);

	handle->image = image;
	mono_image_addref (image);

	/* Try a ppdb file first */
	handle->ppdb = mono_ppdb_load_file (handle->image, raw_contents, size);

	if (!handle->ppdb)
		handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, FALSE);

	g_hash_table_insert (mono_debug_handles, image, handle);

	mono_debugger_unlock ();

	return handle;
}
Example #10
0
/*
 * Initialize debugging support.
 *
 * This method must be called after loading corlib,
 * but before opening the application's main assembly because we need to set some
 * callbacks here.
 */
void
mono_debug_init (MonoDebugFormat format)
{
    g_assert (!mono_debug_initialized);

    if (_mono_debug_using_mono_debugger)
        format = MONO_DEBUG_FORMAT_DEBUGGER;

    mono_debug_initialized = TRUE;
    mono_debug_format = format;

    mono_debugger_initialize (_mono_debug_using_mono_debugger);

    mono_debugger_lock ();

    mono_symbol_table = g_new0 (MonoSymbolTable, 1);
    mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
    mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
    mono_symbol_table->total_size = sizeof (MonoSymbolTable);

    mono_debug_handles = g_hash_table_new_full
                         (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);

    data_table_hash = g_hash_table_new_full (
                          NULL, NULL, NULL, (GDestroyNotify) free_data_table);

    mono_debugger_class_init_func = mono_debug_add_type;
    mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
    mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);

    mono_symbol_table->global_data_table = create_data_table (NULL);

    mono_debugger_unlock ();
}
Example #11
0
MonoDebugMethodInfo *
mono_ppdb_lookup_method (MonoDebugHandle *handle, MonoMethod *method)
{
	MonoDebugMethodInfo *minfo;
	MonoPPDBFile *ppdb = handle->ppdb;

	if (handle->image != mono_class_get_image (mono_method_get_class (method)))
		return NULL;

	mono_debugger_lock ();

	minfo = (MonoDebugMethodInfo *)g_hash_table_lookup (ppdb->method_hash, method);
	if (minfo) {
		mono_debugger_unlock ();
		return minfo;
	}

	minfo = g_new0 (MonoDebugMethodInfo, 1);
	minfo->index = 0;
	minfo->method = method;
	minfo->handle = handle;

	g_hash_table_insert (ppdb->method_hash, method, minfo);

	mono_debugger_unlock ();

	return minfo;
}
Example #12
0
static void
mono_debug_add_type (MonoClass *klass)
{
	MonoDebugHandle *handle;
	MonoDebugClassEntry *entry;
	guint8 buffer [BUFSIZ];
	guint8 *ptr, *oldptr;
	guint32 size, total_size, max_size;
	int base_offset = 0;

	if (klass->generic_class || klass->rank ||
	    (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
		return;

	mono_debugger_lock ();

	handle = _mono_debug_get_image (klass->image);
	if (!handle) {
		mono_debugger_unlock ();
		return;
	}

	max_size = 12 + sizeof (gpointer);
	if (max_size > BUFSIZ)
		ptr = oldptr = g_malloc (max_size);
	else
		ptr = oldptr = buffer;

	if (klass->valuetype)
		base_offset = - (int)(sizeof (MonoObject));

	write_leb128 (klass->type_token, ptr, &ptr);
	write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
	WRITE_UNALIGNED (gpointer, ptr, klass);
	ptr += sizeof (gpointer);

	size = ptr - oldptr;
	g_assert (size < max_size);
	total_size = size + sizeof (MonoDebugClassEntry);

	g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);

	entry = (MonoDebugClassEntry *) allocate_data_item (
		handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);

	entry->size = total_size;

	memcpy (&entry->data, oldptr, size);

	write_data_item (handle->type_table, (guint8 *) entry);

	if (max_size > BUFSIZ)
		g_free (oldptr);

	mono_debugger_unlock ();
}
Example #13
0
/**
 * mono_debug_lookup_method:
 *
 * Lookup symbol file information for the method @method.  The returned
 * `MonoDebugMethodInfo' is a private structure, but it can be passed to
 * mono_debug_symfile_lookup_location().
 */
MonoDebugMethodInfo *
mono_debug_lookup_method (MonoMethod *method)
{
	MonoDebugMethodInfo *minfo;

	mono_debugger_lock ();
	minfo = _mono_debug_lookup_method (method);
	mono_debugger_unlock ();
	return minfo;
}
Example #14
0
void
mono_debugger_check_interruption (void)
{
	if (!_mono_debugger_interruption_request)
		return;

	mono_debugger_lock ();
	mono_debugger_event (MONO_DEBUGGER_EVENT_INTERRUPTION_REQUEST, 0, 0);
	mono_debugger_unlock ();
}
Example #15
0
/**
 * mono_debug_domain_create:
 */
void
mono_debug_domain_create (MonoDomain *domain)
{
	if (!mono_debug_initialized)
		return;

	mono_debugger_lock ();

	create_data_table (domain);

	mono_debugger_unlock ();
}
Example #16
0
static guint64
debugger_register_class_init_callback (guint64 image_argument, guint64 token, guint64 index,
				       const gchar *class_name)
{
	MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
	MonoClass *klass;

	mono_debugger_lock ();
	klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
	mono_debugger_unlock ();
	return (guint64) (gsize) klass;
}
Example #17
0
static guint64
debugger_compile_method (guint64 method_arg)
{
	MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
	gpointer addr;

	mono_debugger_lock ();
	addr = mono_compile_method (method);
	mono_debugger_unlock ();

	return (guint64) (gsize) addr;
}
Example #18
0
static guint64
debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint64 index,
				   const gchar *class_name)
{
	MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
	MonoDebugMethodAddressList *info;
	MonoClass *klass;
	int i;

	mono_debugger_lock ();

	klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
	if (!klass || !klass->inited || !klass->methods) {
		mono_debugger_unlock ();
		return 0;
	}

	for (i = 0; i < klass->method.count; i++) {
		MonoMethod *method = klass->methods [i];

		if (method->token != token)
			continue;

		if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
			const char *name = method->name;
			MonoMethod *nm = NULL;

			if (method->klass->parent == mono_defaults.multicastdelegate_class) {
				if (*name == 'I' && (strcmp (name, "Invoke") == 0))
					nm = mono_marshal_get_delegate_invoke (method, NULL);
				else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
					nm = mono_marshal_get_delegate_begin_invoke (method);
				else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
					nm = mono_marshal_get_delegate_end_invoke (method);
			}

			if (!nm) {
				mono_debugger_unlock ();
				return 0;
			}

			method = nm;
		}

		info = mono_debug_lookup_method_addresses (method);
		mono_debugger_unlock ();
		return (guint64) (gsize) info;
	}

	mono_debugger_unlock ();
	return 0;
}
Example #19
0
MonoDebugMethodJitInfo *
mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
{
	MonoDebugMethodJitInfo *res;

	if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
		return NULL;

	mono_debugger_lock ();
	res = find_method (method, domain);
	mono_debugger_unlock ();
	return res;
}
Example #20
0
/**
 * mono_debug_lookup_method:
 *
 * Lookup symbol file information for the method \p method.  The returned
 * \c MonoDebugMethodInfo is a private structure, but it can be passed to
 * \c mono_debug_symfile_lookup_location.
 */
MonoDebugMethodInfo *
mono_debug_lookup_method (MonoMethod *method)
{
	MonoDebugMethodInfo *minfo;

	if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
		return NULL;

	mono_debugger_lock ();
	minfo = mono_debug_lookup_method_internal (method);
	mono_debugger_unlock ();
	return minfo;
}
Example #21
0
static void
mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
{
	MonoDebugHandle *handle;
	MonoImage *image;

	mono_debugger_lock ();
	image = mono_assembly_get_image (assembly);
	handle = open_symfile_from_bundle (image);
	if (!handle)
		mono_debug_open_image (image, NULL, 0);
	mono_debugger_unlock ();
}
Example #22
0
/**
 * mono_debug_il_offset_from_address:
 *
 *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
 * code of METHOD in DOMAIN.
 */
gint32
mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
{
	gint32 res;

	mono_debugger_lock ();

	res = il_offset_from_address (method, domain, native_offset);

	mono_debugger_unlock ();

	return res;
}
Example #23
0
MonoDebugSourceLocation *
mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
{
	MonoDebugSourceLocation *location;

	mono_debugger_lock ();
	if (minfo->handle->ppdb)
		location = mono_ppdb_lookup_location (minfo, il_offset);
	else
		location = mono_debug_symfile_lookup_location (minfo, il_offset);
	mono_debugger_unlock ();
	return location;
}
Example #24
0
void
mono_debug_domain_create (MonoDomain *domain)
{
	MonoDebugDataTable *table;

	if (!mono_debug_initialized)
		return;

	mono_debugger_lock ();

	table = create_data_table (domain);

	mono_debugger_unlock ();
}
Example #25
0
/**
 * mono_debug_print_stack_frame:
 * \param native_offset Native offset within the \p method's machine code.
 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
 * used if you only want to use the location to print a stack frame.
 */
gchar *
mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
{
	MonoDebugSourceLocation *location;
	gchar *fname, *ptr, *res;
	int offset;

	fname = mono_method_full_name (method, TRUE);
	for (ptr = fname; *ptr; ptr++) {
		if (*ptr == ':') *ptr = '.';
	}

	location = mono_debug_lookup_source_location (method, native_offset, domain);

	if (!location) {
		if (mono_debug_initialized) {
			mono_debugger_lock ();
			offset = il_offset_from_address (method, domain, native_offset);
			mono_debugger_unlock ();
		} else {
			offset = -1;
		}

		if (offset < 0 && get_seq_point)
			offset = get_seq_point (domain, method, native_offset);

		if (offset < 0)
			res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
		else {
			char *mvid = mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method->klass)->heap_guid.data);
			char *aotid = mono_runtime_get_aotid ();
			if (aotid)
				res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
			else
				res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);

			g_free (aotid);
			g_free (mvid);
		}
		g_free (fname);
		return res;
	}

	res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
			       location->source_file, location->row);

	g_free (fname);
	mono_debug_free_source_location (location);
	return res;
}
Example #26
0
MonoDebugMethodAddressList *
mono_debug_lookup_method_addresses (MonoMethod *method)
{
	MonoDebugMethodAddressList *info;
	MonoDebugMethodHeader *header = NULL;
	struct LookupMethodAddressData data;
	MonoMethod *declaring;
	int count, size;
	GSList *list;
	guint8 *ptr;

	g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));

	mono_debugger_lock ();

	declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;

	data.method = declaring;
	data.result = NULL;

	g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
	header = data.result;

	if (!header) {
		mono_debugger_unlock ();
		return NULL;
	}

	count = g_slist_length (header->address_list) + 1;
	size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);

	info = g_malloc0 (size);
	info->size = size;
	info->count = count;

	ptr = info->data;

	WRITE_UNALIGNED (gpointer, ptr, header);
	ptr += sizeof (gpointer);

	for (list = header->address_list; list; list = list->next) {
		WRITE_UNALIGNED (gpointer, ptr, list->data);
		ptr += sizeof (gpointer);
	}

	mono_debugger_unlock ();
	return info;
}
Example #27
0
gboolean
mono_debug_image_has_debug_info (MonoImage *image)
{
	LookupImageData data;

	if (!mono_debug_handles)
		return FALSE;

	memset (&data, 0, sizeof (data));
	data.image = image;

	mono_debugger_lock ();
	g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
	mono_debugger_unlock ();
	return data.found;
}
Example #28
0
MonoSymbolFile *
mono_debug_open_mono_symbols (MonoDebugHandle *handle, const uint8_t *raw_contents,
			      int size, gboolean in_the_debugger)
{
	MonoSymbolFile *symfile;

	mono_debugger_lock ();
	symfile = g_new0 (MonoSymbolFile, 1);

	if (raw_contents != NULL) {
		unsigned char *p;
		symfile->raw_contents_size = size;
		symfile->raw_contents = p = (unsigned char *)g_malloc (size);
		memcpy (p, raw_contents, size);
		symfile->filename = g_strdup_printf ("LoadedFromMemory");
		symfile->was_loaded_from_memory = TRUE;
	} else {
		MonoFileMap *f;

		symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
		symfile->was_loaded_from_memory = FALSE;
		if ((f = mono_file_map_open (symfile->filename))) {
			symfile->raw_contents_size = mono_file_map_size (f);
			if (symfile->raw_contents_size == 0) {
				if (!in_the_debugger)
					g_warning ("stat of %s failed: %s",
						   symfile->filename,  g_strerror (errno));
			} else {
				symfile->raw_contents = (const unsigned char *)mono_file_map (symfile->raw_contents_size, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (f), 0, &symfile->raw_contents_handle);
			}

			mono_file_map_close (f);
		}
	}
	
	if (load_symfile (handle, symfile, in_the_debugger)) {
		mono_debugger_unlock ();
		return symfile;
	} else if (!in_the_debugger) {
		mono_debug_close_mono_symbol_file (symfile);
		mono_debugger_unlock ();
		return NULL;
	}

	mono_debugger_unlock ();
	return symfile;
}
Example #29
0
void
mono_debug_domain_create (MonoDomain *domain)
{
	MonoDebugDataTable *table;

	if (!mono_debug_initialized)
		return;

	mono_debugger_lock ();

	table = create_data_table (domain);

	mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
			     mono_domain_get_id (domain));

	mono_debugger_unlock ();
}
Example #30
0
MonoDebugMethodInfo *
mono_debug_symfile_lookup_method (MonoDebugHandle *handle, MonoMethod *method)
{
    MonoSymbolFileMethodEntry *first_ie, *ie;
    MonoDebugMethodInfo *minfo;
    MonoSymbolFile *symfile = handle->symfile;

    if (!symfile->method_hash)
        return NULL;

    if (handle->image != mono_class_get_image (mono_method_get_class (method)))
        return NULL;

    mono_debugger_lock ();

    minfo = g_hash_table_lookup (symfile->method_hash, method);
    if (minfo) {
        mono_debugger_unlock ();
        return minfo;
    }

    first_ie = (MonoSymbolFileMethodEntry *)
               (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));

    ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie,
                  read32(&(symfile->offset_table->_method_count)),
                  sizeof (MonoSymbolFileMethodEntry), compare_method);

    if (!ie) {
        mono_debugger_unlock ();
        return NULL;
    }

    minfo = g_new0 (MonoDebugMethodInfo, 1);
    minfo->index = (ie - first_ie) + 1;
    minfo->method = method;
    minfo->handle = handle;

    minfo->data_offset = read32 (&(ie->_data_offset));
    minfo->lnt_offset = read32 (&(ie->_line_number_table));

    g_hash_table_insert (symfile->method_hash, method, minfo);

    mono_debugger_unlock ();
    return minfo;
}