PR gas/14201
[deliverable/binutils-gdb.git] / gas / dwarf2dbg.c
index 4061c72893fff7140ef1a45774d12b4b5595e376..f428f0d12230ee3c17957ce857b64ff991c3228a 100644 (file)
 #define DWARF2_FILE_SIZE_NAME(FILENAME,DIRNAME) 0
 #endif
 
+#ifndef DWARF2_VERSION
+#define DWARF2_VERSION 2
+#endif
+
+/* The .debug_aranges version has been 2 in DWARF version 2, 3 and 4. */
+#ifndef DWARF2_ARANGES_VERSION
+#define DWARF2_ARANGES_VERSION 2
+#endif
+
+/* This implementation output version 2 .debug_line information. */
+#ifndef DWARF2_LINE_VERSION
+#define DWARF2_LINE_VERSION 2
+#endif
+
 #include "subsegs.h"
 
 #include "dwarf2.h"
@@ -203,6 +217,10 @@ static struct dwarf2_line_info current = {
   0
 };
 
+/* Lines that are at the same location as CURRENT, and which are waiting
+   for a label.  */
+static struct line_entry *pending_lines, **pending_lines_tail = &pending_lines;
+
 /* The size of an address on the target.  */
 static unsigned int sizeof_address;
 \f
@@ -276,22 +294,47 @@ get_line_subseg (segT seg, subsegT subseg)
   return lss;
 }
 
-/* Record an entry for LOC occurring at LABEL.  */
+/* Push LOC onto the pending lines list.  */
 
 static void
-dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
+dwarf2_push_line (struct dwarf2_line_info *loc)
 {
-  struct line_subseg *lss;
   struct line_entry *e;
 
   e = (struct line_entry *) xmalloc (sizeof (*e));
   e->next = NULL;
-  e->label = label;
+  e->label = NULL;
   e->loc = *loc;
 
-  lss = get_line_subseg (now_seg, now_subseg);
-  *lss->ptail = e;
-  lss->ptail = &e->next;
+  *pending_lines_tail = e;
+  pending_lines_tail = &(*pending_lines_tail)->next;
+}
+
+/* Emit all pending line information.  LABEL is the label with which the
+   lines should be associated, or null if they should be associated with
+   the current position.  */
+
+static void
+dwarf2_flush_pending_lines (symbolS *label)
+{
+  if (pending_lines)
+    {
+      struct line_subseg *lss;
+      struct line_entry *e;
+
+      if (!label)
+       label = symbol_temp_new_now ();
+
+      for (e = pending_lines; e; e = e->next)
+       e->label = label;
+
+      lss = get_line_subseg (now_seg, now_subseg);
+      *lss->ptail = pending_lines;
+      lss->ptail = pending_lines_tail;
+
+      pending_lines = NULL;
+      pending_lines_tail = &pending_lines;
+    }
 }
 
 /* Record an entry for LOC occurring at OFS within the current fragment.  */
@@ -302,8 +345,6 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
   static unsigned int line = -1;
   static unsigned int filenum = -1;
 
-  symbolS *sym;
-
   /* Early out for as-yet incomplete location information.  */
   if (loc->filenum == 0 || loc->line == 0)
     return;
@@ -319,8 +360,8 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
   line = loc->line;
   filenum = loc->filenum;
 
-  sym = symbol_temp_new (now_seg, ofs, frag_now);
-  dwarf2_gen_line_info_1 (sym, loc);
+  dwarf2_push_line (loc);
+  dwarf2_flush_pending_lines (symbol_temp_new (now_seg, ofs, frag_now));
 }
 
 /* Returns the current source information.  If .file directives have
@@ -381,6 +422,11 @@ dwarf2_emit_insn (int size)
 void
 dwarf2_consume_line_info (void)
 {
+  /* If the consumer has stashed the current location away for later use,
+     assume that any earlier location information should be associated
+     with ".".  */
+  dwarf2_flush_pending_lines (NULL);
+
   /* Unless we generate DWARF2 debugging information for each
      assembler line, we only emit one line symbol for one LOC.  */
   dwarf2_loc_directive_seen = FALSE;
@@ -412,7 +458,8 @@ dwarf2_emit_label (symbolS *label)
 
   loc.flags |= DWARF2_FLAG_BASIC_BLOCK;
 
-  dwarf2_gen_line_info_1 (label, &loc);
+  dwarf2_push_line (&loc);
+  dwarf2_flush_pending_lines (label);
   dwarf2_consume_line_info ();
 }
 
@@ -431,14 +478,14 @@ get_filenum (const char *filename, unsigned int num)
   if (num == 0 && last_used)
     {
       if (! files[last_used].dir
-         && strcmp (filename, files[last_used].filename) == 0)
+         && filename_cmp (filename, files[last_used].filename) == 0)
        return last_used;
       if (files[last_used].dir
-         && strncmp (filename, dirs[files[last_used].dir],
-                     last_used_dir_len) == 0
+         && filename_ncmp (filename, dirs[files[last_used].dir],
+                           last_used_dir_len) == 0
          && IS_DIR_SEPARATOR (filename [last_used_dir_len])
-         && strcmp (filename + last_used_dir_len + 1,
-                    files[last_used].filename) == 0)
+         && filename_cmp (filename + last_used_dir_len + 1,
+                          files[last_used].filename) == 0)
        return last_used;
     }
 
@@ -460,7 +507,7 @@ get_filenum (const char *filename, unsigned int num)
       --dir_len;
 #endif
       for (dir = 1; dir < dirs_in_use; ++dir)
