* reflection.c (inflate_mono_method): Reuse method instantiation
[mono.git] / mono / metadata / debug-mono-symfile.c
index 715e2f2ce098eefcb1cfcb1c45f218d9950841af..6d703a57168f698a19bdb0e5905a209b27d18764 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>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/mono-debug-debugger.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>
@@ -49,7 +52,7 @@ get_class_name (MonoClass *klass)
 }
 
 static int
-load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
+load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_debugger)
 {
        const char *ptr, *start;
        gchar *guid;
@@ -63,16 +66,18 @@ 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", symfile->filename);
+               if (!in_the_debugger)
+                       g_warning ("Symbol file %s is not a mono symbol file", symfile->filename);
                return FALSE;
        }
 
        version = read32(ptr);
        ptr += sizeof(guint32);
        if (version != MONO_SYMBOL_FILE_VERSION) {
-               g_warning ("Symbol file %s has incorrect version "
-                          "(expected %d, got %ld)", symfile->filename,
-                          MONO_SYMBOL_FILE_VERSION, version);
+               if (!in_the_debugger)
+                       g_warning ("Symbol file %s has incorrect version "
+                                  "(expected %d, got %ld)", symfile->filename,
+                                  MONO_SYMBOL_FILE_VERSION, version);
                return FALSE;
        }
 
@@ -80,8 +85,11 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
        ptr += 16;
 
        if (strcmp (handle->image->guid, guid)) {
-               g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
-                          handle->image_file);
+               if (!in_the_debugger)
+                       g_warning ("Symbol file %s doesn't match image %s", symfile->filename,
+                                  handle->image_file);
+               if (guid)
+                       g_free (guid);
                return FALSE;
        }
 
@@ -90,33 +98,54 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile)
        symfile->method_hash = g_hash_table_new_full (
                g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_method_info);
 
+       g_free (guid);
        return TRUE;
 }
 
 MonoSymbolFile *
-mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean create_symfile)
+mono_debug_open_mono_symbols (MonoDebugHandle *handle, const guint8 *raw_contents,
+                             int size, gboolean in_the_debugger)
 {
        MonoSymbolFile *symfile;
+       FILE* f;
 
-       mono_loader_lock ();
+       mono_debugger_lock ();
        symfile = g_new0 (MonoSymbolFile, 1);
 
-       symfile->filename = g_strdup_printf ("%s.mdb", mono_image_get_filename (handle->image));
-
-       if (!g_file_get_contents (symfile->filename, (gchar **) &symfile->raw_contents,
-                                 &symfile->raw_contents_size, NULL))
-               symfile->raw_contents = NULL;
-
-       if (load_symfile (handle, symfile)) {
-               mono_loader_unlock ();
+       if (raw_contents != NULL) {
+               symfile->raw_contents_size = size;
+               symfile->raw_contents = g_malloc (size);
+               memcpy(symfile->raw_contents, raw_contents, size);
+               symfile->filename = g_strdup_printf ("LoadedFromMemory");
+       } else {
+               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 (!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);
+                       }
+
+                       fclose (f);
+               }
+       }
+       
+       if (load_symfile (handle, symfile, in_the_debugger)) {
+               mono_debugger_unlock ();
                return symfile;
-       } else if (!create_symfile) {
+       } else if (!in_the_debugger) {
                mono_debug_close_mono_symbol_file (symfile);
-               mono_loader_unlock ();
+               mono_debugger_unlock ();
                return NULL;
        }
 
-       mono_loader_unlock ();
+       mono_debugger_unlock ();
        return symfile;
 }
 
@@ -126,12 +155,17 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
        if (!symfile)
                return;
 
-       mono_loader_lock ();
+       mono_debugger_lock ();
        if (symfile->method_hash)
                g_hash_table_destroy (symfile->method_hash);
 
+       if (symfile->raw_contents)
+               mono_raw_buffer_free ((gpointer) symfile->raw_contents);
+
+       if (symfile->filename)
+               g_free (symfile->filename);
        g_free (symfile);
-       mono_loader_unlock ();
+       mono_debugger_unlock ();
 }
 
 static int
