X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmetadata%2Fdebug-mono-symfile.c;h=9832418bec12990296a243288a4958fdba0f801b;hb=e946a6cdebde729e1c03ec374184254ab38da184;hp=8d3f6f1460909c3cd25a34198a29dd7449d5e6f6;hpb=df54984ae39a677161e9af1553f1f9d3f63b9e8c;p=mono.git diff --git a/mono/metadata/debug-mono-symfile.c b/mono/metadata/debug-mono-symfile.c index 8d3f6f14609..9832418bec1 100644 --- a/mono/metadata/debug-mono-symfile.c +++ b/mono/metadata/debug-mono-symfile.c @@ -5,6 +5,7 @@ * Mono Project (http://www.mono-project.com) * * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com) + * Copyright 2012 Xamarin Inc (http://www.xamarin.com) */ #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -40,18 +42,40 @@ #define TYPE_TABLE_PTR_CHUNK_SIZE 256 #define TYPE_TABLE_CHUNK_SIZE 65536 +struct _MonoSymbolFile { + const uint8_t *raw_contents; + int raw_contents_size; + void *raw_contents_handle; + int major_version; + int minor_version; + char *filename; + GHashTable *method_hash; + GHashTable *source_hash; + MonoSymbolFileOffsetTable *offset_table; + gboolean was_loaded_from_memory; +}; + static void free_method_info (MonoDebugMethodInfo *minfo) { g_free (minfo); } +static void +free_source_info (MonoDebugSourceInfo *sinfo) +{ + g_free (sinfo->source_file); + g_free (sinfo->guid); + g_free (sinfo->hash); + g_free (sinfo); +} + static int -load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_debugger) +load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, mono_bool in_the_debugger) { const char *ptr, *start; gchar *guid; - guint64 magic; + uint64_t magic; int minor, major; ptr = start = (const char*)symfile->raw_contents; @@ -59,7 +83,7 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_ return FALSE; magic = read64(ptr); - ptr += sizeof(guint64); + ptr += sizeof(uint64_t); if (magic != MONO_SYMBOL_FILE_MAGIC) { if (!in_the_debugger) g_warning ("Symbol file %s is not a mono symbol file", symfile->filename); @@ -67,9 +91,9 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_ } major = read32(ptr); - ptr += sizeof(guint32); + ptr += sizeof(uint32_t); minor = read32(ptr); - ptr += sizeof(guint32); + ptr += sizeof(uint32_t); /* * 50.0 is the frozen version for Mono 2.0. @@ -84,7 +108,7 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_ return FALSE; } - guid = mono_guid_to_string ((const guint8 *) ptr); + guid = mono_guid_to_string ((const uint8_t *) ptr); ptr += 16; if (strcmp (handle->image->guid, guid)) { @@ -102,14 +126,17 @@ load_symfile (MonoDebugHandle *handle, MonoSymbolFile *symfile, gboolean in_the_ symfile->offset_table = (MonoSymbolFileOffsetTable *) ptr; symfile->method_hash = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_method_info); + NULL, NULL, NULL, (GDestroyNotify) free_method_info); + + symfile->source_hash = g_hash_table_new_full ( + NULL, NULL, NULL, (GDestroyNotify) free_source_info); g_free (guid); return TRUE; } MonoSymbolFile * -mono_debug_open_mono_symbols (MonoDebugHandle *handle, const guint8 *raw_contents, +mono_debug_open_mono_symbols (MonoDebugHandle *handle, const uint8_t *raw_contents, int size, gboolean in_the_debugger) { MonoSymbolFile *symfile; @@ -178,8 +205,15 @@ mono_debug_close_mono_symbol_file (MonoSymbolFile *symfile) mono_debugger_unlock (); } +mono_bool +mono_debug_symfile_is_loaded (MonoSymbolFile *symfile) +{ + return symfile && symfile->offset_table; +} + + static int -read_leb128 (const guint8 *ptr, const guint8 **rptr) +read_leb128 (const uint8_t *ptr, const uint8_t **rptr) { int ret = 0; int shift = 0; @@ -199,18 +233,24 @@ read_leb128 (const guint8 *ptr, const guint8 **rptr) } static gchar * -read_string (const guint8 *ptr) +read_string (const uint8_t *ptr, const uint8_t **endp) { + gchar *s; int len = read_leb128 (ptr, &ptr); - return g_filename_from_utf8 ((const char *) ptr, len, NULL, NULL, NULL); + + s = g_filename_from_utf8 ((const char *) ptr, len, NULL, NULL, NULL); + ptr += len; + if (endp) + *endp = ptr; + return s; } typedef struct { MonoSymbolFile *symfile; int line_base, line_range, max_address_incr; - guint8 opcode_base; - guint32 last_line, last_file, last_offset; - guint32 first_file; + uint8_t opcode_base; + uint32_t last_line, last_file, last_offset; + uint32_t first_file; int line, file, offset; gboolean is_hidden; } StatementMachine; @@ -234,7 +274,7 @@ check_line (StatementMachine *stm, int offset, MonoDebugSourceLocation **locatio MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (stm->symfile->raw_contents + offset); - source_file = read_string (stm->symfile->raw_contents + read32(&(se->_data_offset))); + source_file = read_string (stm->symfile->raw_contents + read32(&(se->_data_offset)), NULL); } if (stm->last_line == 0) { @@ -264,7 +304,7 @@ check_line (StatementMachine *stm, int offset, MonoDebugSourceLocation **locatio * `native address -> IL offset' mapping. */ MonoDebugSourceLocation * -mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset) +mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset) { MonoDebugSourceLocation *location = NULL; MonoSymbolFile *symfile; @@ -288,7 +328,7 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset) stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base); stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range); - stm.opcode_base = (guint8) read32 (&symfile->offset_table->_line_number_table_opcode_base); + stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base); stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range; mono_debugger_lock (); @@ -305,10 +345,10 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset) stm.is_hidden = FALSE; while (TRUE) { - guint8 opcode = *ptr++; + uint8_t opcode = *ptr++; if (opcode == 0) { - guint8 size = *ptr++; + uint8_t size = *ptr++; const unsigned char *end_ptr = ptr + size; opcode = *ptr++; @@ -371,11 +411,12 @@ mono_debug_symfile_lookup_location (MonoDebugMethodInfo *minfo, guint32 offset) } static void -add_line (StatementMachine *stm, GPtrArray *il_offset_array, GPtrArray *line_number_array) +add_line (StatementMachine *stm, GPtrArray *il_offset_array, GPtrArray *line_number_array, GPtrArray *source_file_array) { if (stm->line > 0) { g_ptr_array_add (il_offset_array, GUINT_TO_POINTER (stm->offset)); g_ptr_array_add (line_number_array, GUINT_TO_POINTER (stm->line)); + g_ptr_array_add (source_file_array, GUINT_TO_POINTER (stm->file)); } if (!stm->is_hidden && !stm->first_file) @@ -396,34 +437,105 @@ mono_debug_symfile_free_location (MonoDebugSourceLocation *location) } /* - * mono_debug_symfile_get_line_numbers: + * LOCKING: Assumes the debugger lock is held. + */ +static MonoDebugSourceInfo* +get_source_info (MonoSymbolFile *symfile, int index) +{ + MonoDebugSourceInfo *info; + + info = g_hash_table_lookup (symfile->source_hash, GUINT_TO_POINTER (index)); + if (!info) { + int offset = read32(&(symfile->offset_table->_source_table_offset)) + + (index - 1) * sizeof (MonoSymbolFileSourceEntry); + MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) + (symfile->raw_contents + offset); + const uint8_t *ptr = symfile->raw_contents + read32(&(se->_data_offset)); + + info = g_new0 (MonoDebugSourceInfo, 1); + info->source_file = read_string (ptr, &ptr); + info->guid = g_malloc0 (16); + memcpy (info->guid, ptr, 16); + ptr += 16; + info->hash = g_malloc0 (16); + memcpy (info->hash, ptr, 16); + ptr += 16; + g_hash_table_insert (symfile->source_hash, GUINT_TO_POINTER (index), info); + } + return info; +} + +static gboolean +method_has_column_info (MonoDebugMethodInfo *minfo) +{ + MonoSymbolFile *symfile; + const unsigned char *ptr; + guint32 flags; + + if ((symfile = minfo->handle->symfile) == NULL) + return FALSE; + + ptr = symfile->raw_contents + minfo->data_offset; + + /* Has to read 'flags' which is preceeded by a bunch of other data */ + /* compile_unit_index */ + read_leb128 (ptr, &ptr); + /* local variable table offset */ + read_leb128 (ptr, &ptr); + /* namespace id */ + read_leb128 (ptr, &ptr); + /* code block table offset */ + read_leb128 (ptr, &ptr); + /* scope variable table offset */ + read_leb128 (ptr, &ptr); + /* real name offset */ + read_leb128 (ptr, &ptr); + + flags = read_leb128 (ptr, &ptr); + return (flags & 2) > 0; +} + +/* + * mono_debug_symfile_get_line_numbers_full: * - * All the output parameters can be NULL. - */ + * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile + * structures, and SOURCE_FILES will contain indexes into this array. + * The MonoDebugSourceFile structures are owned by this module. + */ void -mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_file, int *n_il_offsets, int **il_offsets, int **line_numbers) +mono_debug_symfile_get_line_numbers_full (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int *n_il_offsets, int **il_offsets, int **line_numbers, int **column_numbers, int **source_files) { // FIXME: Unify this with mono_debug_symfile_lookup_location MonoSymbolFile *symfile; const unsigned char *ptr; StatementMachine stm; - guint32 i; - GPtrArray *il_offset_array, *line_number_array; + uint32_t i; + GPtrArray *il_offset_array, *line_number_array, *source_file_array; + gboolean has_column_info; - if (source_file) - *source_file = NULL; + if (source_file_list) + *source_file_list = NULL; if (n_il_offsets) *n_il_offsets = 0; + if (source_files) + *source_files = NULL; + if (source_file) + *source_file = NULL; + if (column_numbers) + *column_numbers = NULL; if ((symfile = minfo->handle->symfile) == NULL) return; + has_column_info = method_has_column_info (minfo); + il_offset_array = g_ptr_array_new (); line_number_array = g_ptr_array_new (); + source_file_array = g_ptr_array_new (); stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base); stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range); - stm.opcode_base = (guint8) read32 (&symfile->offset_table->_line_number_table_opcode_base); + stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base); stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range; mono_debugger_lock (); @@ -440,16 +552,19 @@ mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_f stm.is_hidden = FALSE; while (TRUE) { - guint8 opcode = *ptr++; + uint8_t opcode = *ptr++; if (opcode == 0) { - guint8 size = *ptr++; + uint8_t size = *ptr++; const unsigned char *end_ptr = ptr + size; opcode = *ptr++; if (opcode == DW_LNE_end_sequence) { - add_line (&stm, il_offset_array, line_number_array); + if (il_offset_array->len == 0) + /* Empty table */ + break; + add_line (&stm, il_offset_array, line_number_array, source_file_array); break; } else if (opcode == DW_LNE_MONO_negate_is_hidden) { stm.is_hidden = !stm.is_hidden; @@ -465,7 +580,7 @@ mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_f } else if (opcode < stm.opcode_base) { switch (opcode) { case DW_LNS_copy: - add_line (&stm, il_offset_array, line_number_array); + add_line (&stm, il_offset_array, line_number_array, source_file_array); break; case DW_LNS_advance_pc: stm.offset += read_leb128 (ptr, &ptr); @@ -489,23 +604,48 @@ mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_f stm.offset += opcode / stm.line_range; stm.line += stm.line_base + (opcode % stm.line_range); - add_line (&stm, il_offset_array, line_number_array); + add_line (&stm, il_offset_array, line_number_array, source_file_array); } } if (!stm.file && stm.first_file) stm.file = stm.first_file; - if (stm.file) { + if (stm.file && source_file) { int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) + (stm.file - 1) * sizeof (MonoSymbolFileSourceEntry); MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (stm.symfile->raw_contents + offset); if (source_file) - *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset))); + *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)), NULL); } + if (source_file_list) { + int file, last_file = 0; + + *source_file_list = g_ptr_array_new (); + if (source_files) + *source_files = g_malloc (il_offset_array->len * sizeof (int)); + + for (i = 0; i < il_offset_array->len; ++i) { + file = GPOINTER_TO_UINT (g_ptr_array_index (source_file_array, i)); + if (file && file != last_file) { + MonoDebugSourceInfo *info = get_source_info (symfile, file); + + g_ptr_array_add (*source_file_list, info); + } + last_file = file; + if (source_files) + (*source_files) [i] = (*source_file_list)->len - 1; + } + if ((*source_file_list)->len == 0 && stm.file) { + MonoDebugSourceInfo *info = get_source_info (symfile, stm.file); + + g_ptr_array_add (*source_file_list, info); + } + } + if (n_il_offsets) *n_il_offsets = il_offset_array->len; if (il_offsets && line_numbers) { @@ -516,6 +656,13 @@ mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_f (*line_numbers) [i] = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i)); } } + + if (column_numbers && has_column_info) { + *column_numbers = g_malloc (il_offset_array->len * sizeof (int)); + for (i = 0; i < il_offset_array->len; ++i) + (*column_numbers) [i] = read_leb128 (ptr, &ptr); + } + g_ptr_array_free (il_offset_array, TRUE); g_ptr_array_free (line_number_array, TRUE); @@ -523,8 +670,19 @@ mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_f return; } -gint32 -_mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offset) +/* + * mono_debug_symfile_get_line_numbers: + * + * All the output parameters can be NULL. + */ +void +mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo *minfo, char **source_file, int *n_il_offsets, int **il_offsets, int **line_numbers) +{ + mono_debug_symfile_get_line_numbers_full (minfo, source_file, NULL, n_il_offsets, il_offsets, line_numbers, NULL, NULL); +} + +int32_t +_mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, uint32_t il_offset) { int i; @@ -534,8 +692,6 @@ _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offs for (i = jit->num_line_numbers - 1; i >= 0; i--) { MonoDebugLineNumberEntry lne = jit->line_numbers [i]; - if (lne.il_offset < 0) - continue; if (lne.il_offset <= il_offset) return lne.native_offset; } @@ -546,7 +702,7 @@ _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offs static int compare_method (const void *key, const void *object) { - guint32 token = GPOINTER_TO_UINT (key); + uint32_t token = GPOINTER_TO_UINT (key); MonoSymbolFileMethodEntry *me = (MonoSymbolFileMethodEntry*)object; return token - read32(&(me->_token)); @@ -576,7 +732,7 @@ mono_debug_symfile_lookup_method (MonoDebugHandle *handle, MonoMethod *method) first_ie = (MonoSymbolFileMethodEntry *) (symfile->raw_contents + read32(&(symfile->offset_table->_method_table_offset))); - ie = bsearch (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie, + ie = mono_binary_search (GUINT_TO_POINTER (mono_method_get_token (method)), first_ie, read32(&(symfile->offset_table->_method_count)), sizeof (MonoSymbolFileMethodEntry), compare_method); @@ -610,7 +766,7 @@ MonoDebugLocalsInfo* mono_debug_symfile_lookup_locals (MonoDebugMethodInfo *minfo) { MonoSymbolFile *symfile = minfo->handle->symfile; - const guint8 *p; + const uint8_t *p; int i, len, compile_unit_index, locals_offset, num_locals, block_index; int namespace_id, code_block_table_offset; MonoDebugLocalsInfo *res;