-       if (strncmp (filename, dirs[dir], dir_len) == 0
+       if (filename_ncmp (filename, dirs[dir], dir_len) == 0
            && dirs[dir][dir_len] == '\0')
          break;
 
@@ -485,7 +532,7 @@ get_filenum (const char *filename, unsigned int num)
       for (i = 1; i < files_in_use; ++i)
        if (files[i].dir == dir
            && files[i].filename
-           && strcmp (file, files[i].filename) == 0)
+           && filename_cmp (file, files[i].filename) == 0)
          {
            last_used = i;
            last_used_dir_len = dir_len;
@@ -572,7 +619,7 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
   /* If we see two .loc directives in a row, force the first one to be
      output now.  */
   if (dwarf2_loc_directive_seen)
-    dwarf2_emit_insn (0);
+    dwarf2_push_line (&current);
 
   filenum = get_absolute_expression ();
   SKIP_WHITESPACE ();
@@ -1080,7 +1127,7 @@ emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
       symbolS *to_sym;
       expressionS exp;
 
-      gas_assert (pexp->X_op = O_subtract);
+      gas_assert (pexp->X_op == O_subtract);
       to_sym = pexp->X_add_symbol;
 
       *p++ = DW_LNS_extended_op;
@@ -1420,7 +1467,7 @@ out_debug_line (segT line_seg)
   line_end = exp.X_add_symbol;
 
   /* Version.  */
-  out_two (2);
+  out_two (DWARF2_LINE_VERSION);
 
   /* Length of the prologue following this length.  */
   prologue_end = symbol_temp_make ();
@@ -1455,7 +1502,11 @@ out_debug_line (segT line_seg)
 
   /* For each section, emit a statement program.  */
   for (s = all_segs; s; s = s->next)
-    process_entries (s->seg, s->head->head);
+    if (SEG_NORMAL (s->seg))
+      process_entries (s->seg, s->head->head);
+    else
+      as_warn ("dwarf line number information for %s ignored",
+              segment_name (s->seg));
 
   symbol_set_value_now (line_end);
 }
@@ -1524,7 +1575,7 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
   aranges_end = exp.X_add_symbol;
 
   /* Version.  */
-  out_two (2);
+  out_two (DWARF2_ARANGES_VERSION);
 
   /* Offset to .debug_info.  */
   TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), sizeof_offset);
@@ -1590,7 +1641,11 @@ out_debug_abbrev (segT abbrev_seg,
   if (all_segs->next == NULL)
     {
       out_abbrev (DW_AT_low_pc, DW_FORM_addr);
-      out_abbrev (DW_AT_high_pc, DW_FORM_addr);
+      if (DWARF2_VERSION < 4)
+       out_abbrev (DW_AT_high_pc, DW_FORM_addr);
+      else
+       out_abbrev (DW_AT_high_pc, (sizeof_address == 4
+                                   ? DW_FORM_data4 : DW_FORM_data8));
     }
   else
     {
@@ -1627,7 +1682,7 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
   info_end = exp.X_add_symbol;
 
   /* DWARF version.  */
-  out_two (2);
+  out_two (DWARF2_VERSION);
 
   /* .debug_abbrev offset */
   TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);
@@ -1653,7 +1708,13 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
       emit_expr (&exp, sizeof_address);
 
       /* DW_AT_high_pc */
-      exp.X_op = O_symbol;
+      if (DWARF2_VERSION < 4)
+       exp.X_op = O_symbol;
+      else
+       {
+         exp.X_op = O_subtract;
+         exp.X_op_symbol = all_segs->text_start;
+       }
       exp.X_add_symbol = all_segs->text_end;
       exp.X_add_number = 0;
       emit_expr (&exp, sizeof_address);
@@ -1718,11 +1779,12 @@ dwarf2_init (void)
 
 /* Finish the dwarf2 debug sections.  We emit .debug.line if there
    were any .file/.loc directives, or --gdwarf2 was given, or if the
-   file has a non-empty .debug_info section.  If we emit .debug_line,
-   and the .debug_info section is empty, we also emit .debug_info,
-   .debug_aranges and .debug_abbrev.  ALL_SEGS will be non-null if
-   there were any .file/.loc directives, or --gdwarf2 was given and
-   there were any located instructions emitted.  */
+   file has a non-empty .debug_info section and an empty .debug_line
+   section.  If we emit .debug_line, and the .debug_info section is
+   empty, we also emit .debug_info, .debug_aranges and .debug_abbrev.
+   ALL_SEGS will be non-null if there were any .file/.loc directives,
+   or --gdwarf2 was given and there were any located instructions
+   emitted.  */
 
 void
 dwarf2_finish (void)
@@ -1731,13 +1793,24 @@ dwarf2_finish (void)
   struct line_seg *s;
   segT info_seg;
   int emit_other_sections = 0;
+  int empty_debug_line = 0;
 
   info_seg = bfd_get_section_by_name (stdoutput, ".debug_info");
   emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg);
 
-  if (!all_segs && emit_other_sections)
-    /* There is no line information and no non-empty .debug_info
-       section.  */
+  line_seg = bfd_get_section_by_name (stdoutput, ".debug_line");
+  empty_debug_line = line_seg == NULL || !seg_not_empty_p (line_seg);
+
+  /* We can't construct a new debug_line section if we already have one.
+     Give an error.  */
+  if (all_segs && !empty_debug_line)
+    as_fatal ("duplicate .debug_line sections");
+
+  if ((!all_segs && emit_other_sections)
+      || (!emit_other_sections && !empty_debug_line))
+    /* If there is no line information and no non-empty .debug_info
+       section, or if there is both a non-empty .debug_info and a non-empty
+       .debug_line, then we do nothing.  */
     return;
 
   /* Calculate the size of an address for the target machine.  */
This page took 0.027379 seconds and 4 git commands to generate.