New tests.
[mono.git] / mono / metadata / mono-debug.c
index 12c10b084b27d37f5c900bb9fda68419c700a6a6..a1767f01076066a3011837438d5b5032d185ff2a 100644 (file)
@@ -1,3 +1,13 @@
+/*
+ * mono-debug.c: 
+ *
+ * Author:
+ *     Mono Project (http://www.mono-project.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ */
+
 #include <config.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/tabledefs.h>
@@ -62,7 +72,7 @@ struct _MonoDebugDataTable {
 
 typedef struct {
        const gchar *method_name;
-       const gchar *cil_code;
+       const gchar *obsolete_cil_code;
        guint32 wrapper_type;
 } MonoDebugWrapperData;
 
@@ -96,7 +106,7 @@ typedef struct {
 
 MonoSymbolTable *mono_symbol_table = NULL;
 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
-gint32 mono_debug_debugger_version = 4;
+gint32 mono_debug_debugger_version = 5;
 gint32 _mono_debug_using_mono_debugger = 0;
 
 static gboolean mono_debug_initialized = FALSE;
@@ -149,7 +159,6 @@ free_header_data (gpointer key, gpointer value, gpointer user_data)
 
        if (header->wrapper_data) {
                g_free ((gpointer)header->wrapper_data->method_name);
-               g_free ((gpointer)header->wrapper_data->cil_code);
                g_slist_free (header->address_list);
                g_free (header->wrapper_data);
        }
@@ -213,6 +222,9 @@ mono_debug_init (MonoDebugFormat format)
 {
        g_assert (!mono_debug_initialized);
 
+       if (_mono_debug_using_mono_debugger)
+               format = MONO_DEBUG_FORMAT_DEBUGGER;
+
        mono_debug_initialized = TRUE;
        mono_debug_format = format;
 
@@ -327,6 +339,9 @@ mono_debug_domain_unload (MonoDomain *domain)
        mono_debugger_unlock ();
 }
 
+/*
+ * LOCKING: Assumes the debug lock is held.
+ */
 static MonoDebugHandle *
 _mono_debug_get_image (MonoImage *image)
 {
@@ -341,11 +356,13 @@ mono_debug_close_image (MonoImage *image)
        if (!mono_debug_initialized)
                return;
 
+       mono_debugger_lock ();
+
        handle = _mono_debug_get_image (image);
-       if (!handle)
+       if (!handle) {
+               mono_debugger_unlock ();
                return;
-
-       mono_debugger_lock ();
+       }
 
        mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
                             handle->index);
@@ -364,11 +381,13 @@ mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
        if (mono_image_is_dynamic (image))
                return NULL;
 
+       mono_debugger_lock ();
+
        handle = _mono_debug_get_image (image);
-       if (handle != NULL)
+       if (handle != NULL) {
+               mono_debugger_unlock ();
                return handle;
-
-       mono_debugger_lock ();
+       }
 
        handle = g_new0 (MonoDebugHandle, 1);
        handle->index = ++next_symbol_file_id;
@@ -575,8 +594,8 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
                is_wrapper = TRUE;
        }
 
-       max_size = 24 + 8 * jit->num_line_numbers +
-               (20 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
+       max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
+               (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);
 
        if (max_size > BUFSIZ)
                ptr = oldptr = g_malloc (max_size);
@@ -634,20 +653,13 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
                g_hash_table_insert (table->method_hash, declaring, header);
 
                if (is_wrapper) {
-                       const unsigned char* il_code;
-                       MonoMethodHeader *mheader;
                        MonoDebugWrapperData *wrapper;
-                       guint32 il_codesize;
-
-                       mheader = mono_method_get_header (declaring);
-                       il_code = mono_method_header_get_code (mheader, &il_codesize, NULL);
 
                        header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
 
                        wrapper->wrapper_type = method->wrapper_type;
                        wrapper->method_name = mono_method_full_name (declaring, TRUE);
-                       wrapper->cil_code = mono_disasm_code (
-                               NULL, declaring, il_code, il_code + il_codesize);
+                       wrapper->obsolete_cil_code = "";
                }
        } else {
                address->header.wrapper_data = header->wrapper_data;
@@ -804,16 +816,18 @@ mono_debug_add_type (MonoClass *klass)
        guint32 size, total_size, max_size;
        int base_offset = 0;
 
-       handle = _mono_debug_get_image (klass->image);
-       if (!handle)
-               return;
-
        if (klass->generic_class || klass->rank ||
            (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
                return;
 
        mono_debugger_lock ();
 
+       handle = _mono_debug_get_image (klass->image);
+       if (!handle) {
+               mono_debugger_unlock ();
+               return;
+       }
+
        max_size = 12 + sizeof (gpointer);
        if (max_size > BUFSIZ)
                ptr = oldptr = g_malloc (max_size);
@@ -868,6 +882,10 @@ MonoDebugMethodJitInfo *
 mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
 {
        MonoDebugMethodJitInfo *res;
+
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return NULL;
+
        mono_debugger_lock ();
        res = find_method (method, domain);
        mono_debugger_unlock ();
@@ -903,7 +921,7 @@ mono_debug_lookup_method_addresses (MonoMethod *method)
        GSList *list;
        guint8 *ptr;
 
-       g_assert (mono_debug_debugger_version == 4);
+       g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
 
        mono_debugger_lock ();
 
@@ -965,6 +983,26 @@ cleanup_and_fail:
        return -1;
 }
 
+/**
+ * mono_debug_il_offset_from_address:
+ *
+ *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
+ * code of METHOD in DOMAIN.
+ */
+gint32
+mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
+{
+       gint32 res;
+
+       mono_debugger_lock ();
+
+       res = il_offset_from_address (method, domain, native_offset);
+
+       mono_debugger_unlock ();
+
+       return res;
+}
+
 /**
  * mono_debug_lookup_source_location:
  * @address: Native offset within the @method's machine code.
@@ -1004,6 +1042,40 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma
        return location;
 }
 
+/*
+ * mono_debug_lookup_locals:
+ *
+ *   Return information about the local variables of MINFO.
+ * 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_lookup_locals (MonoMethod *method, char ***names, int **indexes)
+{
+       MonoDebugMethodInfo *minfo;
+       int res;
+
+       *names = NULL;
+       *indexes = NULL;
+
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return -1;
+
+       mono_debugger_lock ();
+       minfo = _mono_debug_lookup_method (method);
+       if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) {
+               mono_debugger_unlock ();
+               return -1;
+       }
+
+       res = mono_debug_symfile_lookup_locals (minfo, names, indexes);
+       mono_debugger_unlock ();
+
+       return res;
+}
+
 /**
  * mono_debug_free_source_location:
  * @location: A `MonoDebugSourceLocation'.
@@ -1031,6 +1103,7 @@ mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDom
 {
        MonoDebugSourceLocation *location;
        gchar *fname, *ptr, *res;
+       int offset;
 
        fname = mono_method_full_name (method, TRUE);
        for (ptr = fname; *ptr; ptr++) {
@@ -1040,7 +1113,18 @@ mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDom
        location = mono_debug_lookup_source_location (method, native_offset, domain);
 
        if (!location) {
-               res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
+               if (mono_debug_initialized) {
+                       mono_debugger_lock ();
+                       offset = il_offset_from_address (method, domain, native_offset);
+                       mono_debugger_unlock ();
+               } else {
+                       offset = -1;
+               }
+
+               if (offset < 0)
+                       res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
+               else
+                       res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
                g_free (fname);
                return res;
        }
@@ -1083,3 +1167,18 @@ mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
                break;
        }
 }
+
+static gboolean is_attached = FALSE;
+
+void
+mono_set_is_debugger_attached (gboolean attached)
+{
+       is_attached = attached;
+}
+
+gboolean
+mono_is_debugger_attached (void)
+{
+       return is_attached;
+}
+