2009-06-10 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / dwarfwriter.c
index 470ac5a1b3de710ede75a25e9fb8d70db925d8cd..94f1459c5ed4b67692954051e1912c20456d93be 100644 (file)
@@ -40,6 +40,9 @@ struct _MonoDwarfWriter
        FILE *il_file;
        int il_file_line_index, loclist_index;
        GSList *cie_program;
+       FILE *fp;
+       const char *temp_prefix;
+       gboolean emit_line;
 };
 
 /*
@@ -57,6 +60,9 @@ mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file)
        w->w = writer;
        w->il_file = il_file;
 
+       w->fp = img_writer_get_fp (w->w);
+       w->temp_prefix = img_writer_get_temp_label_prefix (w->w);
+
        return w;
 }
 
@@ -561,14 +567,6 @@ emit_line_number_file_name (MonoDwarfWriter *w, const char *name,
 static void
 emit_line_number_info_begin (MonoDwarfWriter *w)
 {
-       if (!w->il_file) {
-               /* FIXME: This doesn't seem to work with !xdebug */
-               emit_section_change (w, ".debug_line", 0);
-               emit_label (w, ".Ldebug_line_start");
-               emit_label (w, ".Ldebug_line_section_start");
-               return;
-       }
-
        /* Line number info header */
        /* 
         * GAS seems to emit its own data to the end of the first subsection, so we use
@@ -629,12 +627,31 @@ emit_line_number_info_begin (MonoDwarfWriter *w)
        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 
+ * define it every time something gets added to the .debug_info section.
+ * The apple assember seems to use the last definition.
+ */
+static void
+emit_debug_info_end (MonoDwarfWriter *w)
+{
+       if (!img_writer_subsections_supported (w->w))
+               fprintf (w->fp, "\n.set %sdebug_info_end,.\n", w->temp_prefix);
+}
+
 void
 mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_program)
 {
        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);
@@ -679,11 +696,13 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra
        emit_int32 (w, 0); /* .debug_abbrev offset */
        emit_byte (w, sizeof (gpointer)); /* address size */
 
-       /* Emit this into a separate section so it gets placed at the end */
-       emit_section_change (w, ".debug_info", 1);
-       emit_int32 (w, 0); /* close everything */
-       emit_label (w, ".Ldebug_info_end");
-       emit_section_change (w, ".debug_info", 0);
+       if (img_writer_subsections_supported (w->w)) {
+               /* Emit this into a separate section so it gets placed at the end */
+               emit_section_change (w, ".debug_info", 1);
+               emit_int32 (w, 0); /* close everything */
+               emit_label (w, ".Ldebug_info_end");
+               emit_section_change (w, ".debug_info", 0);
+       }
 
        /* Compilation unit */
        emit_uleb128 (w, ABBREV_COMPILE_UNIT);
@@ -698,7 +717,10 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra
        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_int32 (w, 0);
 
        /* Base types */
        for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
@@ -709,12 +731,15 @@ mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_progra
                emit_string (w, basic_types [i].name);
        }
 
+       emit_debug_info_end (w);
+
        /* debug_loc section */
        emit_section_change (w, ".debug_loc", 0);
        emit_label (w, ".Ldebug_loc_start");
 
        /* debug_line section */
-       emit_line_number_info_begin (w);
+       if (w->emit_line)
+               emit_line_number_info_begin (w);
 
        emit_cie (w);
 }
@@ -1240,8 +1265,10 @@ compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
 }
 
 static void
-emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
-                                          guint32 code_size, MonoDebugMethodJitInfo *debug_info)
+emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, 
+                                          char *start_symbol, char *end_symbol,
+                                          guint8 *code, guint32 code_size,
+                                          MonoDebugMethodJitInfo *debug_info)
 {
        guint32 prev_line = 0;
        guint32 prev_native_offset = 0;
@@ -1254,14 +1281,15 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
        GArray *ln_array;
        int *native_to_il_offset = NULL;
 
-       if (!code)
-               // FIXME: The set_address op below only works with xdebug
+       if (!w->emit_line)
                return;
 
        minfo = mono_debug_lookup_method (method);
 
        /* Compute the native->IL offset mapping */
 
+       g_assert (code_size);
+
 #ifndef _EGLIB_MAJOR
        ln_array = g_array_sized_new (FALSE, FALSE, sizeof (MonoDebugLineNumberEntry), 
                                                                  debug_info->num_line_numbers);
@@ -1332,7 +1360,10 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
                                emit_byte (w, 0);
                                emit_byte (w, sizeof (gpointer) + 1);
                                emit_byte (w, DW_LNE_set_address);
-                               emit_pointer_value (w, code);
+                               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
@@ -1379,7 +1410,7 @@ emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
                emit_byte (w, 0);
                emit_byte (w, 1);
                emit_byte (w, DW_LNE_end_sequence);
-       } else if (code) {
+       } else if (!start_symbol) {
                /* No debug info, XDEBUG mode */
                char *name, *dis;
                const guint8 *ip = header->code;
@@ -1652,6 +1683,8 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod
 
        emit_line (w);
 
+       emit_debug_info_end (w);
+
        /* Emit unwind info */
        if (unwind_info) {
                emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
@@ -1659,10 +1692,9 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod
        }
 
        /* Emit line number info */
-       if (code && debug_info)
-               /* != could happen when using --regression */
-               if (debug_info->code_start == code)
-                       emit_line_number_info (w, method, code, code_size, debug_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);
 
        emit_line (w);
 }
@@ -1685,6 +1717,8 @@ mono_dwarf_writer_emit_trampoline (MonoDwarfWriter *w, const char *tramp_name, c
        /* Subprogram end */
        emit_uleb128 (w, 0x0);
 
+       emit_debug_info_end (w);
+
        /* Emit unwind info */
        emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, FALSE);
        w->fde_index ++;