#include <config.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
#include <string.h>
#include <signal.h>
+#include <sys/param.h>
+#include <sys/stat.h>
#include <mono/metadata/metadata.h>
+#include <mono/metadata/tabledefs.h>
#include <mono/metadata/rawbuffer.h>
#include <mono/metadata/tokentype.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/exception.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/mono-endian.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include <fcntl.h>
#include <unistd.h>
-struct MonoSymbolFilePriv
+#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 void
+free_method_info (MonoDebugMethodInfo *minfo)
{
- int fd;
- int error;
- char *file_name;
- char *source_file;
- MonoImage *image;
- GHashTable *method_table;
- GHashTable *method_hash;
- MonoSymbolFileOffsetTable *offset_table;
-};
-
-typedef struct
+ g_free (minfo);
+}
+
+static gchar *
+get_class_name (MonoClass *klass)
{
- MonoMethod *method;
- MonoDebugMethodInfo *minfo;
- MonoSymbolFileMethodEntry *entry;
-} MonoSymbolFileMethodEntryPriv;
+ MonoClass *nested_in = mono_class_get_nesting_type (klass);
+ const char *name_space;
+ if (nested_in) {
+ gchar *parent_name = get_class_name (nested_in);
+ gchar *name = g_strdup_printf ("%s.%s", parent_name, mono_class_get_name (klass));
+ g_free (parent_name);
+ return name;
+ }
-static int create_symfile (MonoSymbolFile *symfile, GHashTable *method_hash, gboolean emit_warnings);
-static void close_symfile (MonoSymbolFile *symfile);
+ name_space = mono_class_get_namespace (klass);
+ return g_strdup_printf ("%s%s%s", name_space,
+ name_space [0] ? "." : "", mono_class_get_name (klass));
+}
static int
-load_symfile (MonoSymbolFile *symfile)
+load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
{
- MonoSymbolFilePriv *priv = symfile->_priv;
- MonoSymbolFileMethodEntry *me;
const char *ptr, *start;
+ gchar *guid;
guint64 magic;
long version;
- int i;
ptr = start = symfile->raw_contents;
+ if (!ptr)
+ return FALSE;
- magic = *((guint64 *) ptr)++;
+ magic = read64(ptr);
+ ptr += sizeof(guint64);
if (magic != MONO_SYMBOL_FILE_MAGIC) {
- g_warning ("Symbol file %s has is not a mono symbol file", priv->file_name);
+ g_warning ("Symbol file %s is not a mono symbol file", symfile->filename);
return FALSE;
}
- version = *((guint32 *) ptr)++;
+ version = read32(ptr);
+ ptr += sizeof(guint32);
if (version != MONO_SYMBOL_FILE_VERSION) {
- g_warning ("Symbol file %s has incorrect line number table version "
- "(expected %d, got %ld)", priv->file_name,
+ g_warning ("Symbol file %s has incorrect version "
+ "(expected %d, got %ld)", symfile->filename,
MONO_SYMBOL_FILE_VERSION, version);
return FALSE;
}
- priv->offset_table = (MonoSymbolFileOffsetTable *) ptr;
- symfile->address_table_size = priv->offset_table->address_table_size;
+ guid = mono_guid_to_string ((const guint8 *) ptr);
+ ptr += 16;
- /*
- * Read method table.
- *
- */
-
- priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) g_free);
-
- ptr = symfile->raw_contents + priv->offset_table->method_table_offset;
- me = (MonoSymbolFileMethodEntry *) ptr;
-
- for (i = 0; i < priv->offset_table->method_count; i++, me++) {
- MonoMethod *method = mono_get_method (priv->image, me->token, NULL);
- MonoSymbolFileMethodEntryPriv *mep;
-
- if (!method)
- continue;
+ if (strcmp (handle->image->guid, guid)) {
+ g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
+ handle->image_file);
+ return FALSE;
+ }
- mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
- mep->method = method;
- mep->entry = me;
+ symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
- g_hash_table_insert (priv->method_table, method, mep);
- }
+ symfile->method_hash = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_method_info);
return TRUE;
}
MonoSymbolFile *
-mono_debug_open_mono_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
+mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean create_symfile)
{
MonoSymbolFile *symfile;
- MonoSymbolFilePriv *priv;
- off_t file_size;
- void *ptr;
- int fd;
-
- fd = open (filename, O_RDONLY);
- if (fd == -1) {
- if (emit_warnings)
- g_warning ("Can't open symbol file: %s", filename);
- return NULL;
- }
-
- file_size = lseek (fd, 0, SEEK_END);
- lseek (fd, 0, SEEK_SET);
-
- if (file_size == (off_t) -1) {
- if (emit_warnings)
- g_warning ("Can't get size of symbol file: %s", filename);
- return NULL;
- }
-
- ptr = mono_raw_buffer_load (fd, FALSE, 0, file_size);
- if (!ptr) {
- if (emit_warnings)
- g_warning ("Can't read symbol file: %s", filename);
- return NULL;
- }
+ FILE* f;
+ mono_loader_lock ();
symfile = g_new0 (MonoSymbolFile, 1);
- symfile->magic = MONO_SYMBOL_FILE_MAGIC;
- symfile->version = MONO_SYMBOL_FILE_VERSION;
- symfile->raw_contents = ptr;
- symfile->raw_contents_size = file_size;
-
- symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
- priv->fd = fd;
- priv->image = image;
- priv->file_name = g_strdup (filename);
+ symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
- if (!load_symfile (symfile)) {
+ if ((f = fopen (symfile->filename, "rb")) > 0) {
+ struct stat stat_buf;
+
+ if (fstat (fileno (f), &stat_buf) < 0) {
+ g_warning ("stat of %s failed: %s", symfile->filename, g_strerror (errno));
+ } else {
+ symfile->raw_contents_size = stat_buf.st_size;
+ symfile->raw_contents = mono_raw_buffer_load (fileno (f), FALSE, 0, stat_buf.st_size);
+ }
+
+ fclose (f);
+ }
+
+ if (load_symfile (handle, symfile)) {
+ mono_loader_unlock ();
+ return symfile;
+ } else if (!create_symfile) {
mono_debug_close_mono_symbol_file (symfile);
+ mono_loader_unlock ();
return NULL;
}
+ mono_loader_unlock ();
return symfile;
}
-static void
-close_symfile (MonoSymbolFile *symfile)
-{
- MonoSymbolFilePriv *priv = symfile->_priv;
-
- if (symfile->raw_contents) {
- mono_raw_buffer_free (symfile->raw_contents);
- symfile->raw_contents = NULL;
- }
-
- if (priv->fd) {
- close (priv->fd);
- priv->fd = 0;
- }
-
- if (priv->method_table) {
- g_hash_table_destroy (priv->method_table);
- priv->method_table = NULL;
- }
-
- if (symfile->is_dynamic)
- unlink (priv->file_name);
-
- priv->error = FALSE;
-
- if (priv->file_name) {
- g_free (priv->file_name);
- priv->file_name = NULL;
- }
-}
-
void
mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
{
if (!symfile)
return;
- close_symfile (symfile);
+ mono_loader_lock ();
+ if (symfile->method_hash)
+ g_hash_table_destroy (symfile->method_hash);
- g_free (symfile->_priv->source_file);
- g_free (symfile->_priv);
+ if (symfile->raw_contents)
+ mono_raw_buffer_free ((gpointer) symfile->raw_contents);
+
g_free (symfile);
+ mono_loader_unlock ();
}
static int
-read_7bit_encoded_int (const char **ptr)
+read_leb128 (const char *ptr, const char **rptr)
{
int ret = 0;
int shift = 0;
char b;
do {
- b = *(*ptr)++;
+ b = *ptr++;
ret = ret | ((b & 0x7f) << shift);
shift += 7;
} while ((b & 0x80) == 0x80);
- return ret;
-}
-
-static int
-write_7bit_encoded_int (int fd, int value)
-{
- do {
- int high = (value >> 7) & 0x01ffffff;
- char b = (char)(value & 0x7f);
-
- if (high != 0)
- b = (char)(b | 0x80);
+ if (rptr)
+ *rptr = ptr;
- if (write (fd, &b, 1) < 0)
- return FALSE;
-
- value = high;
- } while (value != 0);
- return TRUE;
-}
-
-static int
-write_string (int fd, const char *string)
-{
- if (!write_7bit_encoded_int (fd, strlen (string)))
- return FALSE;
-
- if (write (fd, string, strlen (string)) < 0)
- return FALSE;
-
- return TRUE;
+ return ret;
}
static gchar *
read_string (const char *ptr)
{
- int len = read_7bit_encoded_int (&ptr);
- gchar *retval;
-
- retval = g_malloc0 (len+1);
- memcpy (retval, ptr, len);
- return retval;
+ int len = read_leb128 (ptr, &ptr);
+ return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
}
gchar *
mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, guint32 offset,
guint32 *line_number)
{
- MonoSymbolFilePriv *priv = symfile->_priv;
MonoSymbolFileLineNumberEntry *lne;
- MonoSymbolFileMethodEntryPriv *mep;
+ MonoDebugMethodInfo *minfo;
gchar *source_file = NULL;
const char *ptr;
int i;
- if (!priv->method_table || symfile->is_dynamic)
+ mono_loader_lock ();
+ if (!symfile->method_hash) {
+ mono_loader_unlock ();
return NULL;
+ }
- mep = g_hash_table_lookup (priv->method_table, method);
- if (!mep)
+ minfo = g_hash_table_lookup (symfile->method_hash, method);
+ if (!minfo) {
+ mono_loader_unlock ();
return NULL;
+ }
+
+ if (read32(&(minfo->entry->_source_index))) {
+ int offset = read32(&(symfile->offset_table->_source_table_offset)) +
+ (read32(&(minfo->entry->_source_index)) - 1) * sizeof (MonoSymbolFileSourceEntry);
+ MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (symfile->raw_contents + offset);
- if (mep->entry->source_file_offset)
- source_file = read_string (symfile->raw_contents + mep->entry->source_file_offset);
+ source_file = read_string (symfile->raw_contents + read32(&(se->_name_offset)));
+ }
- ptr = symfile->raw_contents + mep->entry->line_number_table_offset;
+ ptr = symfile->raw_contents + read32(&(minfo->entry->_line_number_table_offset));
lne = (MonoSymbolFileLineNumberEntry *) ptr;
- for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
- if (lne->offset < offset)
+ for (i = 0; i < read32(&(minfo->entry->_num_line_numbers)); i++, lne++) {
+ if (read32(&(lne->_offset)) < offset)
continue;
if (line_number) {
- *line_number = lne->row;
+ *line_number = read32(&(lne->_row));
+ mono_loader_unlock ();
if (source_file)
return source_file;
else
return NULL;
} else if (source_file) {
- gchar *retval = g_strdup_printf ("%s:%d", source_file, lne->row);
+ gchar *retval = g_strdup_printf ("%s:%d", source_file, read32(&(lne->_row)));
g_free (source_file);
+ mono_loader_unlock ();
+ return retval;
+ } else {
+ gchar* retval = g_strdup_printf ("%d", read32(&(lne->_row)));
+ mono_loader_unlock ();
return retval;
- } else
- return g_strdup_printf ("%d", lne->row);
+ }
}
+ mono_loader_unlock ();
return NULL;
}
-struct MyData
-{
- MonoSymbolFile *symfile;
- GHashTable *method_hash;
-};
-
-static void
-update_method_func (gpointer key, gpointer value, gpointer user_data)
+gint32
+_mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offset)
{
- struct MyData *mydata = (struct MyData *) user_data;
- MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
- MonoSymbolFileMethodAddress *address;
- MonoSymbolFileLineNumberEntry *lne;
int i;
- if (!mep->minfo) {
- mep->minfo = g_hash_table_lookup (mydata->method_hash, mep->method);
- if (!mep->minfo)
- return;
- }
-
- address = (MonoSymbolFileMethodAddress *)
- (mydata->symfile->address_table + mep->entry->address_table_offset);
-
- address->is_valid = TRUE;
- address->start_address = GPOINTER_TO_UINT (mep->minfo->code_start);
- address->end_address = GPOINTER_TO_UINT (mep->minfo->code_start + mep->minfo->code_size);
-
- lne = (MonoSymbolFileLineNumberEntry *)
- (mydata->symfile->raw_contents + mep->entry->line_number_table_offset);
+ if (!jit || !jit->line_numbers)
+ return -1;
- for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
- int j;
+ for (i = jit->line_numbers->len - 1; i >= 0; i--) {
+ MonoDebugLineNumberEntry lne = g_array_index (
+ jit->line_numbers, MonoDebugLineNumberEntry, i);
- if (i == 0) {
- address->line_addresses [i] = 0;
- continue;
- } else if (lne->offset == 0) {
- address->line_addresses [i] = mep->minfo->prologue_end;
- continue;
- }
-
- address->line_addresses [i] = mep->minfo->code_size;
-
- for (j = 0; j < mep->minfo->num_il_offsets; j++) {
- MonoDebugILOffsetInfo *il = &mep->minfo->il_offsets [j];
-
- if (il->offset >= lne->offset) {
- address->line_addresses [i] = il->address;
- break;
- }
- }
+ if (lne.il_offset <= il_offset)
+ return lne.native_offset;
}
-}
-
-void
-mono_debug_update_mono_symbol_file (MonoSymbolFile *symfile, GHashTable *method_hash)
-{
- g_message (G_STRLOC);
- if (symfile->is_dynamic) {
- close_symfile (symfile);
-
- symfile->_priv->method_hash = method_hash;
-
- if (!create_symfile (symfile, method_hash, TRUE)) {
- symfile->_priv->method_hash = NULL;
- close_symfile (symfile);
- return;
- }
-
- symfile->_priv->method_hash = NULL;
- }
-
- if (symfile->_priv->method_table) {
- struct MyData mydata = { symfile, method_hash };
-
- if (!symfile->address_table)
- symfile->address_table = g_malloc0 (symfile->address_table_size);
-
- g_hash_table_foreach (symfile->_priv->method_table, update_method_func, &mydata);
- }
-}
-
-static void
-free_method_entry (MonoSymbolFileMethodEntryPriv *mep)
-{
- g_free (mep->entry);
- g_free (mep);
-}
-
-static void
-create_method (gpointer key, gpointer value, gpointer user_data)
-{
- MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
- MonoMethod *method = (MonoMethod *) value;
- MonoSymbolFileMethodEntryPriv *mep;
-
- if (method->klass->image != symfile->_priv->image)
- return;
-
- mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
- mep->entry = g_new0 (MonoSymbolFileMethodEntry, 1);
- mep->entry->token = GPOINTER_TO_UINT (key);
- mep->entry->source_file_offset = symfile->_priv->offset_table->source_table_offset;
-
- mep->method = method;
-
- if (!symfile->_priv->method_hash)
- mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, method);
-
- symfile->_priv->offset_table->method_count++;
-
- g_hash_table_insert (symfile->_priv->method_table, method, mep);
-}
-
-static void
-write_method (gpointer key, gpointer value, gpointer user_data)
-{
- MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
- MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
-
- if (symfile->_priv->error)
- return;
-
- if (write (symfile->_priv->fd, mep->entry, sizeof (MonoSymbolFileMethodEntry)) < 0) {
- symfile->_priv->error = TRUE;
- return;
- }
+ return -1;
}
-static void
-write_line_numbers (gpointer key, gpointer value, gpointer user_data)
+static int
+compare_method (const void *key, const void *object)
{
- MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
- MonoSymbolFilePriv *priv = symfile->_priv;
- MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
- MonoSymbolFileLineNumberEntry lne;
- int i;
-
- if (priv->error)
- return;
-
- if (!mep->minfo) {
- mep->entry->address_table_size = sizeof (MonoSymbolFileMethodAddress);
- symfile->address_table_size += mep->entry->address_table_size;
- return;
- }
-
- mep->entry->num_line_numbers = mep->minfo->num_il_offsets;
- mep->entry->line_number_table_offset = lseek (priv->fd, 0, SEEK_CUR);
-
- for (i = 0; i < mep->minfo->num_il_offsets; i++) {
- MonoDebugILOffsetInfo *il = &mep->minfo->il_offsets [i];
-
- lne.row = il->line;
- lne.offset = il->offset;
-
- if (write (priv->fd, &lne, sizeof (MonoSymbolFileLineNumberEntry)) < 0) {
- priv->error = TRUE;
- return;
- }
- }
-
- mep->entry->address_table_offset = symfile->address_table_size;
- mep->entry->address_table_size = sizeof (MonoSymbolFileMethodAddress) +
- mep->entry->num_line_numbers * sizeof (guint32);
+ guint32 token = GPOINTER_TO_UINT (key);
+ MonoSymbolFileMethodIndexEntry *me = (MonoSymbolFileMethodIndexEntry*)object;
- symfile->address_table_size += mep->entry->address_table_size;
+ return token - read32(&(me->_token));
}
-static int
-create_symfile (MonoSymbolFile *symfile, GHashTable *method_hash, gboolean emit_warnings)
+MonoDebugMethodInfo *
+mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
{
- MonoSymbolFilePriv *priv = symfile->_priv;
- char *ptr;
- guint64 magic;
- long version;
- off_t offset;
-
- priv->fd = g_file_open_tmp (NULL, &priv->file_name, NULL);
- if (priv->fd == -1) {
- if (emit_warnings)
- g_warning ("Can't create symbol file");
- return FALSE;
- }
+ MonoSymbolFileMethodEntry *me;
+ MonoSymbolFileMethodIndexEntry *first_ie, *ie;
+ MonoDebugMethodInfo *minfo;
+ MonoSymbolFile *symfile = handle->symfile;
- magic = MONO_SYMBOL_FILE_MAGIC;
- if (write (priv->fd, &magic, sizeof (magic)) < 0)
- return FALSE;
+ if (!symfile->method_hash)
+ return NULL;
- version = MONO_SYMBOL_FILE_VERSION;
- if (write (priv->fd, &version, sizeof (version)) < 0)
- return FALSE;
+ if (handle->image != mono_class_get_image (mono_method_get_class (method)))
+ return NULL;
- offset = lseek (priv->fd, 0, SEEK_CUR);
+ mono_loader_lock ();
+ first_ie = (MonoSymbolFileMethodIndexEntry *)
+ (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));
- priv->offset_table = g_new0 (MonoSymbolFileOffsetTable, 1);
- if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
- return FALSE;
+ ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie,
+ read32(&(symfile->offset_table->_method_count)),
+ sizeof (MonoSymbolFileMethodIndexEntry), compare_method);
- //
- // Write source file table.
- //
- if (priv->source_file) {
- priv->offset_table->source_table_offset = lseek (priv->fd, 0, SEEK_CUR);
- if (!write_string (priv->fd, priv->source_file))
- return FALSE;
- priv->offset_table->source_table_size = lseek (priv->fd, 0, SEEK_CUR) -
- priv->offset_table->source_table_offset;
+ if (!ie) {
+ mono_loader_unlock ();
+ return NULL;
}
- //
- // Create method table.
- //
-
- priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) free_method_entry);
-
- g_hash_table_foreach (priv->image->method_cache, create_method, symfile);
-
- //
- // Write line numbers.
- //
-
- priv->offset_table->line_number_table_offset = lseek (priv->fd, 0, SEEK_CUR);
-
- g_hash_table_foreach (priv->method_table, write_line_numbers, symfile);
- if (priv->error)
- return FALSE;
-
- priv->offset_table->line_number_table_size = lseek (priv->fd, 0, SEEK_CUR) -
- priv->offset_table->line_number_table_offset;
+ me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(ie->_file_offset)));
- //
- // Write method table.
- //
+ minfo = g_new0 (MonoDebugMethodInfo, 1);
+ minfo->index = (ie - first_ie) + 1;
+ minfo->method = method;
+ minfo->handle = handle;
+ minfo->num_il_offsets = read32(&(me->_num_line_numbers));
+ minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
+ (symfile->raw_contents + read32(&(me->_line_number_table_offset)));
+ minfo->entry = me;
- priv->offset_table->method_table_offset = lseek (priv->fd, 0, SEEK_CUR);
+ g_hash_table_insert (symfile->method_hash, method, minfo);
- g_hash_table_foreach (priv->method_table, write_method, symfile);
- if (priv->error)
- return FALSE;
-
- priv->offset_table->method_table_size = lseek (priv->fd, 0, SEEK_CUR) -
- priv->offset_table->method_table_offset;
-
- //
- // Write offset table.
- //
-
- symfile->raw_contents_size = lseek (priv->fd, 0, SEEK_CUR);
- priv->offset_table->address_table_size = symfile->address_table_size;
-
- lseek (priv->fd, offset, SEEK_SET);
- if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
- return FALSE;
-
- lseek (priv->fd, symfile->raw_contents_size, SEEK_SET);
-
- ptr = mono_raw_buffer_load (priv->fd, TRUE, 0, symfile->raw_contents_size);
- if (!ptr)
- return FALSE;
-
- symfile->raw_contents = ptr;
-
- return TRUE;
-}
-
-MonoSymbolFile *
-mono_debug_create_mono_symbol_file (MonoImage *image, const char *source_file)
-{
- MonoSymbolFile *symfile;
-
- symfile = g_new0 (MonoSymbolFile, 1);
- symfile->magic = MONO_SYMBOL_FILE_MAGIC;
- symfile->version = MONO_SYMBOL_FILE_VERSION;
- symfile->is_dynamic = TRUE;
-
- symfile->_priv = g_new0 (MonoSymbolFilePriv, 1);
- symfile->_priv->image = image;
- symfile->_priv->source_file = g_strdup (source_file);
-
- return symfile;
+ mono_loader_unlock ();
+ return minfo;
}