Mon Apr 6 14:09:53 CEST 2009 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / debug-mono-symfile.c
index ee490a0c177b9752ad604793499c8d6b3748ca59..686468c30adee2528e823014f89ea41e017538b3 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * debug-mono-symfile.c: 
+ *
+ * Author:
+ *     Mono Project (http://www.mono-project.com)
+ *
+ * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
+ */
+
 #include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -10,7 +19,6 @@
 #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>
@@ -21,6 +29,7 @@
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/class-internals.h>
+#include <mono/utils/mono-mmap.h>
 
 #include <fcntl.h>
 #ifdef HAVE_UNISTD_H
@@ -38,23 +47,6 @@ free_method_info (MonoDebugMethodInfo *minfo)
        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 (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_debugger)
 {
@@ -80,12 +72,16 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_
        minor = read32(ptr);
        ptr += sizeof(guint32);
 
-       if ((major != MONO_SYMBOL_FILE_MAJOR_VERSION) || (minor != MONO_SYMBOL_FILE_MINOR_VERSION)) {
+       /*
+        * 50.0 is the frozen version for Mono 2.0.
+        *
+        * Nobody except me (Martin) is allowed to check the minor version.
+        */
+       if (major != MONO_SYMBOL_FILE_MAJOR_VERSION) {
                if (!in_the_debugger)
-                       g_warning ("Symbol file %s has incorrect version "
-                                  "(expected %d.%d, got %d.%d)", symfile->filename,
-                                  MONO_SYMBOL_FILE_MAJOR_VERSION, MONO_SYMBOL_FILE_MINOR_VERSION,
-                                  major, minor);
+                       g_warning ("Symbol file %s has incorrect version (expected %d.%d, got %d)",
+                                  symfile->filename, MONO_SYMBOL_FILE_MAJOR_VERSION,
+                                  MONO_SYMBOL_FILE_MINOR_VERSION, major);
                return FALSE;
        }
 
@@ -118,7 +114,6 @@ mono_debug_open_mono_symbols (MonoDebugHandle *handle, const guint8 *raw_content
                              int size, gboolean in_the_debugger)
 {
        MonoSymbolFile *symfile;
-       FILE* f;
 
        mono_debugger_lock ();
        symfile = g_new0 (MonoSymbolFile, 1);
@@ -130,21 +125,20 @@ mono_debug_open_mono_symbols (MonoDebugHandle *handle, const guint8 *raw_content
                memcpy (p, raw_contents, size);
                symfile->filename = g_strdup_printf ("LoadedFromMemory");
        } else {
+               MonoFileMap *f;
                symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
 
-               if ((f = fopen (symfile->filename, "rb"))) {
-                       struct stat stat_buf;
-                       
-                       if (fstat (fileno (f), &stat_buf) < 0) {
+               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_size = stat_buf.st_size;
-                               symfile->raw_contents = mono_raw_buffer_load (fileno (f), FALSE, 0, stat_buf.st_size);
+                               symfile->raw_contents = mono_file_map (symfile->raw_contents_size, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (f), 0, &symfile->raw_contents_handle);
                        }
 
-                       fclose (f);
+                       mono_file_map_close (f);
                }
        }
        
@@ -172,7 +166,7 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
                g_hash_table_destroy (symfile->method_hash);
 
        if (symfile->raw_contents)
-               mono_raw_buffer_free ((gpointer) symfile->raw_contents);
+               mono_file_unmap ((gpointer) symfile->raw_contents, symfile->raw_contents_handle);
 
        if (symfile->filename)
                g_free (symfile->filename);
@@ -237,6 +231,15 @@ check_line (StatementMachine *stm, int offset, MonoDebugSourceLocation **locatio
                source_file = read_string (stm->symfile->raw_contents + read32(&(se->_data_offset)));
        }
 
+       if (stm->last_line == 0) {
+               /* 
+                * The IL offset is less than the first IL offset which has a corresponding
+                * source line.
+                */
+               *location = NULL;
+               return TRUE;
+       }
+
        *location = g_new0 (MonoDebugSourceLocation, 1);
        (*location)->source_file = source_file;
        (*location)->row = stm->last_line;
@@ -274,9 +277,9 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset)
        if ((symfile = minfo->handle->symfile) == NULL)
                return NULL;
 
-       stm.line_base = symfile->offset_table->_line_number_table_line_base;
-       stm.line_range = symfile->offset_table->_line_number_table_line_range;
-       stm.opcode_base = (guint8) symfile->offset_table->_line_number_table_opcode_base;
+       stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base);
+       stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range);
+       stm.opcode_base = (guint8) read32 (&symfile->offset_table->_line_number_table_opcode_base);
        stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range;
 
        mono_debugger_lock ();
@@ -285,8 +288,10 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset)
 
        stm.symfile = symfile;
        stm.offset = stm.last_offset = 0;
-       stm.file = stm.last_file = 1;
-       stm.line = stm.last_line = 1;
+       stm.last_file = 0;
+       stm.last_line = 0;
+       stm.file = 1;
+       stm.line = 1;
 
        while (TRUE) {
                guint8 opcode = *ptr++;
@@ -394,6 +399,13 @@ mono_debug_symfile_lookup_method (MonoDebugHandle *handle, MonoMethod *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)));
 
@@ -419,3 +431,51 @@ mono_debug_symfile_lookup_method (MonoDebugHandle *handle, MonoMethod *method)
        mono_debugger_unlock ();
        return minfo;
 }
+
+/*
+ * mono_debug_symfile_lookup_locals:
+ *
+ *   Return information about the local variables of MINFO from the symbol file.
+ * NAMES and INDEXES are set to g_malloc-ed arrays containing the local names and
+ * their IL indexes.
+ * Returns: the number of elements placed into the arrays, or -1 if there is no
+ * local variable info.
+ */
+int
+mono_debug_symfile_lookup_locals (MonoDebugMethodInfo *minfo, char ***names, int **indexes)
+{
+       MonoSymbolFile *symfile = minfo->handle->symfile;
+       const guint8 *p;
+       int i, len, compile_unit_index, locals_offset, num_locals, index, block_index;
+
+       *names = NULL;
+       *indexes = NULL;
+
+       if (!symfile)
+               return -1;
+
+       p = symfile->raw_contents + minfo->data_offset;
+
+       compile_unit_index = read_leb128 (p, &p);
+       locals_offset = read_leb128 (p, &p);
+
+       p = symfile->raw_contents + locals_offset;
+       num_locals = read_leb128 (p, &p);
+
+       *names = g_new0 (char*, num_locals);
+       *indexes = g_new0 (int, num_locals);
+
+       for (i = 0; i < num_locals; ++i) {
+               index = read_leb128 (p, &p);
+               (*indexes) [i] = index;
+               len = read_leb128 (p, &p);
+               (*names) [i] = g_malloc (len + 1);
+               memcpy ((*names) [i], p, len);
+               (*names) [i][len] = '\0';
+               p += len;
+               block_index = read_leb128 (p, &p);
+       }
+
+       return num_locals;
+}
+