X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmono-debug.c;h=6eff0ecbda320d6a165b4be0582e800fa2fdc057;hb=2211e3a5d02ca546fdbad2033b8b3d0c817c97c3;hp=e00693296dd096b092155974b7749be8db16d44e;hpb=c7166273ee53fb2f1751e6714fb60b66aa579e2d;p=mono.git diff --git a/mono/metadata/mono-debug.c b/mono/metadata/mono-debug.c index e00693296dd..6eff0ecbda3 100644 --- a/mono/metadata/mono-debug.c +++ b/mono/metadata/mono-debug.c @@ -1,3 +1,14 @@ +/* + * 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) + * Copyright 2011 Xamarin Inc (http://www.xamarin.com) + */ + #include #include #include @@ -7,9 +18,10 @@ #include #include #include +#include #include -#define DATA_TABLE_CHUNK_SIZE 16384 +#define DATA_TABLE_CHUNK_SIZE (16384-sizeof (MonoDebugDataChunk)) #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) @@ -62,7 +74,7 @@ struct _MonoDebugDataTable { typedef struct { const gchar *method_name; - const gchar *cil_code; + const gchar *obsolete_cil_code; guint32 wrapper_type; } MonoDebugWrapperData; @@ -96,11 +108,11 @@ typedef struct { MonoSymbolTable *mono_symbol_table = NULL; MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE; -gint32 mono_debug_debugger_version = 3; +gint32 mono_debug_debugger_version = 5; +gint32 _mono_debug_using_mono_debugger = 0; -static gboolean in_the_mono_debugger = FALSE; static gboolean mono_debug_initialized = FALSE; -GHashTable *mono_debug_handles = NULL; +static GHashTable *mono_debug_handles = NULL; static GHashTable *data_table_hash = NULL; static int next_symbol_file_id = 0; @@ -112,6 +124,8 @@ 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); @@ -149,10 +163,9 @@ 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); } + g_slist_free (header->address_list); } static void @@ -185,7 +198,10 @@ lookup_data_table (MonoDomain *domain) MonoDebugDataTable *table; table = g_hash_table_lookup (data_table_hash, domain); - g_assert (table); + if (!table) { + g_error ("lookup_data_table () failed for %p\n", domain); + g_assert (table); + } return table; } @@ -213,17 +229,25 @@ 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; - in_the_mono_debugger = format == MONO_DEBUG_FORMAT_DEBUGGER; - mono_debugger_initialize (in_the_mono_debugger); + /* + * This must be called before mono_debugger_initialize(), because the + * latter registers GC roots. + */ + mono_gc_base_init (); + + mono_debugger_initialize (_mono_debug_using_mono_debugger); mono_debugger_lock (); mono_symbol_table = g_new0 (MonoSymbolTable, 1); mono_symbol_table->magic = MONO_DEBUGGER_MAGIC; - mono_symbol_table->version = MONO_DEBUGGER_VERSION; + mono_symbol_table->version = MONO_DEBUGGER_MAJOR_VERSION; mono_symbol_table->total_size = sizeof (MonoSymbolTable); mono_debug_handles = g_hash_table_new_full @@ -258,6 +282,9 @@ _mono_debug_init_corlib (MonoDomain *domain) void mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, int size) { + if (!mono_debug_initialized) + return; + mono_debug_open_image (image, raw_contents, size); } @@ -265,7 +292,7 @@ mono_debug_open_image_from_memory (MonoImage *image, const guint8 *raw_contents, gboolean mono_debug_using_mono_debugger (void) { - return in_the_mono_debugger; + return _mono_debug_using_mono_debugger; } void @@ -280,8 +307,13 @@ mono_debug_cleanup (void) data_table_hash = NULL; } - g_free (mono_symbol_table); - mono_symbol_table = 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; + } } void @@ -328,6 +360,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) { @@ -342,11 +377,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); @@ -365,11 +402,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; @@ -380,7 +419,8 @@ mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size) handle->type_table = create_data_table (NULL); - handle->symfile = mono_debug_open_mono_symbols (handle, raw_contents, size, in_the_mono_debugger); + handle->symfile = mono_debug_open_mono_symbols ( + handle, raw_contents, size, _mono_debug_using_mono_debugger); mono_debug_list_add (&mono_symbol_table->symbol_files, handle); @@ -398,8 +438,14 @@ mono_debug_open_image (MonoImage *image, const guint8 *raw_contents, int size) static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data) { + MonoDebugHandle *handle; + MonoImage *image; + mono_debugger_lock (); - mono_debug_open_image (mono_assembly_get_image (assembly), NULL, 0); + image = mono_assembly_get_image (assembly); + handle = open_symfile_from_bundle (image); + if (!handle) + mono_debug_open_image (image, NULL, 0); mono_debugger_unlock (); } @@ -558,7 +604,6 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma guint8 buffer [BUFSIZ]; guint8 *ptr, *oldptr; guint32 i, size, total_size, max_size; - gint32 last_il_offset = 0, last_native_offset = 0; gboolean is_wrapper = FALSE; mono_debugger_lock (); @@ -576,10 +621,8 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma is_wrapper = TRUE; } - jit->num_lexical_blocks = minfo ? minfo->num_lexical_blocks : 0; - - max_size = 24 + 8 * jit->num_line_numbers + 16 * jit->num_lexical_blocks + - (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); @@ -593,41 +636,8 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma for (i = 0; i < jit->num_line_numbers; i++) { MonoDebugLineNumberEntry *lne = &jit->line_numbers [i]; - write_sleb128 (lne->il_offset - last_il_offset, ptr, &ptr); - write_sleb128 (lne->native_offset - last_native_offset, ptr, &ptr); - - last_il_offset = lne->il_offset; - last_native_offset = lne->native_offset; - } - - jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks); - for (i = 0; i < jit->num_lexical_blocks; i ++) { - MonoDebugLexicalBlockEntry *jit_lbe = &jit->lexical_blocks [i]; - MonoSymbolFileLexicalBlockEntry *minfo_lbe = &minfo->lexical_blocks [i]; - jit_lbe->il_start_offset = read32 (&(minfo_lbe->_start_offset)); - jit_lbe->native_start_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_start_offset); - - jit_lbe->il_end_offset = read32 (&(minfo_lbe->_end_offset)); - jit_lbe->native_end_offset = _mono_debug_address_from_il_offset (jit, jit_lbe->il_end_offset); - } - - last_il_offset = 0; - last_native_offset = 0; - write_leb128 (jit->num_lexical_blocks, ptr, &ptr); - for (i = 0; i < jit->num_lexical_blocks; i++) { - MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i]; - - write_sleb128 (lbe->il_start_offset - last_il_offset, ptr, &ptr); - write_sleb128 (lbe->native_start_offset - last_native_offset, ptr, &ptr); - - last_il_offset = lbe->il_start_offset; - last_native_offset = lbe->native_start_offset; - - write_sleb128 (lbe->il_end_offset - last_il_offset, ptr, &ptr); - write_sleb128 (lbe->native_end_offset - last_native_offset, ptr, &ptr); - - last_il_offset = lbe->il_end_offset; - last_native_offset = lbe->native_end_offset; + write_sleb128 (lne->il_offset, ptr, &ptr); + write_sleb128 (lne->native_offset, ptr, &ptr); } *ptr++ = jit->this_var ? 1 : 0; @@ -642,12 +652,22 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma 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; g_assert (size < max_size); total_size = size + sizeof (MonoDebugMethodAddress); - address = (MonoDebugMethodAddress *) allocate_data_item ( - table, MONO_DEBUG_DATA_ITEM_METHOD, total_size); + if (method->dynamic) { + address = g_malloc0 (total_size); + } else { + address = (MonoDebugMethodAddress *) allocate_data_item ( + table, MONO_DEBUG_DATA_ITEM_METHOD, total_size); + } address->header.size = total_size; address->header.symfile_id = handle ? handle->index : 0; @@ -670,20 +690,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; @@ -692,12 +705,49 @@ mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDoma g_hash_table_insert (table->method_address_hash, method, address); - write_data_item (table, (guint8 *) address); + if (!method->dynamic) + 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) + return; + + g_assert (method->dynamic); + + mono_debugger_lock (); + + 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); + } + g_free (address); + } + + g_hash_table_remove (table->method_address_hash, method); + + mono_debugger_unlock (); +} + void mono_debug_add_delegate_trampoline (gpointer code, int size) { @@ -774,11 +824,25 @@ read_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr) *rptr = ptr; } +void +mono_debug_free_method_jit_info (MonoDebugMethodJitInfo *jit) +{ + if (!jit) + return; + g_free (jit->line_numbers); + g_free (jit->this_var); + g_free (jit->params); + g_free (jit->locals); + g_free (jit->gsharedvt_info_var); + g_free (jit->gsharedvt_locals_var); + g_free (jit); +} + static MonoDebugMethodJitInfo * mono_debug_read_method (MonoDebugMethodAddress *address) { MonoDebugMethodJitInfo *jit; - guint32 i, il_offset = 0, native_offset = 0; + guint32 i; guint8 *ptr; jit = g_new0 (MonoDebugMethodJitInfo, 1); @@ -796,31 +860,8 @@ mono_debug_read_method (MonoDebugMethodAddress *address) for (i = 0; i < jit->num_line_numbers; i++) { MonoDebugLineNumberEntry *lne = &jit->line_numbers [i]; - il_offset += read_sleb128 (ptr, &ptr); - native_offset += read_sleb128 (ptr, &ptr); - - lne->il_offset = il_offset; - lne->native_offset = native_offset; - } - - il_offset = 0; - native_offset = 0; - jit->num_lexical_blocks = read_leb128 (ptr, &ptr); - jit->lexical_blocks = g_new0 (MonoDebugLexicalBlockEntry, jit->num_lexical_blocks); - for (i = 0; i < jit->num_lexical_blocks; i ++) { - MonoDebugLexicalBlockEntry *lbe = &jit->lexical_blocks [i]; - - il_offset += read_sleb128 (ptr, &ptr); - native_offset += read_sleb128 (ptr, &ptr); - - lbe->il_start_offset = il_offset; - lbe->native_start_offset = native_offset; - - il_offset += read_sleb128 (ptr, &ptr); - native_offset += read_sleb128 (ptr, &ptr); - - lbe->il_end_offset = il_offset; - lbe->native_end_offset = native_offset; + lne->il_offset = read_sleb128 (ptr, &ptr); + lne->native_offset = read_sleb128 (ptr, &ptr); } if (*ptr++) { @@ -838,6 +879,13 @@ mono_debug_read_method (MonoDebugMethodAddress *address) 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; } @@ -851,16 +899,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); @@ -915,6 +965,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 (); @@ -950,7 +1004,7 @@ mono_debug_lookup_method_addresses (MonoMethod *method) GSList *list; guint8 *ptr; - g_assert (mono_debug_debugger_version == 3); + g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5)); mono_debugger_lock (); @@ -996,18 +1050,42 @@ il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_o jit = find_method (method, domain); if (!jit || !jit->line_numbers) - return -1; + goto cleanup_and_fail; for (i = jit->num_line_numbers - 1; i >= 0; i--) { MonoDebugLineNumberEntry lne = jit->line_numbers [i]; - if (lne.native_offset <= native_offset) + if (lne.native_offset <= native_offset) { + mono_debug_free_method_jit_info (jit); return lne.il_offset; + } } +cleanup_and_fail: + mono_debug_free_method_jit_info (jit); 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. @@ -1031,7 +1109,7 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma mono_debugger_lock (); minfo = _mono_debug_lookup_method (method); - if (!minfo || !minfo->handle || !minfo->handle->symfile || !minfo->handle->symfile->offset_table) { + if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) { mono_debugger_unlock (); return NULL; } @@ -1047,6 +1125,34 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma 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 (). + */ +MonoDebugLocalsInfo* +mono_debug_lookup_locals (MonoMethod *method) +{ + MonoDebugMethodInfo *minfo; + MonoDebugLocalsInfo *res; + + 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 || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) { + mono_debugger_unlock (); + return NULL; + } + + res = mono_debug_symfile_lookup_locals (minfo); + mono_debugger_unlock (); + + return res; +} + /** * mono_debug_free_source_location: * @location: A `MonoDebugSourceLocation'. @@ -1074,6 +1180,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++) { @@ -1083,7 +1190,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 ", fname, offset, native_offset); g_free (fname); return res; } @@ -1126,3 +1244,60 @@ 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; +} + +/* + * Bundles + */ + +typedef struct _BundledSymfile BundledSymfile; + +struct _BundledSymfile { + BundledSymfile *next; + const char *aname; + const mono_byte *raw_contents; + int size; +}; + +static BundledSymfile *bundled_symfiles = NULL; + +void +mono_register_symfile_for_assembly (const char *assembly_name, const mono_byte *raw_contents, int size) +{ + BundledSymfile *bsymfile; + + bsymfile = g_new0 (BundledSymfile, 1); + bsymfile->aname = assembly_name; + bsymfile->raw_contents = raw_contents; + bsymfile->size = size; + bsymfile->next = bundled_symfiles; + bundled_symfiles = bsymfile; +} + +static MonoDebugHandle * +open_symfile_from_bundle (MonoImage *image) +{ + BundledSymfile *bsymfile; + + for (bsymfile = bundled_symfiles; bsymfile; bsymfile = bsymfile->next) { + if (strcmp (bsymfile->aname, image->module_name)) + continue; + + return mono_debug_open_image (image, bsymfile->raw_contents, bsymfile->size); + } + + return NULL; +}