Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / mono-debug.c
index 5e5173f93234ccfcf34c9b0c509001e57f71a71d..4230399ec10242c2c3d339e80ed8271981bb4f96 100644 (file)
@@ -1,5 +1,5 @@
-/*
- * mono-debug.c: 
+/**
+ * \file
  *
  * Author:
  *     Mono Project (http://www.mono-project.com)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/debug-internals.h>
 #include <mono/metadata/mono-endian.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/mempool.h>
+#include <mono/metadata/debug-mono-symfile.h>
+#include <mono/metadata/debug-mono-ppdb.h>
+#include <mono/metadata/exception-internals.h>
+#include <mono/metadata/runtime.h>
 #include <string.h>
 
-#define DATA_TABLE_CHUNK_SIZE          (16384-sizeof (MonoDebugDataChunk))
-
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 
 #if NO_UNALIGNED_ACCESS
-#define RETURN_UNALIGNED(type, addr) \
-       { \
-               type val; \
-               memcpy(&val, p + offset, sizeof(val)); \
-               return val; \
-       }
 #define WRITE_UNALIGNED(type, addr, val) \
        memcpy(addr, &val, sizeof(type))
 #define READ_UNALIGNED(type, addr, val) \
        memcpy(&val, addr, sizeof(type))
 #else
-#define RETURN_UNALIGNED(type, addr) \
-       return *(type*)(p + offset);
 #define WRITE_UNALIGNED(type, addr, val) \
        (*(type *)(addr) = (val))
 #define READ_UNALIGNED(type, addr, val) \
        val = (*(type *)(addr))
 #endif
 
-typedef enum {
-       MONO_DEBUG_DATA_ITEM_UNKNOWN            = 0,
-       MONO_DEBUG_DATA_ITEM_CLASS,
-       MONO_DEBUG_DATA_ITEM_METHOD,
-       MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE
-} MonoDebugDataItemType;
-
-typedef struct _MonoDebugDataChunk MonoDebugDataChunk;
-
-struct _MonoDebugDataChunk {
-       guint32 total_size;
-       guint32 allocated_size;
-       guint32 current_offset;
-       guint32 dummy;
-       MonoDebugDataChunk *next;
-       guint8 data [MONO_ZERO_LEN_ARRAY];
-};
-
+/* This contains per-domain info */
 struct _MonoDebugDataTable {
-       gint32 domain;
-       gint32 _dummy; /* alignment for next field. */
-       MonoDebugDataChunk *first_chunk;
-       MonoDebugDataChunk *current_chunk;
-       GHashTable *method_hash;
+       MonoMemPool *mp;
        GHashTable *method_address_hash;
 };
 
-typedef struct {
-       const gchar *method_name;
-       const gchar *obsolete_cil_code;
-       guint32 wrapper_type;
-} MonoDebugWrapperData;
-
-typedef struct {
-       guint32 size;
-       guint32 symfile_id;
-       guint32 domain_id;
-       guint32 method_id;
-       MonoDebugWrapperData *wrapper_data;
-       MonoMethod *method;
-       GSList *address_list;
-} MonoDebugMethodHeader;
-
+/* This contains JIT debugging information about a method in serialized format */
 struct _MonoDebugMethodAddress {
-       MonoDebugMethodHeader header;
        const guint8 *code_start;
-       const guint8 *wrapper_addr;
        guint32 code_size;
        guint8 data [MONO_ZERO_LEN_ARRAY];
 };
 
-struct _MonoDebugClassEntry {
-       guint32 size;
-       guint8 data [MONO_ZERO_LEN_ARRAY];
-};
-
-typedef struct {
-       gpointer code;
-       guint32 size;
-} MonoDebugDelegateTrampolineEntry;
-
-static MonoSymbolTable *mono_symbol_table = NULL;
 static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
-static gint32 mono_debug_debugger_version = 5;
 
 static gboolean mono_debug_initialized = FALSE;
-static GHashTable *mono_debug_handles = NULL;
+/* Maps MonoImage -> MonoMonoDebugHandle */
+static GHashTable *mono_debug_handles;
+/* Maps MonoDomain -> MonoDataTable */
+static GHashTable *data_table_hash;
 
-static GHashTable *data_table_hash = NULL;
-static int next_symbol_file_id = 0;
+static mono_mutex_t debugger_lock_mutex;
+
+static gboolean is_attached = FALSE;
 
 static MonoDebugHandle     *mono_debug_open_image      (MonoImage *image, const guint8 *raw_contents, int size);
 
-static MonoDebugHandle     *_mono_debug_get_image      (MonoImage *image);
+static MonoDebugHandle     *mono_debug_get_image      (MonoImage *image);
 static void                 mono_debug_add_assembly    (MonoAssembly *assembly,
                                                        gpointer user_data);
-static void                 mono_debug_add_type        (MonoClass *klass);
 
 static MonoDebugHandle     *open_symfile_from_bundle   (MonoImage *image);
 
