Merge pull request #1155 from steffen-kiess/json-string
[mono.git] / mono / mini / dwarfwriter.c
index d00b7332e32e14199c9f43b69917f49f7c394042..c9c3b120000d38480d243672922254dc0f66d6cf 100644 (file)
@@ -30,6 +30,9 @@
 
 #include <mono/utils/freebsd-dwarf.h>
 
+#define DW_AT_MIPS_linkage_name 0x2007
+#define DW_LNE_set_prologue_end 0x0a
+
 typedef struct {
        MonoMethod *method;
        char *start_symbol, *end_symbol;
@@ -455,6 +458,9 @@ static int compile_unit_attr [] = {
 
 static int subprogram_attr [] = {
        DW_AT_name         , DW_FORM_string,
+       DW_AT_MIPS_linkage_name, DW_FORM_string,
+       DW_AT_decl_file    , DW_FORM_udata,
+       DW_AT_decl_line    , DW_FORM_udata,
 #ifndef TARGET_IOS
        DW_AT_description  , DW_FORM_string,
 #endif
@@ -465,9 +471,6 @@ static int subprogram_attr [] = {
 
 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,
 };
@@ -678,69 +681,6 @@ add_line_number_file_name (MonoDwarfWriter *w, const char *name,
        return index;
 }
 
-static void
-emit_line_number_info_begin (MonoDwarfWriter *w)
-{
-       /* Line number info header */
-       /* 
-        * GAS seems to emit its own data to the end of the first subsection, so we use
-        * subsections 1, 2 etc:
-        * 1 - contains the header
-        * 2 - contains the file names
-        * 3 - contains the end of the header + the data
-        * 4 - the end symbol
-        */
-       emit_section_change (w, ".debug_line", 0);
-       emit_label (w, ".Ldebug_line_section_start");
-       emit_section_change (w, ".debug_line", LINE_SUBSECTION_HEADER);
-       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", LINE_SUBSECTION_INCLUDES);
-
-       /* End of Includes */
-       emit_section_change (w, ".debug_line", LINE_SUBSECTION_FILES);
-       emit_byte (w, 0);
-
-       /* Files */
-       emit_line_number_file_name (w, "xdb.il", 0, 0);
-
-       /* End of Files */
-       emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
-       emit_byte (w, 0);
-
-       emit_label (w, ".Ldebug_line_header_end");
-
-       /* Emit this into a separate subsection so it gets placed at the end */ 
-       emit_section_change (w, ".debug_line", LINE_SUBSECTION_END);
-
-       emit_byte (w, 0);
-       emit_byte (w, 1);
-       emit_byte (w, DW_LNE_end_sequence);
-
-       emit_label (w, ".Ldebug_line_end");
-}
-
 char *
 mono_dwarf_escape_path (const char *name)
 {
@@ -789,7 +729,7 @@ emit_all_line_number_info (MonoDwarfWriter *w)
                if (!minfo)
                        continue;
 
-               mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, NULL, NULL, NULL, NULL, NULL);
+               mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, NULL, NULL, 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);
@@ -919,7 +859,7 @@ emit_debug_info_end (MonoDwarfWriter *w)
 }
 
 void
-mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_program)
+mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSList *base_unwind_program)
 {
        char *s, *build_info;
        int i;
@@ -988,13 +928,16 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra
        emit_string (w, s);
        g_free (build_info);
        g_free (s);
-       emit_string (w, "JITted code");
+       emit_string (w, cu_name);
        emit_string (w, "");
        emit_byte (w, DW_LANG_C);
        emit_pointer_value (w, 0);
        emit_pointer_value (w, 0);
        /* offset into .debug_line section */
-       emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+       if (w->emit_line)
+               emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+       else
+               emit_pointer_value (w, 0);
 
        /* Base types */
        for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
@@ -1011,14 +954,6 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra
        emit_section_change (w, ".debug_loc", 0);
        emit_label (w, ".Ldebug_loc_start");
 
-       /* debug_line section */
-       /*
-        * We emit some info even if emit_line is FALSE, as the
-        * apple linker seems to require a .debug_line section.
-        */
-       if (!w->collect_line_info)
-               emit_line_number_info_begin (w);
-
        emit_cie (w);
 }
 
