update known-issues
[mono.git] / mono / metadata / mono-debug.c
index a0ef8382e95135a34e5f2a8f79ffefd4b7f88e80..677318e8e20263e470f867d9b643e4ed3fb4499f 100644 (file)
@@ -33,6 +33,7 @@
 
 MonoSymbolTable *mono_symbol_table = NULL;
 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
+guint32 mono_debug_debugger_version = -1;
 
 static gboolean in_the_mono_debugger = FALSE;
 static gboolean mono_debug_initialized = FALSE;
@@ -40,7 +41,8 @@ GHashTable *mono_debug_handles = NULL;
 
 static GHashTable *method_hash = NULL;
 
-static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image);
+static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image, const guint8 *raw_contents, int size);
+
 static void                 mono_debug_close_image     (MonoDebugHandle *debug);
 
 static MonoDebugHandle     *_mono_debug_get_image      (MonoImage *image);
@@ -116,7 +118,7 @@ mono_debug_init (MonoDebugFormat format)
 void
 mono_debug_init_1 (MonoDomain *domain)
 {
-       MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib ());
+       MonoDebugHandle *handle = mono_debug_open_image (mono_get_corlib (), NULL, 0);
 
        mono_symbol_table->corlib = handle;
 }
@@ -129,9 +131,21 @@ mono_debug_init_1 (MonoDomain *domain)
 void
 mono_debug_init_2 (MonoAssembly *assembly)
 {
-       mono_debug_open_image (mono_assembly_get_image (assembly));
+       mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
+}
+
+/*
+ * Initialize debugging support - part 2.
+ *
+ * This method must be called between loading the image and loading the assembly.
+ */
+void
+mono_debug_init_2_memory (MonoImage *image, const guint8 *raw_contents, int size)
+{
+       mono_debug_open_image (image, raw_contents, size);
 }
 
+
 gboolean
 mono_debug_using_mono_debugger (void)
 {
@@ -175,7 +189,7 @@ allocate_debug_handle (MonoSymbolTable *table)
 }
 
 static MonoDebugHandle *
-mono_debug_open_image (MonoImage *image)
+mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
 {
        MonoDebugHandle *handle;
 
@@ -194,7 +208,7 @@ mono_debug_open_image (MonoImage *image)
 
        g_hash_table_insert (mono_debug_handles, image, handle);
 
-       handle->symfile = mono_debug_open_mono_symbol_file (handle, in_the_mono_debugger);
+       handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, in_the_mono_debugger);
        if (in_the_mono_debugger)
                mono_debugger_add_symbol_file (handle);
 
@@ -217,7 +231,7 @@ static void
 mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
 {
        mono_debugger_lock ();
-       mono_debug_open_image (mono_assembly_get_image (assembly));
+       mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0);
        mono_debugger_unlock ();
 }
 
@@ -303,7 +317,7 @@ lookup_method_func (gpointer key, gpointer value, gpointer user_data)
                return;
 
        if (handle->symfile)
-               data->minfo = mono_debug_find_method (handle, data->method);
+               data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
 }
 
 static MonoDebugMethodInfo *
@@ -321,6 +335,24 @@ _mono_debug_lookup_method (MonoMethod *method)
        return data.minfo;
 }
 