-void _mono_debug_init_corlib (MonoDomain *domain);
-
-extern void (*mono_debugger_class_init_func) (MonoClass *klass);
-
 static MonoDebugDataTable *
 create_data_table (MonoDomain *domain)
 {
        MonoDebugDataTable *table;
-       MonoDebugDataChunk *chunk;
 
        table = g_new0 (MonoDebugDataTable, 1);
-       table->domain = domain ? mono_domain_get_id (domain) : -1;
 
+       table->mp = mono_mempool_new ();
        table->method_address_hash = g_hash_table_new (NULL, NULL);
-       table->method_hash = g_hash_table_new (NULL, NULL);
-
-       chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + DATA_TABLE_CHUNK_SIZE);
-       chunk->total_size = DATA_TABLE_CHUNK_SIZE;
-
-       table->first_chunk = table->current_chunk = chunk;
 
-       if (domain) {
-               mono_debug_list_add (&mono_symbol_table->data_tables, table);
+       if (domain)
                g_hash_table_insert (data_table_hash, domain, table);
-       }
 
        return table;
 }
 
-static void
-free_header_data (gpointer key, gpointer value, gpointer user_data)
-{
-       MonoDebugMethodHeader *header = (MonoDebugMethodHeader*)value;
-
-       if (header->wrapper_data) {
-               g_free ((gpointer)header->wrapper_data->method_name);
-               g_free (header->wrapper_data);
-       }
-       g_slist_free (header->address_list);
-}
-
 static void
 free_data_table (MonoDebugDataTable *table)
 {
-       MonoDebugDataChunk *chunk, *next_chunk;
-
-       g_hash_table_foreach (table->method_hash, free_header_data, NULL);
-       g_hash_table_destroy (table->method_hash);
+       mono_mempool_destroy (table->mp);
        g_hash_table_destroy (table->method_address_hash);
 
-       table->method_hash = NULL;
-       table->method_address_hash = NULL;
-
-       chunk = table->first_chunk;
-       while (chunk) {
-               next_chunk = chunk->next;
-               g_free (chunk);
-               chunk = next_chunk;
-       }
-
-       table->first_chunk = table->current_chunk = NULL;
-       mono_debug_list_remove (&mono_symbol_table->data_tables, table);
        g_free (table);
 }
 
@@ -195,7 +104,7 @@ lookup_data_table (MonoDomain *domain)
 {
        MonoDebugDataTable *table;
 
-       table = g_hash_table_lookup (data_table_hash, domain);
+       table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
        if (!table) {
                g_error ("lookup_data_table () failed for %p\n", domain);
                g_assert (table);
@@ -206,12 +115,12 @@ lookup_data_table (MonoDomain *domain)
 static void
 free_debug_handle (MonoDebugHandle *handle)
 {
+       if (handle->ppdb)
+               mono_ppdb_close (handle);
        if (handle->symfile)
                mono_debug_close_mono_symbol_file (handle->symfile);
        /* decrease the refcount added with mono_image_addref () */
-       free_data_table (handle->type_table);
        mono_image_close (handle->image);
-       g_free (handle->image_file);
        g_free (handle);
 }
 
@@ -229,53 +138,24 @@ mono_debug_init (MonoDebugFormat format)
        if (format == MONO_DEBUG_FORMAT_DEBUGGER)
                g_error ("The mdb debugger is no longer supported.");
 
-
        mono_debug_initialized = TRUE;
        mono_debug_format = format;
 
-       /*
-        * This must be called before mono_debugger_initialize(), because the
-        * latter registers GC roots.
-        */
-       mono_gc_base_init ();
-
-       mono_debugger_initialize ();
+       mono_os_mutex_init_recursive (&debugger_lock_mutex);
 
        mono_debugger_lock ();
 
-       mono_symbol_table = g_new0 (MonoSymbolTable, 1);
-       mono_symbol_table->magic = MONO_DEBUGGER_MAGIC;
-       mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION;
-       mono_symbol_table->total_size = sizeof (MonoSymbolTable);
-
        mono_debug_handles = g_hash_table_new_full
                (NULL, NULL, NULL, (GDestroyNotify) free_debug_handle);
 
        data_table_hash = g_hash_table_new_full (
                NULL, NULL, NULL, (GDestroyNotify) free_data_table);
 
-       /* FIXME this is a disgusting hack. Kill it */
-       mono_debugger_class_init_func = mono_debug_add_type;
        mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
 
-       mono_symbol_table->global_data_table = create_data_table (NULL);
-
        mono_debugger_unlock ();
 }
 
-/*
- * INTERNAL USE ONLY !
- * FIXME this can have a decent name and exist in an internal header
- */
-void
-_mono_debug_init_corlib (MonoDomain *domain)
-{
-       if (!mono_debug_initialized)
-               return;
-
-       mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
-}
-
 void
 mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size)
 {
@@ -296,27 +176,20 @@ mono_debug_cleanup (void)
                g_hash_table_destroy (data_table_hash);
                data_table_hash = NULL;
        }