@@ -1447,6 +1382,7 @@ static const guint8 *token_handler_ip;
 static char*
 token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
 {
+       MonoError error;
        char *res, *desc;
        MonoMethod *cmethod;
        MonoClass *klass;
@@ -1460,10 +1396,12 @@ token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
        case CEE_ISINST:
        case CEE_CASTCLASS:
        case CEE_LDELEMA:
-               if (method->wrapper_type)
+               if (method->wrapper_type) {
                        klass = data;
-               else
-                       klass = mono_class_get_full (method->klass->image, token, NULL);
+               } else {
+                       klass = mono_class_get_checked (method->klass->image, token, &error);
+                       g_assert (mono_error_ok (&error)); /* FIXME error handling */
+               }
                res = g_strdup_printf ("<%s>", klass->name);
                break;
        case CEE_NEWOBJ:
@@ -1490,10 +1428,12 @@ token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
        case CEE_LDSFLD:
        case CEE_STFLD:
        case CEE_STSFLD:
-               if (method->wrapper_type)
+               if (method->wrapper_type) {
                        field = data;
-               else
-                       field = mono_field_from_token (method->klass->image, token, &klass, NULL);
+               } else {
+                       field = mono_field_from_token_checked (method->klass->image, token, &klass, NULL,  &error);
+                       g_assert (mono_error_ok (&error)); /* FIXME error handling */
+               }
                desc = mono_field_full_name (field);
                res = g_strdup_printf ("<%s>", desc);
                g_free (desc);
@@ -1686,6 +1626,7 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
        prev_line = 1;
        prev_il_offset = -1;
 
+       w->cur_file_index = -1;
        for (i = 0; i < code_size; ++i) {
                int line_diff, addr_diff;
 
@@ -1731,16 +1672,6 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
                                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;
-                       prev_native_offset = i;
                        first = FALSE;
                }
 
@@ -1762,6 +1693,12 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
                                        w->cur_file_index = file_index;
                                }                                       
                        }
+               }
+
+               if (loc->row != prev_line) {
+                       if (prev_native_offset == 0)
+                               emit_byte (w, DW_LNE_set_prologue_end);
+
                        //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);
 
@@ -1770,6 +1707,7 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method,
                }
 
                mono_debug_symfile_free_location (loc);
+               first = FALSE;
        }
 
        g_free (native_to_il_offset);
@@ -1887,13 +1825,16 @@ find_vmv (MonoCompile *cfg, MonoInst *ins)
 }
 
 void
-mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
+mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, char *linkage_name,
+                                                          guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
 {
        char *name;
        MonoMethodSignature *sig;
        MonoMethodHeader *header;
        char **names;
        MonoDebugLocalsInfo *locals_info;
+       MonoDebugMethodInfo *minfo;
+       MonoDebugSourceLocation *loc = NULL;
        int i;
        guint8 buf [128];
        guint8 *p;
@@ -1925,13 +1866,32 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod
                emit_type (w, header->locals [i]);
        }
 
+       minfo = mono_debug_lookup_method (method);
+       if (minfo)
+               loc = mono_debug_symfile_lookup_location (minfo, 0);
+
        /* Subprogram */
        names = g_new0 (char *, sig->param_count);
        mono_method_get_param_names (method, (const char **) names);
 
        emit_uleb128 (w, ABBREV_SUBPROGRAM);
+       /* DW_AT_name */
        name = mono_method_full_name (method, FALSE);
        emit_string (w, name);
+       /* DW_AT_MIPS_linkage_name */
+       if (linkage_name)
+               emit_string (w, linkage_name);
+       else
+               emit_string (w, "");
+       /* DW_AT_decl_file/DW_AT_decl_line */
+       if (loc) {
+               int file_index = add_line_number_file_name (w, loc->source_file, 0, 0);
+               emit_uleb128 (w, file_index + 1);
+               emit_uleb128 (w, loc->row);
+       } else {
+               emit_uleb128 (w, 0);
+               emit_uleb128 (w, 0);
+       }
 #ifndef TARGET_IOS
        emit_string (w, name);
 #endif