2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / debug-mono-symfile.c
index 74b5610ce7b4edb44442fd5f72d1cbbff1ce4703..05ed1c0bad97218a4d23474269db2ed3076c6db0 100644 (file)
@@ -1,7 +1,11 @@
 #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/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
-{
-       int fd;
-       int error;
-       char *file_name;
-       char *source_file;
-       guint32 string_table_size;
-       guint32 string_offset_size;
-       MonoImage *image;
-       GHashTable *method_table;
-       GHashTable *method_hash;
-       MonoSymbolFileOffsetTable *offset_table;
-       GPtrArray *range_table;
-};
-
-typedef struct
-{
-       MonoMethod *method;
-       MonoDebugMethodInfo *minfo;
-       MonoSymbolFileMethodEntry *entry;
-       guint32 method_name_offset;
-       guint32 index;
-       gchar *name;
-} MonoSymbolFileMethodEntryPriv;
-
-static int write_string_table (MonoSymbolFile *symfile);
-static int create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings);
-static void close_symfile (MonoSymbolFile *symfile);
+#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)
 {
-       g_free (minfo->jit);
        g_free (minfo);
 }
 
+static gchar *
+get_class_name (MonoClass *klass)
+{
+       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;
+       }
+
+       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;
-
-       /*
-        * Read method table.
-        *
-        */
-
-       priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-                                                   (GDestroyNotify) g_free);
-       priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-                                                  (GDestroyNotify) free_method_info);
+       guid = mono_guid_to_string ((const guint8 *) ptr);
+       ptr += 16;
 
-       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;
-               MonoDebugMethodInfo *minfo;
-
-               if (!method)
-                       continue;
-
-               minfo = g_new0 (MonoDebugMethodInfo, 1);
-               minfo->file_offset = ((const char *) me) - start;
-               minfo->method = method;
-               minfo->symfile = symfile;
-               minfo->num_il_offsets = me->num_line_numbers;
-               minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
-                       (symfile->raw_contents + me->line_number_table_offset);
-
-               mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
-               mep->method = method;
-               mep->minfo = minfo;
-               mep->entry = me;
-               mep->index = i;
-
-               mep->method_name_offset = priv->string_table_size;
-               mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
-                                            method->klass->name, method->name);
-               priv->string_table_size += strlen (mep->name) + 1;
-
-               g_hash_table_insert (priv->method_table, method, mep);
-               g_hash_table_insert (priv->method_hash, method, minfo);
+       if (strcmp (handle->image->guid, guid)) {
+               g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
+                          handle->image_file);
+               return FALSE;
        }
 
-       if (!write_string_table (symfile))
-               return FALSE;
+       symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
+
+       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->image_file = g_strdup (image->name);
-       symfile->raw_contents = ptr;
-       symfile->raw_contents_size = file_size;
 
-       symfile->_priv = priv = g_new0 (MonoSymbolFilePriv, 1);
+       symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
 
-       priv->fd = fd;
-       priv->image = image;
-       priv->file_name = g_strdup (filename);
-
-       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 (priv->method_hash) {
-               g_hash_table_destroy (priv->method_hash);
-               priv->method_hash = NULL;
-       }
-
-       if (symfile->is_dynamic)
-               unlink (priv->file_name);
-
-       if (symfile->image_file) {
-               g_free (symfile->image_file);
-               symfile->image_file = NULL;
-       }
-
-       if (priv->file_name) {
-               g_free (priv->file_name);
-               priv->file_name = NULL;
-       }
-
-       priv->error = FALSE;
-}
-
 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;
-}
+       if (rptr)
+               *rptr = ptr;
 
-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 (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;
 }
 