+/**
+ * mono_debug_lookup_method:
+ *
+ * Lookup symbol file information for the method @method.  The returned
+ * `MonoDebugMethodInfo' is a private structure, but it can be passed to
+ * mono_debug_symfile_lookup_location().
+ */
+MonoDebugMethodInfo *
+mono_debug_lookup_method (MonoMethod *method)
+{
+       MonoDebugMethodInfo *minfo;
+
+       mono_debugger_lock ();
+       minfo = _mono_debug_lookup_method (method);
+       mono_debugger_unlock ();
+       return minfo;
+}
+
 static inline void
 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
 {
@@ -370,7 +402,7 @@ mono_debug_add_wrapper (MonoMethod *method, MonoDebugMethodJitInfo *jit)
 {
        MonoMethodHeader *header;
        MonoDebugWrapperData *wrapper;
-       char buffer [BUFSIZ];
+       guint8 buffer [BUFSIZ];
        guint8 *ptr, *oldptr;
        guint32 i, size, total_size, max_size;
        gint32 last_il_offset = 0, last_native_offset = 0;
@@ -448,7 +480,7 @@ MonoDebugMethodAddress *
 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
 {
        MonoDebugMethodAddress *address;
-       char buffer [BUFSIZ];
+       guint8 buffer [BUFSIZ];
        guint8 *ptr, *oldptr;
        guint32 i, size, total_size, max_size;
        gint32 last_il_offset = 0, last_native_offset = 0;
@@ -738,7 +770,7 @@ mono_debug_add_type (MonoClass *klass)
 {
        MonoDebugHandle *handle;
        MonoDebugClassEntry *entry;
-       char buffer [BUFSIZ];
+       guint8 buffer [BUFSIZ];
        guint8 *ptr, *oldptr;
        guint32 size, total_size, max_size;
        int base_offset = 0;
@@ -781,7 +813,7 @@ mono_debug_add_type (MonoClass *klass)
        if (max_size > BUFSIZ)
                g_free (oldptr);
 
-       mono_debugger_start_add_type (handle, klass);
+       mono_debugger_add_type (handle, klass);
 }
 
 static MonoDebugMethodJitInfo *
@@ -801,6 +833,16 @@ find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
        return mono_debug_read_method (address);
 }
 
+MonoDebugMethodJitInfo *
+mono_debug_find_method (MonoDebugMethodInfo *minfo, MonoDomain *domain)
+{
+       MonoDebugMethodJitInfo *res;
+       mono_debugger_lock ();
+       res = find_method (minfo, domain);
+       mono_debugger_unlock ();
+       return res;
+}
+
 static gint32
 il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32 native_offset)
 {
@@ -822,27 +864,21 @@ il_offset_from_address (MonoDebugMethodInfo *minfo, MonoDomain *domain, guint32
 }
 
 /**
- * mono_debug_source_location_from_address:
- * @method:
- * @address:
- * @line_number:
- * @domain:
+ * mono_debug_lookup_source_location:
+ * @address: Native offset within the @method's machine code.
  *
- * Used by the exception code to get a source location from a machine address.
+ * Lookup the source code corresponding to the machine instruction located at
+ * native offset @address within @method.
  *
- * Returns: a textual representation of the specified address which is suitable to be displayed to
- * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
- *
- * If the optional @line_number argument is not NULL, the line number is stored there and just the
- * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
- * line number 8 in the variable pointed to by @line_number).
+ * The returned `MonoDebugSourceLocation' contains both file / line number
+ * information and the corresponding IL offset.  It must be freed by
+ * mono_debug_free_source_location().
  */
-gchar *
-mono_debug_source_location_from_address (MonoMethod *method, guint32 address, guint32 *line_number,
-                                        MonoDomain *domain)
+MonoDebugSourceLocation *
+mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
 {
        MonoDebugMethodInfo *minfo;
-       char *res = NULL;
+       MonoDebugSourceLocation *location;
        gint32 offset;
 
        if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
@@ -856,115 +892,62 @@ mono_debug_source_location_from_address (MonoMethod *method, guint32 address, gu
        }
 
        offset = il_offset_from_address (minfo, domain, address);
-               
-       if (offset >= 0)
-               res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
-
-       mono_debugger_unlock ();
-       return res;
-}
-
-/**
- * mono_debug_source_location_from_il_offset:
- * @method:
- * @offset:
- * @line_number:
- *
- * Used by the exception code to get a source location from an IL offset.
- *
- * Returns a textual representation of the specified address which is suitable to be displayed to
- * the user (for instance "/home/martin/monocvs/debugger/test/Y.cs:8").
- *
- * If the optional @line_number argument is not NULL, the line number is stored there and just the
- * source file is returned (ie. it'd return "/home/martin/monocvs/debugger/test/Y.cs" and store the
- * line number 8 in the variable pointed to by @line_number).
- */
-gchar *
-mono_debug_source_location_from_il_offset (MonoMethod *method, guint32 offset, guint32 *line_number)
-{
-       char *res;
-       MonoDebugMethodInfo *minfo;
-
-       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
-               return NULL;
-
-       mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
-       if (!minfo || !minfo->handle || !minfo->handle->symfile) {
+       if (offset < 0) {
                mono_debugger_unlock ();
                return NULL;
        }
 
-       res = mono_debug_find_source_location (minfo->handle->symfile, method, offset, line_number);
+       location = mono_debug_symfile_lookup_location (minfo, offset);
        mono_debugger_unlock ();
-       return res;
+       return location;
 }
 
 /**
- * mono_debug_il_offset_from_address:
- * @method:
- * @address:
- * @domain:
+ * mono_debug_free_source_location:
+ * @location: A `MonoDebugSourceLocation'.
  *
- * Returns: the IL offset corresponding to machine address @address which is an offset
- * relative to the beginning of the method @method.
+ * Frees the @location.
  */
-gint32
-mono_debug_il_offset_from_address (MonoMethod *method, gint32 address, MonoDomain *domain)
+void
+mono_debug_free_source_location (MonoDebugSourceLocation *location)
 {
-       MonoDebugMethodInfo *minfo;
-       gint32 res;
-
-       if ((address < 0) || (mono_debug_format == MONO_DEBUG_FORMAT_NONE))
-               return -1;
-
-       mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
-       if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
-           !minfo->handle->symfile->offset_table) {
-               mono_debugger_unlock ();
-               return -1;
+       if (location) {
+               g_free (location->source_file);
+               g_free (location);
        }
-
-       res = il_offset_from_address (minfo, domain, address);
-       mono_debugger_unlock ();
-       return res;
 }
 
 /**
- * mono_debug_address_from_il_offset:
- * @method:
- * @il_offset:
- * @domain:
+ * mono_debug_print_stack_frame:
+ * @native_offset: Native offset within the @method's machine code.
  *
- * Returns: the machine address corresponding to IL offset @il_offset.
- * The returned value is an offset relative to the beginning of the method @method.
+ * Conventient wrapper around mono_debug_lookup_source_location() which can be
+ * used if you only want to use the location to print a stack frame.
  */
-gint32
-mono_debug_address_from_il_offset (MonoMethod *method, gint32 il_offset, MonoDomain *domain)
+gchar *
+mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
 {
-       MonoDebugMethodInfo *minfo;
-       MonoDebugMethodJitInfo *jit;
-       gint32 res;
-
-       if ((il_offset < 0) || (mono_debug_format == MONO_DEBUG_FORMAT_NONE))
-               return -1;
+       MonoDebugSourceLocation *location;
+       gchar *fname, *ptr, *res;
 
-       mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
-       if (!minfo || !minfo->il_offsets || !minfo->handle || !minfo->handle->symfile ||
-           !minfo->handle->symfile->offset_table) {
-               mono_debugger_unlock ();
-               return -1;
+       fname = mono_method_full_name (method, TRUE);
+       for (ptr = fname; *ptr; ptr++) {
+               if (*ptr == ':') *ptr = '.';
        }
 
-       jit = find_method (minfo, domain);
-       if (!jit) {
-               mono_debugger_unlock ();
-               return -1;
+       location = mono_debug_lookup_source_location (method, native_offset, domain);
+
+       if (!location) {
+               res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
+               g_free (fname);
+               return res;
        }
 
-       res = _mono_debug_address_from_il_offset (jit, il_offset);
-       mono_debugger_unlock ();
+       res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
+                              location->source_file, location->row);
+
+       g_free (fname);
+       mono_debug_free_source_location (location);
        return res;
 }
+