-
-       if (mono_symbol_table) {
-               if (mono_symbol_table->global_data_table)
-                       free_data_table (mono_symbol_table->global_data_table);
-
-               g_free (mono_symbol_table);
-               mono_symbol_table = NULL;
-       }
 }
 
+/**
+ * mono_debug_domain_create:
+ */
 void
 mono_debug_domain_create (MonoDomain *domain)
 {
-       MonoDebugDataTable *table;
-
        if (!mono_debug_initialized)
                return;
 
        mono_debugger_lock ();
 
-       table = create_data_table (domain);
+       create_data_table (domain);
 
        mono_debugger_unlock ();
 }
@@ -331,7 +204,7 @@ mono_debug_domain_unload (MonoDomain *domain)
 
        mono_debugger_lock ();
 
-       table = g_hash_table_lookup (data_table_hash, domain);
+       table = (MonoDebugDataTable *)g_hash_table_lookup (data_table_hash, domain);
        if (!table) {
                g_warning (G_STRLOC ": unloading unknown domain %p / %d",
                           domain, mono_domain_get_id (domain));
@@ -348,11 +221,14 @@ mono_debug_domain_unload (MonoDomain *domain)
  * LOCKING: Assumes the debug lock is held.
  */
 static MonoDebugHandle *
-_mono_debug_get_image (MonoImage *image)
+mono_debug_get_image (MonoImage *image)
 {
-       return g_hash_table_lookup (mono_debug_handles, image);
+       return (MonoDebugHandle *)g_hash_table_lookup (mono_debug_handles, image);
 }
 
+/**
+ * mono_debug_close_image:
+ */
 void
 mono_debug_close_image (MonoImage *image)
 {
@@ -363,13 +239,12 @@ mono_debug_close_image (MonoImage *image)
 
        mono_debugger_lock ();
 
-       handle = _mono_debug_get_image (image);
+       handle = mono_debug_get_image (image);
        if (!handle) {
                mono_debugger_unlock ();
                return;
        }
 
-       mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
        g_hash_table_remove (mono_debug_handles, image);
 
        mono_debugger_unlock ();
@@ -385,25 +260,22 @@ mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size)
 
        mono_debugger_lock ();
 
-       handle = _mono_debug_get_image (image);
+       handle = mono_debug_get_image (image);
        if (handle != NULL) {
                mono_debugger_unlock ();
                return handle;
        }
 
        handle = g_new0 (MonoDebugHandle, 1);
-       handle->index = ++next_symbol_file_id;
 
        handle->image = image;
        mono_image_addref (image);
-       handle->image_file = g_strdup (mono_image_get_filename (image));
 
-       handle->type_table = create_data_table (NULL);
+       /* Try a ppdb file first */
+       handle->ppdb = mono_ppdb_load_file (handle->image, raw_contents, size);
 
-       handle->symfile = mono_debug_open_mono_symbols (
-               handle, raw_contents, size, FALSE);
-
-       mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
+       if (!handle->ppdb)
+               handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, FALSE);
 
        g_hash_table_insert (mono_debug_handles, image, handle);
 
@@ -426,51 +298,6 @@ mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data)
        mono_debugger_unlock ();
 }
 
-static guint8 *
-allocate_data_item (MonoDebugDataTable *table, MonoDebugDataItemType type, guint32 size)
-{
-       guint32 chunk_size;
-       guint8 *data;
-
-       size = ALIGN_TO (size, sizeof (gpointer));
-
-       if (size + 16 < DATA_TABLE_CHUNK_SIZE)
-               chunk_size = DATA_TABLE_CHUNK_SIZE;
-       else
-               chunk_size = size + 16;
-
-       g_assert (table->current_chunk->current_offset == table->current_chunk->allocated_size);
-
-       if (table->current_chunk->allocated_size + size + 8 >= table->current_chunk->total_size) {
-               MonoDebugDataChunk *new_chunk;
-
-               new_chunk = g_malloc0 (sizeof (MonoDebugDataChunk) + chunk_size);
-               new_chunk->total_size = chunk_size;
-
-               table->current_chunk->next = new_chunk;
-               table->current_chunk = new_chunk;
-       }
-
-       data = &table->current_chunk->data [table->current_chunk->allocated_size];
-       table->current_chunk->allocated_size += size + 8;
-
-       * ((guint32 *) data) = size;
-       data += 4;
-       * ((guint32 *) data) = type;
-       data += 4;
-       return data;
-}
-
-static void
-write_data_item (MonoDebugDataTable *table, const guint8 *data)
-{
-       MonoDebugDataChunk *current_chunk = table->current_chunk;
-       guint32 size = * ((guint32 *) (data - 8));
-
-       g_assert (current_chunk->current_offset + size + 8 == current_chunk->allocated_size);
-       current_chunk->current_offset = current_chunk->allocated_size;
-}
-
 struct LookupMethodData
 {
        MonoDebugMethodInfo *minfo;
@@ -486,12 +313,14 @@ lookup_method_func (gpointer key, gpointer value, gpointer user_data)
        if (data->minfo)
                return;
 
-       if (handle->symfile)
+       if (handle->ppdb)
+               data->minfo = mono_ppdb_lookup_method (handle, data->method);
+       else if (handle->symfile)
                data->minfo = mono_debug_symfile_lookup_method (handle, data->method);
 }
 
 static MonoDebugMethodInfo *