-static void
-update_method_func (gpointer key, gpointer value, gpointer user_data)
+gint32
+_mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offset)
 {
-       MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
-       MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
-       MonoSymbolFileMethodAddress *address;
-       MonoSymbolFileLineNumberEntry *lne;
-       MonoDebugRangeInfo *range;
        int i;
 
-       if (!mep->minfo) {
-               mep->minfo = g_hash_table_lookup (symfile->_priv->method_hash, mep->method);
-               if (!mep->minfo)
-                       return;
-       }
-
-       if (!mep->minfo->jit)
-               return;
-
-       address = (MonoSymbolFileMethodAddress *)
-               (symfile->address_table + mep->entry->address_table_offset);
-
-       address->is_valid = TRUE;
-       address->start_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start);
-       address->end_address = GPOINTER_TO_UINT (mep->minfo->jit->code_start + mep->minfo->jit->code_size);
-
-       range = g_new0 (MonoDebugRangeInfo, 1);
-       range->start_address = address->start_address;
-       range->end_address = address->end_address;
-       range->file_offset = mep->minfo->file_offset;
-
-       g_ptr_array_add (symfile->_priv->range_table, range);
-
-       lne = (MonoSymbolFileLineNumberEntry *)
-               (symfile->raw_contents + mep->entry->line_number_table_offset);
-
-       for (i = 0; i < mep->entry->num_line_numbers; i++, lne++) {
-               int j;
-
-               if (i == 0) {
-                       address->line_addresses [i] = 0;
-                       continue;
-               } else if (lne->offset == 0) {
-                       address->line_addresses [i] = mep->minfo->jit->prologue_end;
-                       continue;
-               }
-
-               address->line_addresses [i] = mep->minfo->jit->code_size;
-
-               for (j = 0; j < mep->minfo->num_il_offsets; j++) {
-                       MonoSymbolFileLineNumberEntry *il = &mep->minfo->il_offsets [j];
-
-                       if (il->offset >= lne->offset) {
-                               address->line_addresses [i] = mep->minfo->jit->il_addresses [j];
-                               break;
-                       }
-               }
-       }
-}
-
-static gint
-range_table_compare_func (gconstpointer a, gconstpointer b)
-{
-       const MonoDebugRangeInfo *r1 = (const MonoDebugRangeInfo *) a;
-       const MonoDebugRangeInfo *r2 = (const MonoDebugRangeInfo *) b;
-
-       if (r1->start_address < r2->start_address)
+       if (!jit || !jit->line_numbers)
                return -1;
-       else if (r1->start_address > r2->start_address)
-               return 1;
-       else
-               return 0;
-}      
-
-void
-mono_debug_update_mono_symbol_file (MonoSymbolFile *symfile)
-{
-       int i;
-
-       if (!symfile->_priv->method_table)
-               return;
 
-       symfile->_priv->range_table = g_ptr_array_new ();
+       for (i = jit->line_numbers->len - 1; i >= 0; i--) {
+               MonoDebugLineNumberEntry lne = g_array_index (
+                       jit->line_numbers, MonoDebugLineNumberEntry, i);
 
-       if (!symfile->address_table)
-               symfile->address_table = g_malloc0 (symfile->address_table_size);
-
-       g_hash_table_foreach (symfile->_priv->method_table, update_method_func, symfile);
-
-       symfile->range_table_size = symfile->_priv->range_table->len * sizeof (MonoDebugRangeInfo);
-       symfile->range_table = g_malloc0 (symfile->range_table_size);
-
-       g_ptr_array_sort (symfile->_priv->range_table, range_table_compare_func);
-
-       for (i = 0; i < symfile->_priv->range_table->len; i++) {
-               MonoDebugRangeInfo *range = g_ptr_array_index (symfile->_priv->range_table, i);
-
-               symfile->range_table [i] = *range;
+               if (lne.il_offset <= il_offset)
+                       return lne.native_offset;
        }
 
-       g_ptr_array_free (symfile->_priv->range_table, TRUE);
-       symfile->_priv->range_table = NULL;
-}
-
-static void
-free_method_entry (MonoSymbolFileMethodEntryPriv *mep)
-{
-       g_free (mep->name);
-       g_free (mep->entry);
-       g_free (mep);
-}
-
-static void
-create_method (MonoSymbolFile *symfile, guint32 token, MonoMethod *method)
-{
-       MonoSymbolFileMethodEntryPriv *mep;
-       MonoDebugMethodInfo *minfo;
-
-       g_assert (method->klass->image == symfile->_priv->image);
-
-       mep = g_new0 (MonoSymbolFileMethodEntryPriv, 1);
-       mep->entry = g_new0 (MonoSymbolFileMethodEntry, 1);
-       mep->entry->token = token;
-       mep->entry->source_file_offset = symfile->_priv->offset_table->source_table_offset;
-
-       mep->method_name_offset = symfile->_priv->string_table_size;
-       mep->name = g_strdup_printf ("%s%s.%s", method->klass->name_space,
-                                    method->klass->name, method->name);
-       symfile->_priv->string_table_size += strlen (mep->name) + 1;
-
-       minfo = g_new0 (MonoDebugMethodInfo, 1);
-       minfo->method = method;
-       minfo->symfile = symfile;
-
-       mep->minfo = minfo;
-       mep->method = method;
-
-       symfile->_priv->offset_table->method_count++;
-
-       g_hash_table_insert (symfile->_priv->method_table, method, mep);
-       g_hash_table_insert (symfile->_priv->method_hash, method, minfo);
-}
-
-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;
-
-       mep->minfo->file_offset = lseek (symfile->_priv->fd, 0, SEEK_CUR);
-
-       if (write (symfile->_priv->fd, mep->entry, sizeof (MonoSymbolFileMethodEntry)) < 0) {
-               symfile->_priv->error = TRUE;
-               return;
-       }
-}
-
-static void
-write_line_numbers (gpointer key, gpointer value, gpointer user_data)
-{
-       MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
-       MonoSymbolFilePriv *priv = symfile->_priv;
-       MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
-       MonoSymbolFileLineNumberEntry lne;
-       const unsigned char *ip, *start, *end;
-       MonoMethodHeader *header;
-
-       if (priv->error)
-               return;
-
-       if ((mep->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
-           (mep->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
-           (mep->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
-               g_assert_not_reached ();
-
-       header = ((MonoMethodNormal *) mep->method)->header;
-
-       mep->entry->line_number_table_offset = lseek (priv->fd, 0, SEEK_CUR);
-       ++mep->entry->num_line_numbers;
-
-       lne.offset = 0;
-       lne.row = -1;
-
-       if (write (priv->fd, &lne, sizeof (MonoSymbolFileLineNumberEntry)) < 0) {
-               priv->error = TRUE;
-               return;
-       }
-
-       ip = start = header->code;
-       end = ip + header->code_size;
-
-       while (ip < end) {
-               gchar *line;
-
-               ++mep->entry->num_line_numbers;
-               lne.offset = ip - start;
-               lne.row = -1;
-
-               if (write (priv->fd, &lne, sizeof (MonoSymbolFileLineNumberEntry)) < 0) {
-                       priv->error = TRUE;
-                       return;
-               }
-
-               line = mono_disasm_code_one (NULL, mep->method, ip, &ip);
-               g_free (line);
-       }
-
-       mep->entry->address_table_offset = symfile->address_table_size;
-       mep->entry->address_table_size = sizeof (MonoSymbolFileMethodAddress) +
-               mep->entry->num_line_numbers * sizeof (guint32);
-
-       symfile->address_table_size += mep->entry->address_table_size;
-}
-
-static void
-create_methods (MonoSymbolFile *symfile)
-{
-       MonoImage *image = symfile->_priv->image;
-       MonoTableInfo *table = &image->tables [MONO_TABLE_METHOD];
-       int idx;
-
-       for (idx = 1; idx <= table->rows; idx++) {
-               guint32 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
-               MonoMethod *method = mono_get_method (image, token, NULL);
-
-               if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
-                   (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
-                   (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
-                       continue;
-
-               if (method->wrapper_type != MONO_WRAPPER_NONE)
-                       continue;
-
-               create_method (symfile, token, method);
-       }
-}
-
-static void
-load_line_numbers (gpointer key, gpointer value, gpointer user_data)
-{
-       MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
-       MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
-
-       mep->minfo->num_il_offsets = mep->entry->num_line_numbers;
-       mep->minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
-               (symfile->raw_contents + mep->entry->line_number_table_offset);
+       return -1;
 }
 
 static int
-create_symfile (MonoSymbolFile *symfile, gboolean emit_warnings)
+compare_method (const void *key, const void *object)
 {
-       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;
-       }
-
-       magic = MONO_SYMBOL_FILE_MAGIC;
-       if (write (priv->fd, &magic, sizeof (magic)) < 0)
-               return FALSE;
+       guint32 token = GPOINTER_TO_UINT (key);
+       MonoSymbolFileMethodIndexEntry *me = (MonoSymbolFileMethodIndexEntry*)object;
 
-       version = MONO_SYMBOL_FILE_VERSION;
-       if (write (priv->fd, &version, sizeof (version)) < 0)
-               return FALSE;
-
-       offset = lseek (priv->fd, 0, SEEK_CUR);
-
-       priv->offset_table = g_new0 (MonoSymbolFileOffsetTable, 1);
-       if (write (priv->fd, priv->offset_table, sizeof (MonoSymbolFileOffsetTable)) < 0)
-               return FALSE;
-
-       //
-       // 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;
-       }
-
-       //
-       // Create method table.
-       //
-
-       priv->method_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-                                                   (GDestroyNotify) free_method_entry);
-       priv->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-                                                  (GDestroyNotify) free_method_info);
-
-       create_methods (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;
-
-       //
-       // Write method table.
-       //
-
-       priv->offset_table->method_table_offset = lseek (priv->fd, 0, SEEK_CUR);
-
-       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;
-
-       //
-       // Load line number table.
-       //
-       g_hash_table_foreach (priv->method_table, load_line_numbers, symfile);
-       if (priv->error)
-               return FALSE;
-
-       if (!write_string_table (symfile))
-               return FALSE;
-
-       return TRUE;
+       return token - read32(&(me->_token));
 }
 
-MonoSymbolFile *
-mono_debug_create_mono_symbol_file (MonoImage *image)
+MonoDebugMethodInfo *
+mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
 {
-       MonoSymbolFile *symfile;
-
-       symfile = g_new0 (MonoSymbolFile, 1);
-       symfile->magic = MONO_SYMBOL_FILE_MAGIC;
-       symfile->version = MONO_SYMBOL_FILE_VERSION;
-       symfile->is_dynamic = TRUE;
-       symfile->image_file = g_strdup (image->name);
-
-       symfile->_priv = g_new0 (MonoSymbolFilePriv, 1);
-       symfile->_priv->image = image;
+       MonoSymbolFileMethodEntry *me;
+       MonoSymbolFileMethodIndexEntry *first_ie, *ie;
+       MonoDebugMethodInfo *minfo;
+       MonoSymbolFile *symfile = handle->symfile;
 
-       if (!create_symfile (symfile, TRUE)) {
-               mono_debug_close_mono_symbol_file (symfile);
+       if (!symfile->method_hash)
                return NULL;
-       }
-
-       return symfile;
-}
 
-MonoDebugMethodInfo *
-mono_debug_find_method (MonoSymbolFile *symfile, MonoMethod *method)
-{
-       return g_hash_table_lookup (symfile->_priv->method_hash, method);
-}
-
-static void
-write_method_name (gpointer key, gpointer value, gpointer user_data)
-{
-       MonoSymbolFile *symfile = (MonoSymbolFile *) user_data;
-       MonoSymbolFileMethodEntryPriv *mep = (MonoSymbolFileMethodEntryPriv *) value;
-       MonoSymbolFilePriv *priv = symfile->_priv;
-       guint8 *offset_ptr, *string_ptr;
-       guint32 offset;
+       if (handle->image != mono_class_get_image (mono_method_get_class (method)))
+               return NULL;
 
-       offset = mep->method_name_offset + priv->string_offset_size;
+       mono_loader_lock ();
+       first_ie = (MonoSymbolFileMethodIndexEntry *)
+               (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));
 
-       offset_ptr = symfile->string_table + mep->index * 4;
-       string_ptr = symfile->string_table + offset;
+       ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie,
+                                  read32(&(symfile->offset_table->_method_count)),
+                                  sizeof (MonoSymbolFileMethodIndexEntry), compare_method);
 
-       *((guint32 *) offset_ptr) = offset;
-       strcpy (string_ptr, mep->name);
-}
+       if (!ie) {
+               mono_loader_unlock ();
+               return NULL;
+       }
 
-static int
-write_string_table (MonoSymbolFile *symfile)
-{
-       MonoSymbolFilePriv *priv = symfile->_priv;
+       me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(ie->_file_offset)));
 
-       priv->string_offset_size = priv->offset_table->method_count * 4;
+       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;
 
-       symfile->string_table_size = priv->string_table_size + priv->string_offset_size;
-       symfile->string_table = g_malloc0 (symfile->string_table_size);
+       g_hash_table_insert (symfile->method_hash, method, minfo);
 
-       g_hash_table_foreach (symfile->_priv->method_table, write_method_name, symfile);
-       return TRUE;
+       mono_loader_unlock ();
+       return minfo;
 }