@@ -161,27 +195,29 @@ read_string (const char *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)
+/**
+ * mono_debug_symfile_lookup_location:
+ * @minfo: A `MonoDebugMethodInfo' which can be retrieved by
+ *         mono_debug_lookup_method().
+ * @offset: IL offset within the corresponding method's CIL code.
+ *
+ * This function is similar to mono_debug_lookup_location(), but we
+ * already looked up the method and also already did the
+ * `native address -> IL offset' mapping.
+ */
+MonoDebugSourceLocation *
+mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset)
 {
        MonoSymbolFileLineNumberEntry *lne;
-       MonoDebugMethodInfo *minfo;
+       MonoSymbolFile *symfile;
        gchar *source_file = NULL;
        const char *ptr;
-       int i;
+       int count, i;
 
-       mono_loader_lock ();
-       if (!symfile->method_hash) {
-               mono_loader_unlock ();
+       if ((symfile = minfo->handle->symfile) == NULL)
                return NULL;
-       }
 
-       minfo = g_hash_table_lookup (symfile->method_hash, method);
-       if (!minfo) {
-               mono_loader_unlock ();
-               return NULL;
-       }
+       mono_debugger_lock ();
 
        if (read32(&(minfo->entry->_source_index))) {
                int offset = read32(&(symfile->offset_table->_source_table_offset)) +
@@ -193,32 +229,25 @@ mono_debug_find_source_location (MonoSymbolFile *symfile, MonoMethod *method, gu
 
        ptr = symfile->raw_contents + read32(&(minfo->entry->_line_number_table_offset));
 
-       lne = (MonoSymbolFileLineNumberEntry *) ptr;
+       count = read32(&(minfo->entry->_num_line_numbers));
+       lne = ((MonoSymbolFileLineNumberEntry *) ptr) + count - 1;
+
+       for (i = count - 1; i >= 0; i--, lne--) {
+               MonoDebugSourceLocation *location;
 
-       for (i = 0; i < read32(&(minfo->entry->_num_line_numbers)); i++, lne++) {
-               if (read32(&(lne->_offset)) < offset)
+               if (read32(&(lne->_offset)) > offset)
                        continue;
 
-               if (line_number) {
-                       *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, 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;
-               }
+               location = g_new0 (MonoDebugSourceLocation, 1);
+               location->source_file = source_file;
+               location->row = read32(&(lne->_row));
+               location->il_offset = read32(&(lne->_offset));
+
+               mono_debugger_unlock ();
+               return location;
        }
 
-       mono_loader_unlock ();
+       mono_debugger_unlock ();
        return NULL;
 }
 
@@ -230,9 +259,8 @@ _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offs
        if (!jit || !jit->line_numbers)
                return -1;
 
-       for (i = jit->line_numbers->len - 1; i >= 0; i--) {
-               MonoDebugLineNumberEntry lne = g_array_index (
-                       jit->line_numbers, MonoDebugLineNumberEntry, i);
+       for (i = jit->num_line_numbers - 1; i >= 0; i--) {
+               MonoDebugLineNumberEntry lne = jit->line_numbers [i];
 
                if (lne.il_offset <= il_offset)
                        return lne.native_offset;
@@ -251,7 +279,7 @@ compare_method (const void *key, const void *object)
 }
 
 MonoDebugMethodInfo *
-mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
+mono_debug_symfile_lookup_method (MonoDebugHandle *handle, MonoMethod *method)
 {
        MonoSymbolFileMethodEntry *me;
        MonoSymbolFileMethodIndexEntry *first_ie, *ie;
@@ -264,7 +292,7 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
        if (handle->image != mono_class_get_image (mono_method_get_class (method)))
                return NULL;
 
-       mono_loader_lock ();
+       mono_debugger_lock ();
        first_ie = (MonoSymbolFileMethodIndexEntry *)
                (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset)));
 
@@ -273,7 +301,7 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
                                   sizeof (MonoSymbolFileMethodIndexEntry), compare_method);
 
        if (!ie) {
-               mono_loader_unlock ();
+               mono_debugger_unlock ();
                return NULL;
        }
 
@@ -286,10 +314,13 @@ mono_debug_find_method (MonoDebugHandle *handle, MonoMethod *method)
        minfo->num_il_offsets = read32(&(me->_num_line_numbers));
        minfo->il_offsets = (MonoSymbolFileLineNumberEntry *)
                (symfile->raw_contents + read32(&(me->_line_number_table_offset)));
+       minfo->num_lexical_blocks = read32(&(me->_num_lexical_blocks));
+       minfo->lexical_blocks = (MonoSymbolFileLexicalBlockEntry *)
+               (symfile->raw_contents + read32(&(me->_lexical_block_table_offset)));
        minfo->entry = me;
 
        g_hash_table_insert (symfile->method_hash, method, minfo);
 
-       mono_loader_unlock ();
+       mono_debugger_unlock ();
        return minfo;
 }