-_mono_debug_lookup_method (MonoMethod *method)
+mono_debug_lookup_method_internal (MonoMethod *method)
 {
        struct LookupMethodData data;
 
@@ -508,21 +337,60 @@ _mono_debug_lookup_method (MonoMethod *method)
 /**
  * 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().
+ * Lookup symbol file information for the method \p method.  The returned
+ * \c MonoDebugMethodInfo is a private structure, but it can be passed to
+ * \c mono_debug_symfile_lookup_location.
  */
 MonoDebugMethodInfo *
 mono_debug_lookup_method (MonoMethod *method)
 {
        MonoDebugMethodInfo *minfo;
 
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return NULL;
+
        mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
+       minfo = mono_debug_lookup_method_internal (method);
        mono_debugger_unlock ();
        return minfo;
 }
 
+typedef struct
+{
+       gboolean found;
+       MonoImage *image;
+} LookupImageData;
+
+static void
+lookup_image_func (gpointer key, gpointer value, gpointer user_data)
+{
+       MonoDebugHandle *handle = (MonoDebugHandle *) value;
+       LookupImageData *data = (LookupImageData *) user_data;
+
+       if (data->found)
+               return;
+
+       if (handle->image == data->image && handle->symfile)
+               data->found = TRUE;
+}
+
+gboolean
+mono_debug_image_has_debug_info (MonoImage *image)
+{
+       LookupImageData data;
+
+       if (!mono_debug_handles)
+               return FALSE;
+
+       memset (&data, 0, sizeof (data));
+       data.image = image;
+
+       mono_debugger_lock ();
+       g_hash_table_foreach (mono_debug_handles, lookup_image_func, &data);
+       mono_debugger_unlock ();
+       return data.found;
+}
+
 static inline void
 write_leb128 (guint32 value, guint8 *ptr, guint8 **rptr)
 {
@@ -569,40 +437,27 @@ write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
        *rptr = ptr;
 }
 
+/**
+ * mono_debug_add_method:
+ */
 MonoDebugMethodAddress *
 mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
 {
-       MonoMethod *declaring;
        MonoDebugDataTable *table;
-       MonoDebugMethodHeader *header;
        MonoDebugMethodAddress *address;
-       MonoDebugMethodInfo *minfo;
-       MonoDebugHandle *handle;
        guint8 buffer [BUFSIZ];
        guint8 *ptr, *oldptr;
        guint32 i, size, total_size, max_size;
-       gboolean is_wrapper = FALSE;
 
        mono_debugger_lock ();
 
        table = lookup_data_table (domain);
 
-       handle = _mono_debug_get_image (method->klass->image);
-       minfo = _mono_debug_lookup_method (method);
-
-       if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
-           (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
-           (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
-           (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
-           (method->wrapper_type != MONO_WRAPPER_NONE)) {
-               is_wrapper = TRUE;
-       }
-
        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);
+               ptr = oldptr = (guint8 *)g_malloc (max_size);
        else
                ptr = oldptr = buffer;
 
@@ -616,23 +471,25 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
                write_sleb128 (lne->il_offset, ptr, &ptr);
                write_sleb128 (lne->native_offset, ptr, &ptr);
        }
-
-       *ptr++ = jit->this_var ? 1 : 0;
-       if (jit->this_var)
-               write_variable (jit->this_var, ptr, &ptr);
-
-       write_leb128 (jit->num_params, ptr, &ptr);
-       for (i = 0; i < jit->num_params; i++)
-               write_variable (&jit->params [i], ptr, &ptr);
-
-       write_leb128 (jit->num_locals, ptr, &ptr);
-       for (i = 0; i < jit->num_locals; i++)
-               write_variable (&jit->locals [i], ptr, &ptr);
-
-       *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
-       if (jit->gsharedvt_info_var) {
-               write_variable (jit->gsharedvt_info_var, ptr, &ptr);
-               write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+       write_leb128 (jit->has_var_info, ptr, &ptr);
+       if (jit->has_var_info) {
+               *ptr++ = jit->this_var ? 1 : 0;
+               if (jit->this_var)
+                       write_variable (jit->this_var, ptr, &ptr);
+
+               write_leb128 (jit->num_params, ptr, &ptr);
+               for (i = 0; i < jit->num_params; i++)
+                       write_variable (&jit->params [i], ptr, &ptr);
+
+               write_leb128 (jit->num_locals, ptr, &ptr);
+               for (i = 0; i < jit->num_locals; i++)
+                       write_variable (&jit->locals [i], ptr, &ptr);
+
+               *ptr++ = jit->gsharedvt_info_var ? 1 : 0;
+               if (jit->gsharedvt_info_var) {
+                       write_variable (jit->gsharedvt_info_var, ptr, &ptr);
+                       write_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+               }
        }
 
        size = ptr - oldptr;
@@ -640,18 +497,11 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
        total_size = size + sizeof (MonoDebugMethodAddress);
 
        if (method_is_dynamic (method)) {
-               address = g_malloc0 (total_size);
+               address = (MonoDebugMethodAddress *)g_malloc0 (total_size);
        } else {
-               address = (MonoDebugMethodAddress *) allocate_data_item (
-                                 table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);
+               address = (MonoDebugMethodAddress *)mono_mempool_alloc (table->mp, total_size);
        }
 
-       address->header.size = total_size;
-       address->header.symfile_id = handle ? handle->index : 0;
-       address->header.domain_id = mono_domain_get_id (domain);
-       address->header.method_id = is_wrapper ? 0 : minfo->index;
-       address->header.method = method;
-
        address->code_start = jit->code_start;
        address->code_size = jit->code_size;
 
@@ -659,32 +509,8 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
        if (max_size > BUFSIZ)
                g_free (oldptr);
 
-       declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
-       header = g_hash_table_lookup (table->method_hash, declaring);
-
-       if (!header) {
-               header = &address->header;
-               g_hash_table_insert (table->method_hash, declaring, header);
-
-               if (is_wrapper) {
-                       MonoDebugWrapperData *wrapper;
-
-                       header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);
-
-                       wrapper->wrapper_type = method->wrapper_type;
-                       wrapper->method_name = mono_method_full_name (declaring, TRUE);
-                       wrapper->obsolete_cil_code = "";
-               }
-       } else {
-               address->header.wrapper_data = header->wrapper_data;
-               header->address_list = g_slist_prepend (header->address_list, address);
-       }
-
        g_hash_table_insert (table->method_address_hash, method, address);
 
-       if (!method_is_dynamic (method))
-               write_data_item (table, (guint8 *) address);
-
        mono_debugger_unlock ();
        return address;
 }
@@ -692,9 +518,7 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma
 void
 mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
 {
-       MonoMethod *declaring;
        MonoDebugDataTable *table;
-       MonoDebugMethodHeader *header;
        MonoDebugMethodAddress *address;
 
        if (!mono_debug_initialized)
@@ -706,44 +530,21 @@ mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
 
        table = lookup_data_table (domain);
 
-       declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
-       g_hash_table_remove (table->method_hash, declaring);
-
-       address = g_hash_table_lookup (table->method_address_hash, method);
-       if (address) {
-               header = &address->header;
-
-               if (header->wrapper_data) {
-                       g_free ((char*)header->wrapper_data->method_name);
-                       g_free (header->wrapper_data);
-               }
+       address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
+       if (address)
                g_free (address);
-       }
 
        g_hash_table_remove (table->method_address_hash, method);
 
        mono_debugger_unlock ();
 }
 
+/**
+ * mono_debug_add_delegate_trampoline:
+ */
 void
 mono_debug_add_delegate_trampoline (gpointer code, int size)
 {
-       MonoDebugDelegateTrampolineEntry *entry;
-
-       if (!mono_debug_initialized)
-               return;
-
-       mono_debugger_lock ();
-
-       entry = (MonoDebugDelegateTrampolineEntry *) allocate_data_item (
-               mono_symbol_table->global_data_table, MONO_DEBUG_DATA_ITEM_DELEGATE_TRAMPOLINE,
-               sizeof (MonoDebugDelegateTrampolineEntry));
-       entry->code = code;
-       entry->size = size;
-
-       write_data_item (mono_symbol_table->global_data_table, (guint8 *) entry);
-
-       mono_debugger_unlock ();
 }
 
 static inline guint32
@@ -796,7 +597,7 @@ read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr)
        var->size = read_leb128 (ptr, &ptr);
        var->begin_scope = read_leb128 (ptr, &ptr);
        var->end_scope = read_leb128 (ptr, &ptr);
