merge from trunk at 97714
[mono.git] / mono / metadata / debug-mono-symfile.c
index e5a888b751cc228af357ba0333020a27f2334d8a..000f9b8ef1635a712530cc7e319bf571c817be96 100644 (file)
@@ -4,7 +4,9 @@
 #include <errno.h>
 #include <string.h>
 #include <signal.h>
+#ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
+#endif
 #include <sys/stat.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/tabledefs.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 <fcntl.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #define RANGE_TABLE_CHUNK_SIZE         256
 #define CLASS_TABLE_CHUNK_SIZE         256
@@ -58,7 +63,7 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_
        guint64 magic;
        long version;
 
-       ptr = start = symfile->raw_contents;
+       ptr = start = (const char*)symfile->raw_contents;
        if (!ptr)
                return FALSE;
 
@@ -72,7 +77,7 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_
 
        version = read32(ptr);
        ptr += sizeof(guint32);
-       if (version != MONO_SYMBOL_FILE_VERSION) {
+       if ((version != MONO_SYMBOL_FILE_VERSION) && (version != MONO_SYMBOL_FILE_COMPATIBILITY_VERSION)) {
                if (!in_the_debugger)
                        g_warning ("Symbol file %s has incorrect version "
                                   "(expected %d, got %ld)", symfile->filename,
@@ -87,19 +92,25 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_
                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;
        }
 
+       symfile->version = version;
+
        symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr;
 
        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 in_the_debugger)
+mono_debug_open_mono_symbols (MonoDebugHandle *handle, const guint8 *raw_contents,
+                             int size, gboolean in_the_debugger)
 {
        MonoSymbolFile *symfile;
        FILE* f;
@@ -107,21 +118,29 @@ mono_debug_open_mono_symbol_file (MonoDebugHandle *handle, gboolean in_the_debug
        mono_debugger_lock ();
        symfile = g_new0 (MonoSymbolFile, 1);
 
-       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 (raw_contents != NULL) {
+               unsigned char *p;
+               symfile->raw_contents_size = size;
+               symfile->raw_contents = p = g_malloc (size);
+               memcpy (p, 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);
+                       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);
                }
-               
-               fclose (f);
        }
        
        if (load_symfile (handle, symfile, in_the_debugger)) {
@@ -149,7 +168,9 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile)
 
        if (symfile->raw_contents)
                mono_raw_buffer_free ((gpointer) symfile->raw_contents);
-       
+
+       if (symfile->filename)
+               g_free (symfile->filename);
        g_free (symfile);
        mono_debugger_unlock ();
 }
@@ -181,61 +202,56 @@ 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;
+       const unsigned char *ptr;
+       int count, i;
 
-       mono_debugger_lock ();
-       if (!symfile->method_hash) {
-               mono_debugger_unlock ();
+       if ((symfile = minfo->handle->symfile) == NULL)
                return NULL;
-       }
 
-       minfo = g_hash_table_lookup (symfile->method_hash, method);
-       if (!minfo) {
-               mono_debugger_unlock ();
-               return NULL;
-       }
+       mono_debugger_lock ();
 
        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);
 
-               source_file = read_string (symfile->raw_contents + read32(&(se->_name_offset)));
+               source_file = read_string ((const char*)symfile->raw_contents + read32(&(se->_name_offset)));
        }
 
        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_debugger_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_debugger_unlock ();
-                       return retval;
-               } else {
-                       gchar* retval = g_strdup_printf ("%d", read32(&(lne->_row)));
-                       mono_debugger_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_debugger_unlock ();
@@ -253,11 +269,13 @@ _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offs
        for (i = jit->num_line_numbers - 1; i >= 0; i--) {
                MonoDebugLineNumberEntry lne = jit->line_numbers [i];
 
+               if (lne.il_offset < 0)
+                       continue;
                if (lne.il_offset <= il_offset)
                        return lne.native_offset;
        }
 
-       return -1;
+       return 0;
 }
 
 static int
@@ -270,7 +288,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;
@@ -305,9 +323,7 @@ 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);