X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdwarfwriter.c;h=2f216dda226e0456f03c6df7c38fda188a367ed3;hb=32455dbbe90d3f7826a2bae5a95360e050f04172;hp=0fd42f91d34fa5c39ab449a7a0e2f455d9585210;hpb=bab56f4f78baa882473dfedcd9a5eac703b0b64b;p=mono.git diff --git a/mono/mini/dwarfwriter.c b/mono/mini/dwarfwriter.c index 0fd42f91d34..2f216dda226 100644 --- a/mono/mini/dwarfwriter.c +++ b/mono/mini/dwarfwriter.c @@ -30,21 +30,37 @@ #include +typedef struct { + MonoMethod *method; + char *start_symbol, *end_symbol; + guint8 *code; + guint32 code_size; + MonoDebugMethodJitInfo *debug_info; +} MethodLineNumberInfo; + struct _MonoDwarfWriter { MonoImageWriter *w; GHashTable *class_to_die, *class_to_vtype_die, *class_to_pointer_die; GHashTable *class_to_reference_die; int fde_index, tdie_index, line_number_file_index, line_number_dir_index; - GHashTable *file_to_index, *dir_to_index; + GHashTable *file_to_index, *index_to_file, *dir_to_index; FILE *il_file; int il_file_line_index, loclist_index; GSList *cie_program; FILE *fp; const char *temp_prefix; - gboolean emit_line, appending; + gboolean emit_line, appending, collect_line_info; + GSList *line_info; + int cur_file_index; }; +static void +emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, + char *start_symbol, char *end_symbol, + guint8 *code, guint32 code_size, + MonoDebugMethodJitInfo *debug_info); + /* * mono_dwarf_writer_create: * @@ -78,9 +94,26 @@ mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_st if (appending) g_assert (img_writer_subsections_supported (w->w)); + w->emit_line = TRUE; + + if (appending) { + if (!img_writer_subsections_supported (w->w)) + /* Can't emit line number info without subsections */ + w->emit_line = FALSE; + } else { + /* Collect line number info and emit it at once */ + w->collect_line_info = TRUE; + } + w->fp = img_writer_get_fp (w->w); w->temp_prefix = img_writer_get_temp_label_prefix (w->w); + w->class_to_die = g_hash_table_new (NULL, NULL); + w->class_to_vtype_die = g_hash_table_new (NULL, NULL); + w->class_to_pointer_die = g_hash_table_new (NULL, NULL); + w->class_to_reference_die = g_hash_table_new (NULL, NULL); + w->cur_file_index = -1; + return w; } @@ -373,7 +406,8 @@ emit_fde (MonoDwarfWriter *w, int fde_index, char *start_symbol, char *end_symbo int i; for (i = 0; i < g_slist_length (w->cie_program); ++i) - l = l->next; + if (l) + l = l->next; } /* Convert the list of MonoUnwindOps to the format used by DWARF */ @@ -403,6 +437,7 @@ emit_fde (MonoDwarfWriter *w, int fde_index, char *start_symbol, char *end_symbo #define ABBREV_PARAM_LOCLIST 15 #define ABBREV_INHERITANCE 16 #define ABBREV_STRUCT_TYPE_NOCHILDREN 17 +#define ABBREV_TRAMP_SUBPROGRAM 18 static int compile_unit_attr [] = { DW_AT_producer ,DW_FORM_string, @@ -416,11 +451,23 @@ static int compile_unit_attr [] = { static int subprogram_attr [] = { DW_AT_name , DW_FORM_string, +#ifndef TARGET_IOS + DW_AT_description , DW_FORM_string, +#endif DW_AT_low_pc , DW_FORM_addr, DW_AT_high_pc , DW_FORM_addr, DW_AT_frame_base , DW_FORM_block1 }; +static int tramp_subprogram_attr [] = { + DW_AT_name , DW_FORM_string, +#ifndef TARGET_IOS + DW_AT_description , DW_FORM_string, +#endif + DW_AT_low_pc , DW_FORM_addr, + DW_AT_high_pc , DW_FORM_addr, +}; + static int param_attr [] = { DW_AT_name, DW_FORM_string, DW_AT_type, DW_FORM_ref4, @@ -592,6 +639,41 @@ emit_line_number_file_name (MonoDwarfWriter *w, const char *name, return index; } +static int +get_line_number_file_name (MonoDwarfWriter *w, const char *name) +{ + int index; + + g_assert (w->file_to_index); + index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name)); + g_assert (index > 0); + return index - 1; +} + +static int +add_line_number_file_name (MonoDwarfWriter *w, const char *name, + gint64 last_mod_time, gint64 file_size) +{ + int index; + char *copy; + + if (!w->file_to_index) { + w->file_to_index = g_hash_table_new (g_str_hash, g_str_equal); + w->index_to_file = g_hash_table_new (NULL, NULL); + } + + index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name)); + if (index > 0) + return index - 1; + index = w->line_number_file_index; + w->line_number_file_index ++; + copy = g_strdup (name); + g_hash_table_insert (w->file_to_index, copy, GUINT_TO_POINTER (index + 1)); + g_hash_table_insert (w->index_to_file, GUINT_TO_POINTER (index + 1), copy); + + return index; +} + static void emit_line_number_info_begin (MonoDwarfWriter *w) { @@ -655,6 +737,163 @@ emit_line_number_info_begin (MonoDwarfWriter *w) emit_label (w, ".Ldebug_line_end"); } +static char * +escape_path (char *name) +{ + if (strchr (name, '\\')) { + char *s = g_malloc (strlen (name) * 2); + int len, i, j; + + len = strlen (name); + j = 0; + for (i = 0; i < len; ++i) { + if (name [i] == '\\') { + s [j ++] = '\\'; + s [j ++] = '\\'; + } else { + s [j ++] = name [i]; + } + } + return s; + } + return name; +} + +static void +emit_all_line_number_info (MonoDwarfWriter *w) +{ + int i; + GHashTable *dir_to_index, *index_to_dir; + GSList *l; + GSList *info_list; + + g_assert (w->collect_line_info); + + add_line_number_file_name (w, "", 0, 0); + + /* Collect files */ + info_list = g_slist_reverse (w->line_info); + for (l = info_list; l; l = l->next) { + MethodLineNumberInfo *info = l->data; + MonoDebugMethodInfo *minfo; + char *source_file; + GPtrArray *source_file_list; + + // FIXME: Free stuff + minfo = mono_debug_lookup_method (info->method); + if (!minfo) + continue; + + mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, NULL, NULL, NULL, NULL, NULL); + for (i = 0; i < source_file_list->len; ++i) { + MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, i); + add_line_number_file_name (w, sinfo->source_file, 0, 0); + } + } + + /* Preprocess files */ + dir_to_index = g_hash_table_new (g_str_hash, g_str_equal); + index_to_dir = g_hash_table_new (NULL, NULL); + for (i = 0; i < w->line_number_file_index; ++i) { + char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1)); + char *copy; + int dir_index = 0; + + if (g_path_is_absolute (name)) { + char *dir = g_path_get_dirname (name); + + dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (dir_to_index, dir)); + if (dir_index == 0) { + dir_index = w->line_number_dir_index; + w->line_number_dir_index ++; + copy = g_strdup (dir); + g_hash_table_insert (dir_to_index, copy, GUINT_TO_POINTER (dir_index + 1)); + g_hash_table_insert (index_to_dir, GUINT_TO_POINTER (dir_index + 1), copy); + } else { + dir_index --; + } + + g_free (dir); + } + } + + /* Line number info header */ + emit_section_change (w, ".debug_line", 0); + emit_label (w, ".Ldebug_line_section_start"); + emit_label (w, ".Ldebug_line_start"); + emit_symbol_diff (w, ".Ldebug_line_end", ".", -4); /* length */ + emit_int16 (w, 0x2); /* version */ + emit_symbol_diff (w, ".Ldebug_line_header_end", ".", -4); /* header_length */ + emit_byte (w, 1); /* minimum_instruction_length */ + emit_byte (w, 1); /* default_is_stmt */ + emit_byte (w, LINE_BASE); /* line_base */ + emit_byte (w, LINE_RANGE); /* line_range */ + emit_byte (w, OPCODE_BASE); /* opcode_base */ + emit_byte (w, 0); /* standard_opcode_lengths */ + emit_byte (w, 1); + emit_byte (w, 1); + emit_byte (w, 1); + emit_byte (w, 1); + emit_byte (w, 0); + emit_byte (w, 0); + emit_byte (w, 0); + emit_byte (w, 1); + emit_byte (w, 0); + emit_byte (w, 0); + emit_byte (w, 1); + + /* Includes */ + emit_section_change (w, ".debug_line", 0); + for (i = 0; i < w->line_number_dir_index; ++i) { + char *dir = g_hash_table_lookup (index_to_dir, GUINT_TO_POINTER (i + 1)); + + emit_string (w, escape_path (dir)); + } + /* End of Includes */ + emit_byte (w, 0); + + /* Files */ + for (i = 0; i < w->line_number_file_index; ++i) { + char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1)); + char *basename = NULL, *dir; + int dir_index = 0; + + if (g_path_is_absolute (name)) { + dir = g_path_get_dirname (name); + + dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (dir_to_index, dir)); + basename = g_path_get_basename (name); + } + + if (basename) + emit_string (w, basename); + else + emit_string (w, escape_path (name)); + emit_uleb128 (w, dir_index); + emit_byte (w, 0); + emit_byte (w, 0); + } + + /* End of Files */ + emit_byte (w, 0); + + emit_label (w, ".Ldebug_line_header_end"); + + /* Emit line number table */ + for (l = info_list; l; l = l->next) { + MethodLineNumberInfo *info = l->data; + + emit_line_number_info (w, info->method, info->start_symbol, info->end_symbol, info->code, info->code_size, info->debug_info); + } + g_slist_free (info_list); + + emit_byte (w, 0); + emit_byte (w, 1); + emit_byte (w, DW_LNE_end_sequence); + + emit_label (w, ".Ldebug_line_end"); +} + /* * Some assemblers like apple's do not support subsections, so we can't place * .Ldebug_info_end at the end of the section using subsections. Instead, we @@ -677,12 +916,6 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra char *s, *build_info; int i; - if (!img_writer_subsections_supported (w->w)) - /* Can't emit line number info without subsections */ - w->emit_line = FALSE; - else - w->emit_line = TRUE; - w->cie_program = base_unwind_program; emit_section_change (w, ".debug_abbrev", 0); @@ -720,6 +953,8 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra reference_type_attr, G_N_ELEMENTS (reference_type_attr)); emit_dwarf_abbrev (w, ABBREV_INHERITANCE, DW_TAG_inheritance, FALSE, inheritance_attr, G_N_ELEMENTS (inheritance_attr)); + emit_dwarf_abbrev (w, ABBREV_TRAMP_SUBPROGRAM, DW_TAG_subprogram, FALSE, + tramp_subprogram_attr, G_N_ELEMENTS (tramp_subprogram_attr)); emit_byte (w, 0); emit_section_change (w, ".debug_info", 0); @@ -773,7 +1008,8 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra * We emit some info even if emit_line is FALSE, as the * apple linker seems to require a .debug_line section. */ - emit_line_number_info_begin (w); + if (!w->collect_line_info) + emit_line_number_info_begin (w); emit_cie (w); } @@ -791,9 +1027,26 @@ mono_dwarf_writer_close (MonoDwarfWriter *w) emit_byte (w, 0); /* close COMPILE_UNIT */ emit_label (w, ".Ldebug_info_end"); } + + if (w->collect_line_info) + emit_all_line_number_info (w); } -static const char* emit_type (MonoDwarfWriter *w, MonoType *t); +static void emit_type (MonoDwarfWriter *w, MonoType *t); +static const char* get_type_die (MonoDwarfWriter *w, MonoType *t); + +static const char* +get_class_die (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype) +{ + GHashTable *cache; + + if (vtype) + cache = w->class_to_vtype_die; + else + cache = w->class_to_die; + + return g_hash_table_lookup (cache, klass); +} /* Returns the local symbol pointing to the emitted debug info */ static char* @@ -808,16 +1061,6 @@ emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype) gboolean emit_namespace = FALSE, has_children; GHashTable *cache; - // FIXME: Appdomains - if (!w->class_to_die) - w->class_to_die = g_hash_table_new (NULL, NULL); - if (!w->class_to_vtype_die) - w->class_to_vtype_die = g_hash_table_new (NULL, NULL); - if (!w->class_to_pointer_die) - w->class_to_pointer_die = g_hash_table_new (NULL, NULL); - if (!w->class_to_reference_die) - w->class_to_reference_die = g_hash_table_new (NULL, NULL); - if (vtype) cache = w->class_to_vtype_die; else @@ -827,7 +1070,8 @@ emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype) if (die) return die; - if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || (klass->byval_arg.type == MONO_TYPE_OBJECT) || klass->byval_arg.type == MONO_TYPE_GENERICINST || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype))) + if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || (klass->byval_arg.type == MONO_TYPE_OBJECT) || klass->byval_arg.type == MONO_TYPE_GENERICINST || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype) || + (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8 && !vtype))) return NULL; /* @@ -969,7 +1213,7 @@ emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype) if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; - fdie = emit_type (w, field->type); + fdie = get_type_die (w, field->type); if (fdie) { emit_uleb128 (w, ABBREV_DATA_MEMBER); emit_string (w, field->name); @@ -1019,8 +1263,10 @@ emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype) return die; } +static gboolean base_types_emitted [64]; + static const char* -emit_type (MonoDwarfWriter *w, MonoType *t) +get_type_die (MonoDwarfWriter *w, MonoType *t) { MonoClass *klass = mono_class_from_mono_type (t); int j; @@ -1028,12 +1274,10 @@ emit_type (MonoDwarfWriter *w, MonoType *t) if (t->byref) { if (t->type == MONO_TYPE_VALUETYPE) { - tdie = emit_class_dwarf_info (w, klass, TRUE); - if (tdie) - return g_hash_table_lookup (w->class_to_pointer_die, klass); + tdie = g_hash_table_lookup (w->class_to_pointer_die, klass); } else { - tdie = emit_class_dwarf_info (w, klass, FALSE); + tdie = get_class_die (w, klass, FALSE); /* Should return a pointer type to a reference */ } // FIXME: @@ -1042,12 +1286,11 @@ emit_type (MonoDwarfWriter *w, MonoType *t) for (j = 0; j < G_N_ELEMENTS (basic_types); ++j) if (basic_types [j].type == t->type) break; - if (j < G_N_ELEMENTS (basic_types)) + if (j < G_N_ELEMENTS (basic_types)) { tdie = basic_types [j].die_name; - else { + } else { switch (t->type) { case MONO_TYPE_CLASS: - emit_class_dwarf_info (w, klass, FALSE); tdie = g_hash_table_lookup (w->class_to_reference_die, klass); //tdie = ".LDIE_OBJECT"; break; @@ -1056,13 +1299,12 @@ emit_type (MonoDwarfWriter *w, MonoType *t) break; case MONO_TYPE_VALUETYPE: if (klass->enumtype) - tdie = emit_class_dwarf_info (w, klass, FALSE); + tdie = get_class_die (w, klass, FALSE); else tdie = ".LDIE_I4"; break; case MONO_TYPE_GENERICINST: if (!MONO_TYPE_ISSTRUCT (t)) { - emit_class_dwarf_info (w, klass, FALSE); tdie = g_hash_table_lookup (w->class_to_reference_die, klass); } else { tdie = ".LDIE_I4"; @@ -1077,15 +1319,68 @@ emit_type (MonoDwarfWriter *w, MonoType *t) } } + g_assert (tdie); + return tdie; } +static void +emit_type (MonoDwarfWriter *w, MonoType *t) +{ + MonoClass *klass = mono_class_from_mono_type (t); + int j; + const char *tdie; + + if (t->byref) { + if (t->type == MONO_TYPE_VALUETYPE) { + tdie = emit_class_dwarf_info (w, klass, TRUE); + if (tdie) + return; + } + else { + emit_class_dwarf_info (w, klass, FALSE); + } + // FIXME: + t = &mono_defaults.int_class->byval_arg; + } + for (j = 0; j < G_N_ELEMENTS (basic_types); ++j) + if (basic_types [j].type == t->type) + break; + if (j < G_N_ELEMENTS (basic_types)) { + /* Emit a boxed version of base types */ + if (j < 64 && !base_types_emitted [j]) { + emit_class_dwarf_info (w, klass, FALSE); + base_types_emitted [j] = TRUE; + } + } else { + switch (t->type) { + case MONO_TYPE_CLASS: + emit_class_dwarf_info (w, klass, FALSE); + break; + case MONO_TYPE_ARRAY: + break; + case MONO_TYPE_VALUETYPE: + if (klass->enumtype) + emit_class_dwarf_info (w, klass, FALSE); + break; + case MONO_TYPE_GENERICINST: + if (!MONO_TYPE_ISSTRUCT (t)) + emit_class_dwarf_info (w, klass, FALSE); + break; + case MONO_TYPE_PTR: + break; + default: + break; + } + } +} + static void emit_var_type (MonoDwarfWriter *w, MonoType *t) { const char *tdie; - tdie = emit_type (w, t); + tdie = get_type_die (w, t); emit_symbol_diff (w, tdie, ".Ldebug_info_start", 0); } @@ -1306,6 +1601,7 @@ emit_advance_op (MonoDwarfWriter *w, int line_diff, int addr_diff) if (opcode != 0) { emit_byte (w, opcode); } else { + //printf ("large: %d %d %d\n", line_diff, addr_diff, max_special_addr_diff); emit_byte (w, DW_LNS_advance_line); emit_sleb128 (w, line_diff); emit_byte (w, DW_LNS_advance_pc); @@ -1339,7 +1635,7 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, MonoDebugMethodInfo *minfo; MonoDebugLineNumberEntry *ln_array; int *native_to_il_offset = NULL; - + if (!w->emit_line) { mono_metadata_free_mh (header); return; @@ -1383,6 +1679,8 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, prev_il_offset = -1; for (i = 0; i < code_size; ++i) { + int line_diff, addr_diff; + if (!minfo) continue; @@ -1409,60 +1707,63 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, prev_il_offset = il_offset; loc = mono_debug_symfile_lookup_location (minfo, il_offset); + if (!(loc && loc->source_file)) + continue; - // Added the loc->source_file check as otherwise we can - // crash, see the sample in bug 553191 that makes this code - // crash when we call strcmp on loc->source_file below - if (loc && loc->source_file) { - int line_diff = (gint32)loc->row - (gint32)prev_line; - int addr_diff = i - prev_native_offset; - - if (first) { - emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA); - - emit_byte (w, 0); - emit_byte (w, sizeof (gpointer) + 1); - emit_byte (w, DW_LNE_set_address); - if (start_symbol) - emit_pointer_unaligned (w, start_symbol); - else - emit_pointer_value (w, code); + line_diff = (gint32)loc->row - (gint32)prev_line; + addr_diff = i - prev_native_offset; - /* - * The prolog+initlocals region does not have a line number, this - * makes them belong to the first line of the method. - */ - emit_byte (w, DW_LNS_advance_line); - emit_sleb128 (w, (gint32)loc->row - (gint32)prev_line); - prev_line = loc->row; - } + if (first) { + emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA); + + emit_byte (w, 0); + emit_byte (w, sizeof (gpointer) + 1); + emit_byte (w, DW_LNE_set_address); + if (start_symbol) + emit_pointer_unaligned (w, start_symbol); + else + emit_pointer_value (w, code); + + /* + * The prolog+initlocals region does not have a line number, this + * makes them belong to the first line of the method. + */ + emit_byte (w, DW_LNS_advance_line); + //printf ("FIRST: %d %d %d\n", prev_line, loc->row, il_offset); + emit_sleb128 (w, (gint32)loc->row - (gint32)prev_line); + prev_line = loc->row; + first = FALSE; + } - if (loc->row != prev_line) { - if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) { - /* Add an entry to the file table */ - /* FIXME: Avoid duplicates */ + if (loc->row != prev_line) { + if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) { + /* Add an entry to the file table */ + /* FIXME: Avoid duplicates */ + if (w->collect_line_info) + file_index = get_line_number_file_name (w, loc->source_file) + 1; + else file_index = emit_line_number_file_name (w, loc->source_file, 0, 0); - g_free (prev_file_name); - prev_file_name = g_strdup (loc->source_file); + g_free (prev_file_name); + prev_file_name = g_strdup (loc->source_file); + if (w->cur_file_index != file_index) { emit_byte (w, DW_LNS_set_file); emit_uleb128 (w, file_index); emit_byte (w, DW_LNS_copy); - } - - //printf ("X: %p(+0x%x) %d %s:%d(+%d)\n", code + i, addr_diff, loc->il_offset, loc->source_file, loc->row, line_diff); - - emit_advance_op (w, line_diff, addr_diff); - - prev_line = loc->row; - prev_native_offset = i; + w->cur_file_index = file_index; + } } + //printf ("X: %p(+0x%x) %d %s:%d(+%d)\n", code + i, addr_diff, loc->il_offset, loc->source_file, loc->row, line_diff); + emit_advance_op (w, line_diff, addr_diff); - first = FALSE; - g_free (loc); + prev_line = loc->row; + prev_native_offset = i; } + + mono_debug_symfile_free_location (loc); } + g_free (native_to_il_offset); g_free (prev_file_name); if (!first) { @@ -1582,10 +1883,9 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod char *name; MonoMethodSignature *sig; MonoMethodHeader *header; - char **names, **tdies, **local_tdies; - char **local_names; - int *local_indexes; - int i, num_locals; + char **names; + MonoDebugLocalsInfo *locals_info; + int i; guint8 buf [128]; guint8 *p; @@ -1595,7 +1895,6 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod header = mono_method_get_header (method); /* Parameter types */ - tdies = g_new0 (char *, sig->param_count + sig->hasthis); for (i = 0; i < sig->param_count + sig->hasthis; ++i) { MonoType *t; @@ -1610,9 +1909,9 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod emit_type (w, t); } + //emit_type (w, &mono_defaults.int32_class->byval_arg); /* Local types */ - local_tdies = g_new0 (char *, header->num_locals); for (i = 0; i < header->num_locals; ++i) { emit_type (w, header->locals [i]); } @@ -1624,6 +1923,9 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod emit_uleb128 (w, ABBREV_SUBPROGRAM); name = mono_method_full_name (method, FALSE); emit_string (w, name); +#ifndef TARGET_IOS + emit_string (w, name); +#endif g_free (name); if (start_symbol) { emit_pointer_unaligned (w, start_symbol); @@ -1690,7 +1992,7 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod g_free (names); /* Locals */ - num_locals = mono_debug_lookup_locals (method, &local_names, &local_indexes); + locals_info = mono_debug_lookup_locals (method); for (i = 0; i < header->num_locals; ++i) { MonoInst *ins = locals [i]; @@ -1698,6 +2000,7 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod int j; MonoMethodVar *vmv = NULL; gboolean need_loclist = FALSE; + char *lname; /* ins->dreg no longer contains the original vreg */ vmv = find_vmv (cfg, ins); @@ -1710,11 +2013,16 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod emit_uleb128 (w, need_loclist ? ABBREV_VARIABLE_LOCLIST : ABBREV_VARIABLE); /* name */ - for (j = 0; j < num_locals; ++j) - if (local_indexes [j] == i) - break; - if (j < num_locals) { - emit_string (w, local_names [j]); + lname = NULL; + if (locals_info) { + for (j = 0; j < locals_info->num_locals; ++j) + if (locals_info->locals [j].index == i) + break; + if (j < locals_info->num_locals) + lname = locals_info->locals [j].name; + } + if (lname) { + emit_string (w, lname); } else { sprintf (name_buf, "V_%d", i); emit_string (w, name_buf); @@ -1739,8 +2047,8 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod } } - g_free (local_names); - g_free (local_indexes); + if (locals_info) + mono_debug_symfile_free_locals (locals_info); /* Subprogram end */ emit_uleb128 (w, 0x0); @@ -1757,8 +2065,23 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod /* Emit line number info */ /* != could happen when using --regression */ - if (debug_info && (debug_info->code_start == code)) - emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info); + if (debug_info && (debug_info->code_start == code)) { + if (w->collect_line_info) { + MethodLineNumberInfo *info; + + /* Save the information needed to emit the line number info later at once */ + info = g_new0 (MethodLineNumberInfo, 1); + info->method = method; + info->start_symbol = g_strdup (start_symbol); + info->end_symbol = g_strdup (end_symbol); + info->code = code; + info->code_size = code_size; + info->debug_info = debug_info; + w->line_info = g_slist_prepend (w->line_info, info); + } else { + emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info); + } + } emit_line (w); mono_metadata_free_mh (header); @@ -1770,14 +2093,10 @@ mono_dwarf_writer_emit_trampoline (MonoDwarfWriter *w, const char *tramp_name, c emit_section_change (w, ".debug_info", 0); /* Subprogram */ - emit_uleb128 (w, ABBREV_SUBPROGRAM); + emit_uleb128 (w, ABBREV_TRAMP_SUBPROGRAM); emit_string (w, tramp_name); emit_pointer_value (w, code); emit_pointer_value (w, code + code_size); - /* frame_base */ - emit_byte (w, 2); - emit_byte (w, DW_OP_breg6); - emit_byte (w, 16); /* Subprogram end */ emit_uleb128 (w, 0x0);