-       READ_UNALIGNED (gpointer, ptr, var->type);
+       READ_UNALIGNED (MonoType *, ptr, var->type);
        ptr += sizeof (gpointer);
        *rptr = ptr;
 }
@@ -825,7 +626,6 @@ mono_debug_read_method (MonoDebugMethodAddress *address)
        jit = g_new0 (MonoDebugMethodJitInfo, 1);
        jit->code_start = address->code_start;
        jit->code_size = address->code_size;
-       jit->wrapper_addr = address->wrapper_addr;
 
        ptr = (guint8 *) &address->data;
 
@@ -840,89 +640,34 @@ mono_debug_read_method (MonoDebugMethodAddress *address)
                lne->il_offset = read_sleb128 (ptr, &ptr);
                lne->native_offset = read_sleb128 (ptr, &ptr);
        }
+       jit->has_var_info = read_leb128 (ptr, &ptr);
+       if (jit->has_var_info) {
+               if (*ptr++) {
+                       jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+                       read_variable (jit->this_var, ptr, &ptr);
+               }
 
-       if (*ptr++) {
-               jit->this_var = g_new0 (MonoDebugVarInfo, 1);
-               read_variable (jit->this_var, ptr, &ptr);
-       }
-
-       jit->num_params = read_leb128 (ptr, &ptr);
-       jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
-       for (i = 0; i < jit->num_params; i++)
-               read_variable (&jit->params [i], ptr, &ptr);
-
-       jit->num_locals = read_leb128 (ptr, &ptr);
-       jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
-       for (i = 0; i < jit->num_locals; i++)
-               read_variable (&jit->locals [i], ptr, &ptr);
-
-       if (*ptr++) {
-               jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
-               jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
-               read_variable (jit->gsharedvt_info_var, ptr, &ptr);
-               read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+               jit->num_params = read_leb128 (ptr, &ptr);
+               jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+               for (i = 0; i < jit->num_params; i++)
+                       read_variable (&jit->params [i], ptr, &ptr);
+
+               jit->num_locals = read_leb128 (ptr, &ptr);
+               jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
+               for (i = 0; i < jit->num_locals; i++)
+                       read_variable (&jit->locals [i], ptr, &ptr);
+
+               if (*ptr++) {
+                       jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+                       jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+                       read_variable (jit->gsharedvt_info_var, ptr, &ptr);
+                       read_variable (jit->gsharedvt_locals_var, ptr, &ptr);
+               }
        }
 
        return jit;
 }
 
