2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / debug-mono-symfile.c
index b5f107f13ef75ff80b1871ebd6e62430d4c0f3db..05ed1c0bad97218a4d23474269db2ed3076c6db0 100644 (file)
@@ -1,8 +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>
@@ -13,6 +16,9 @@
 #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>
@@ -31,21 +37,25 @@ free_method_info (MonoDebugMethodInfo *minfo)
 static gchar *
 get_class_name (MonoClass *klass)
 {
-       if (klass->nested_in) {
-               gchar *parent_name = get_class_name (klass->nested_in);
-               gchar *name = g_strdup_printf ("%s.%s", parent_name, klass->name);
+       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;
        }
 
-       return g_strdup_printf ("%s%s%s", klass->name_space,
-                               klass->name_space [0] ? "." : "", klass->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 (MonoDebugHandle *handle, MonoSymbolFile *symfile)
 {
        const char *ptr, *start;
+       gchar *guid;
        guint64 magic;
        long version;
 
@@ -56,7 +66,7 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
        magic = read64(ptr);
        ptr += sizeof(guint64);
        if (magic != MONO_SYMBOL_FILE_MAGIC) {
-               g_warning ("Symbol file %s is not a mono symbol file", handle->image_file);
+               g_warning ("Symbol file %s is not a mono symbol file", symfile->filename);
                return FALSE;
        }
 
@@ -64,56 +74,62 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
        ptr += sizeof(guint32);
        if (version != MONO_SYMBOL_FILE_VERSION) {
                g_warning ("Symbol file %s has incorrect version "
-                          "(expected %d, got %ld)", handle->image_file,
+                          "(expected %d, got %ld)", symfile->filename,
                           MONO_SYMBOL_FILE_VERSION, version);
                return FALSE;
        }
 
-       symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
+       guid = mono_guid_to_string ((const guint8 *) ptr);
+       ptr += 16;
 
-       symfile->method_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-                                                            (GDestroyNotify) free_method_info);
+       if (strcmp (handle->image->guid, guid)) {
+               g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
+                          handle->image_file);
+               return FALSE;
+       }
 
-       return TRUE;
-}
+       symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
 
-static gconstpointer
-open_symfile (MonoImage *image, guint32 *size)
-{
-       MonoTableInfo *table = &image->tables [MONO_TABLE_MANIFESTRESOURCE];
-       guint32 i;
-       guint32 cols [MONO_MANIFEST_SIZE];
-       const char *val;
-
-       for (i = 0; i < table->rows; ++i) {
-               mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
-               val = mono_metadata_string_heap (image, cols [MONO_MANIFEST_NAME]);
-               if (!strcmp (val, "MonoSymbolFile"))
-                       break;
-       }
-       if (i == table->rows)
-               return NULL;
-       g_assert (!cols [MONO_MANIFEST_IMPLEMENTATION]);
+       symfile->method_hash = g_hash_table_new_full (
+               g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_method_info);
 
-       return mono_image_get_resource (image, cols [MONO_MANIFEST_OFFSET], size);
+       return TRUE;
 }
 
 MonoSymbolFile *
 mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean create_symfile)
 {
        MonoSymbolFile *symfile;
+       FILE* f;
 
+       mono_loader_lock ();
        symfile = g_new0 (MonoSymbolFile, 1);
 
-       symfile->raw_contents = open_symfile (handle->image, &symfile->raw_contents_size);
-
-       if (load_symfile (handle, symfile))
+       symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
+
+       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) {
+       else if (!create_symfile) {
                mono_debug_close_mono_symbol_file (symfile);
+               mono_loader_unlock ();
                return NULL;
        }
 
+       mono_loader_unlock ();
        return symfile;
 }
 
@@ -123,17 +139,41 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
        if (!symfile)
                return;
 
+       mono_loader_lock ();
        if (symfile->method_hash)
                g_hash_table_destroy (symfile->method_hash);
 
+       if (symfile->raw_contents)
+               mono_raw_buffer_free ((gpointer) symfile->raw_contents);
+       
        g_free (symfile);
+       mono_loader_unlock ();
+}
+
+static int
+read_leb128 (const char *ptr, const char **rptr)
+{
+       int ret = 0;
+       int shift = 0;
+       char b;
+
+       do {
+               b = *ptr++;
+                               
+               ret = ret | ((b & 0x7f) << shift);
+               shift += 7;
+       } while ((b & 0x80) == 0x80);
+
+       if (rptr)
+               *rptr = ptr;
+
+       return ret;
 }
 
 static gchar *
 read_string (const char *ptr)
 {
-       int len = *((guint32 *) ptr);
-       ptr += sizeof(guint32);
+       int len = read_leb128 (ptr, &ptr);
        return g_filename_from_utf8 (ptr, len, NULL, NULL, NULL);
 }
 
@@ -147,12 +187,17 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu
        const char *ptr;
        int i;
 
-       if (!symfile->method_hash)
+       mono_loader_lock ();
+       if (!symfile->method_hash) {
+               mono_loader_unlock ();
                return NULL;
+       }
 
        minfo = g_hash_table_lookup (symfile->method_hash, method);
-       if (!minfo)
+       if (!minfo) {
+               mono_loader_unlock ();
                return NULL;
+       }
 
        if (read32(&(minfo->entry->_source_index))) {
                int offset = read32(&(symfile->offset_table->_source_table_offset)) +
@@ -172,6 +217,7 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu
 
                if (line_number) {
                        *line_number = read32(&(lne->_row));
+                       mono_loader_unlock ();
                        if (source_file)
                                return source_file;
                        else
@@ -179,11 +225,16 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu
                } else if (source_file) {
                        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", read32(&(lne->_row)));
+               }
        }
 
+       mono_loader_unlock ();
        return NULL;
 }
 
@@ -199,8 +250,8 @@ _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offs
                MonoDebugLineNumberEntry lne = g_array_index (
                        jit->line_numbers, MonoDebugLineNumberEntry, i);
 
-               if (lne.offset <= il_offset)
-                       return lne.address;
+               if (lne.il_offset <= il_offset)
+                       return lne.native_offset;
        }
 
        return -1;
@@ -226,18 +277,21 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
        if (!symfile->method_hash)
                return NULL;
 
-       if (handle->image != method->klass->image)
+       if (handle->image != mono_class_get_image (mono_method_get_class (method)))
                return NULL;
 
+       mono_loader_lock ();
        first_ie = (MonoSymbolFileMethodIndexEntry *)
                (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));
 
-       ie = bsearch (GUINT_TO_POINTER (method->token), first_ie,
+       ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie,
                                   read32(&(symfile->offset_table->_method_count)),
                                   sizeof (MonoSymbolFileMethodIndexEntry), compare_method);
 
-       if (!ie)
+       if (!ie) {
+               mono_loader_unlock ();
                return NULL;
+       }
 
        me = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(ie->_file_offset)));
 
@@ -252,5 +306,6 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
 
        g_hash_table_insert (symfile->method_hash, method, minfo);
 
+       mono_loader_unlock ();
        return minfo;
 }