-/*
- * mono-debug.c:
+/**
+ * \file
*
* 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)
* 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);
}
{
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);
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);
}
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)
{
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 ();
}
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));
* 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)
{
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 ();
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);
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;
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;
/**
* 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)
{
*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;
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;
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;
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;
}
void
mono_debug_remove_method (MonoMethod *method, MonoDomain *domain)
{
- MonoMethod *declaring;
MonoDebugDataTable *table;
- MonoDebugMethodHeader *header;
MonoDebugMethodAddress *address;
if (!mono_debug_initialized)
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
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;
}
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;
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)
{
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;
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
/**
* 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)
/**
* 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)
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;
}
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;
}
* 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)
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)
}
}
+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 *
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;
}
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)
{
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)
{
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:
*
{
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);
+}