-static void
-mono_debug_add_type (MonoClass *klass)
-{
-       MonoDebugHandle *handle;
-       MonoDebugClassEntry *entry;
-       guint8 buffer [BUFSIZ];
-       guint8 *ptr, *oldptr;
-       guint32 size, total_size, max_size;
-       int base_offset = 0;
-
-       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);
-       else
-               ptr = oldptr = buffer;
-
-       if (klass->valuetype)
-               base_offset = - (int)(sizeof (MonoObject));
-
-       write_leb128 (klass->type_token, ptr, &ptr);
-       write_leb128 (klass->instance_size + base_offset, ptr, &ptr);
-       WRITE_UNALIGNED (gpointer, ptr, klass);
-       ptr += sizeof (gpointer);
-
-       size = ptr - oldptr;
-       g_assert (size < max_size);
-       total_size = size + sizeof (MonoDebugClassEntry);
-
-       g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE);
-
-       entry = (MonoDebugClassEntry *) allocate_data_item (
-               handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size);
-
-       entry->size = total_size;
-
-       memcpy (&entry->data, oldptr, size);
-
-       write_data_item (handle->type_table, (guint8 *) entry);
-
-       if (max_size > BUFSIZ)
-               g_free (oldptr);
-
-       mono_debugger_unlock ();
-}
-
 static MonoDebugMethodJitInfo *
 find_method (MonoMethod *method, MonoDomain *domain)
 {
@@ -930,7 +675,7 @@ find_method (MonoMethod *method, MonoDomain *domain)
        MonoDebugMethodAddress *address;
 
        table = lookup_data_table (domain);
-       address = g_hash_table_lookup (table->method_address_hash, method);
+       address = (MonoDebugMethodAddress *)g_hash_table_lookup (table->method_address_hash, method);
 
        if (!address)
                return NULL;
@@ -952,71 +697,11 @@ mono_debug_find_method (MonoMethod *method, MonoDomain *domain)
        return res;
 }
 
-struct LookupMethodAddressData
-{
-       MonoMethod *method;
-       MonoDebugMethodHeader *result;
-};
-
-static void
-lookup_method_address_func (gpointer key, gpointer value, gpointer user_data)
-{
-       MonoDebugDataTable *table = (MonoDebugDataTable *) value;
-       struct LookupMethodAddressData *data = (struct LookupMethodAddressData *) user_data;
-       MonoDebugMethodHeader *header;
-
-       header = g_hash_table_lookup (table->method_hash, data->method);
-       if (header)
-               data->result = header;
-}
-
 MonoDebugMethodAddressList *
 mono_debug_lookup_method_addresses (MonoMethod *method)
 {
-       MonoDebugMethodAddressList *info;
-       MonoDebugMethodHeader *header = NULL;
-       struct LookupMethodAddressData data;
-       MonoMethod *declaring;
-       int count, size;
-       GSList *list;
-       guint8 *ptr;
-
-       g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5));
-
-       mono_debugger_lock ();
-
-       declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
-
-       data.method = declaring;
-       data.result = NULL;
-
-       g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data);
-       header = data.result;
-
-       if (!header) {
-               mono_debugger_unlock ();
-               return NULL;
-       }
-
-       count = g_slist_length (header->address_list) + 1;
-       size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer);
-
-       info = g_malloc0 (size);
-       info->size = size;
-       info->count = count;
-
-       ptr = info->data;
-
-       WRITE_UNALIGNED (gpointer, ptr, header);
-       ptr += sizeof (gpointer);
-
-       for (list = header->address_list; list; list = list->next) {
-               WRITE_UNALIGNED (gpointer, ptr, list->data);
-               ptr += sizeof (gpointer);
-       }
-
-       mono_debugger_unlock ();
-       return info;
+       g_assert_not_reached ();
+       return NULL;
 }
 
 static gint32
@@ -1046,8 +731,8 @@ cleanup_and_fail:
 /**
  * mono_debug_il_offset_from_address:
  *
- *   Compute the IL offset corresponding to NATIVE_OFFSET inside the native
- * code of METHOD in DOMAIN.
+ * Compute the IL offset corresponding to \p native_offset inside the native
+ * code of \p method in \p domain.
  */
 gint32
 mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset)
@@ -1065,14 +750,12 @@ mono_debug_il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint
 
 /**
  * mono_debug_lookup_source_location:
- * @address: Native offset within the @method's machine code.
- *
+ * \param address Native offset within the \p method's machine code.
  * Lookup the source code corresponding to the machine instruction located at
- * native offset @address within @method.
- *
- * The returned `MonoDebugSourceLocation' contains both file / line number
+ * native offset \p address within \p method.
+ * The returned \c MonoDebugSourceLocation contains both file / line number
  * information and the corresponding IL offset.  It must be freed by
- * mono_debug_free_source_location().
+ * \c mono_debug_free_source_location.
  */
 MonoDebugSourceLocation *
 mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain)
@@ -1085,8 +768,13 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma
                return NULL;
 
        mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
-       if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
+       minfo = mono_debug_lookup_method_internal (method);
+       if (!minfo || !minfo->handle) {
+               mono_debugger_unlock ();
+               return NULL;
+       }
+
+       if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
                mono_debugger_unlock ();
                return NULL;
        }
@@ -1097,7 +785,58 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma
                return NULL;
        }
 
-       location = mono_debug_symfile_lookup_location (minfo, offset);
+       if (minfo->handle->ppdb)
+               location = mono_ppdb_lookup_location (minfo, offset);
+       else
+               location = mono_debug_symfile_lookup_location (minfo, offset);
+       mono_debugger_unlock ();
+       return location;
+}
+
+/**
+ * mono_debug_lookup_source_location_by_il:
+ *
+ *   Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
+ */
+MonoDebugSourceLocation *
+mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain)
+{
+       MonoDebugMethodInfo *minfo;
+       MonoDebugSourceLocation *location;
+
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return NULL;
+
+       mono_debugger_lock ();
+       minfo = mono_debug_lookup_method_internal (method);
+       if (!minfo || !minfo->handle) {
+               mono_debugger_unlock ();
+               return NULL;
+       }
+
+       if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
+               mono_debugger_unlock ();
+               return NULL;
+       }
+
+       if (minfo->handle->ppdb)
+               location = mono_ppdb_lookup_location (minfo, il_offset);
+       else
+               location = mono_debug_symfile_lookup_location (minfo, il_offset);
+       mono_debugger_unlock ();
+       return location;
+}
+
+MonoDebugSourceLocation *
+mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
+{
+       MonoDebugSourceLocation *location;
+
+       mono_debugger_lock ();
+       if (minfo->handle->ppdb)
+               location = mono_ppdb_lookup_location (minfo, il_offset);
+       else
+               location = mono_debug_symfile_lookup_location (minfo, il_offset);
        mono_debugger_unlock ();
        return location;
 }
@@ -1106,7 +845,7 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma
  * mono_debug_lookup_locals:
  *
  *   Return information about the local variables of MINFO.
- * The result should be freed using mono_debug_symfile_free_locals ().
+ * The result should be freed using mono_debug_free_locals ().
  */
 MonoDebugLocalsInfo*
 mono_debug_lookup_locals (MonoMethod *method)
@@ -1118,23 +857,92 @@ mono_debug_lookup_locals (MonoMethod *method)
                return NULL;
 
        mono_debugger_lock ();
-       minfo = _mono_debug_lookup_method (method);
-       if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) {
+       minfo = mono_debug_lookup_method_internal (method);
+       if (!minfo || !minfo->handle) {
                mono_debugger_unlock ();
                return NULL;
        }
 
-       res = mono_debug_symfile_lookup_locals (minfo);
+       if (minfo->handle->ppdb) {
+               res = mono_ppdb_lookup_locals (minfo);
+       } else {
+               if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))
+                       res = NULL;
+               else
+                       res = mono_debug_symfile_lookup_locals (minfo);
+       }
        mono_debugger_unlock ();
 
        return res;
 }
 
+/*
+ * mono_debug_free_locals:
+ *
+ *   Free all the data allocated by mono_debug_lookup_locals ().
+ */
+void
+mono_debug_free_locals (MonoDebugLocalsInfo *info)
+{
+       int i;
+
+       for (i = 0; i < info->num_locals; ++i)
+               g_free (info->locals [i].name);
+       g_free (info->locals);
+       g_free (info->code_blocks);
+       g_free (info);
+}
+
+/*
+* mono_debug_lookup_method_async_debug_info:
+*
+*   Return information about the async stepping information of method.
+* The result should be freed using mono_debug_free_async_debug_info ().
+*/
+MonoDebugMethodAsyncInfo*
+mono_debug_lookup_method_async_debug_info (MonoMethod *method)
+{
+       MonoDebugMethodInfo *minfo;
+       MonoDebugMethodAsyncInfo *res = NULL;
+
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return NULL;
+
+       mono_debugger_lock ();
+       minfo = mono_debug_lookup_method_internal (method);
+       if (!minfo || !minfo->handle) {
+               mono_debugger_unlock ();
+               return NULL;
+       }
+
+       if (minfo->handle->ppdb)
+               res = mono_ppdb_lookup_method_async_debug_info (minfo);
+
+       mono_debugger_unlock ();
+
+       return res;
+}
+
+/*
+ * mono_debug_free_method_async_debug_info:
+ *
+ *   Free all the data allocated by mono_debug_lookup_method_async_debug_info ().
+ */
+void
+mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo *info)
+{
+       if (info->num_awaits) {
+               g_free (info->yield_offsets);
+               g_free (info->resume_offsets);
+               g_free (info->move_next_method_token);
+       }
+       g_free (info);
+}
+
 /**
  * mono_debug_free_source_location:
- * @location: A `MonoDebugSourceLocation'.
- *
- * Frees the @location.
+ * \param location A \c MonoDebugSourceLocation
+ * Frees the \p location.
  */
 void
 mono_debug_free_source_location (MonoDebugSourceLocation *location)
@@ -1145,11 +953,18 @@ mono_debug_free_source_location (MonoDebugSourceLocation *location)
        }
 }
 
+static int (*get_seq_point) (MonoDomain *domain, MonoMethod *method, gint32 native_offset);
+
+void
+mono_install_get_seq_point (MonoGetSeqPointFunc func)
+{
+       get_seq_point = func;
+}
+
 /**
  * mono_debug_print_stack_frame:
- * @native_offset: Native offset within the @method's machine code.
- *
- * Conventient wrapper around mono_debug_lookup_source_location() which can be
+ * \param native_offset Native offset within the \p method's machine code.
+ * Conventient wrapper around \c mono_debug_lookup_source_location which can be
  * used if you only want to use the location to print a stack frame.
  */
 gchar *
@@ -1175,10 +990,22 @@ mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDom
                        offset = -1;
                }
 
+               if (offset < 0 && get_seq_point)
+                       offset = get_seq_point (domain, method, native_offset);
+
                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);
+               else {
+                       char *mvid = mono_guid_to_string_minimal ((uint8_t*)method->klass->image->heap_guid.data);
+                       char *aotid = mono_runtime_get_aotid ();
+                       if (aotid)
+                               res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
+                       else
+                               res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);
+
+                       g_free (aotid);
+                       g_free (mvid);
+               }
                g_free (fname);
                return res;
        }
@@ -1191,39 +1018,6 @@ mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDom
        return res;
 }
 
-void
-mono_debug_list_add (MonoDebugList **list, gconstpointer data)
-{
-       MonoDebugList *element, **ptr;
-
-       element = g_new0 (MonoDebugList, 1);
-       element->data = data;
-
-       for (ptr = list; *ptr; ptr = &(*ptr)->next)
-               ;
-
-       *ptr = element;
-}
-
-void
-mono_debug_list_remove (MonoDebugList **list, gconstpointer data)
-{
-       MonoDebugList **ptr;
-       MonoDebugList *next;
-
-       for (ptr = list; *ptr; ptr = &(*ptr)->next) {
-               if ((*ptr)->data != data)
-                       continue;
-
-               next = (*ptr)->next;
-               g_free ((*ptr));
-               *ptr = next;
-               break;
-       }
-}
-
-static gboolean is_attached = FALSE;
-
 void
 mono_set_is_debugger_attached (gboolean attached)
 {
@@ -1251,6 +1045,9 @@ struct _BundledSymfile {
 
 static BundledSymfile *bundled_symfiles = NULL;
 
+/**
+ * mono_register_symfile_for_assembly:
+ */
 void
 mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size)
 {
@@ -1279,6 +1076,20 @@ open_symfile_from_bundle (MonoImage *image)
        return NULL;
 }
 
+void
+mono_debugger_lock (void)
+{
+       g_assert (mono_debug_initialized);
+       mono_os_mutex_lock (&debugger_lock_mutex);
+}
+
+void
+mono_debugger_unlock (void)
+{
+       g_assert (mono_debug_initialized);
+       mono_os_mutex_unlock (&debugger_lock_mutex);
+}
+
 /**
  * mono_debug_enabled:
  *
@@ -1289,3 +1100,12 @@ mono_debug_enabled (void)
 {
        return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
 }
+
+void
+mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
+{
+       if (minfo->handle->ppdb)
+               mono_ppdb_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
+       else
+               mono_debug_symfile_get_seq_points (minfo, source_file, source_file_list, source_files, seq_points, n_seq_points);
+}