OSDN Git Service

Merge commit '97841852f4cb6c2' into tmp
[pf3gnuchains/pf3gnuchains4x.git] / gas / dwarf2dbg.c
index 2bcba9b..4061c72 100644 (file)
@@ -1,5 +1,5 @@
 /* dwarf2dbg.c - DWARF2 debug support
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
@@ -25,7 +25,8 @@
 
        .file FILENO "file.c"
        .loc  FILENO LINENO [COLUMN] [basic_block] [prologue_end] \
-             [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+             [epilogue_begin] [is_stmt VALUE] [isa VALUE] \
+             [discriminator VALUE]
 */
 
 #include "as.h"
@@ -90,7 +91,7 @@
 
 #include "subsegs.h"
 
-#include "elf/dwarf2.h"
+#include "dwarf2.h"
 
 /* Since we can't generate the prolog until the body is complete, we
    use three different subsegments for .debug_line: one holding the
@@ -167,6 +168,10 @@ struct line_seg {
 
 /* Collects data for all line table entries during assembly.  */
 static struct line_seg *all_segs;
+/* Hash used to quickly lookup a segment by name, avoiding the need to search
+   through the all_segs list.  */
+static struct hash_control *all_segs_hash;
+static struct line_seg **last_seg_ptr;
 
 struct file_entry {
   const char *filename;
@@ -194,7 +199,8 @@ bfd_boolean dwarf2_loc_mark_labels;
 /* Current location as indicated by the most recent .loc directive.  */
 static struct dwarf2_line_info current = {
   1, 1, 0, 0,
-  DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0
+  DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0,
+  0
 };
 
 /* The size of an address on the target.  */
@@ -210,12 +216,12 @@ static unsigned int get_filenum (const char *, unsigned int);
 static void
 generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 {
-  expressionS expr;
+  expressionS exp;
 
-  expr.X_op = O_symbol;
-  expr.X_add_symbol = symbol;
-  expr.X_add_number = 0;
-  emit_expr (&expr, size);
+  exp.X_op = O_symbol;
+  exp.X_add_symbol = symbol;
+  exp.X_add_number = 0;
+  emit_expr (&exp, size);
 }
 #endif
 
@@ -228,44 +234,46 @@ get_line_subseg (segT seg, subsegT subseg)
   static subsegT last_subseg;
   static struct line_subseg *last_line_subseg;
 
-  struct line_seg **ps, *s;
-  struct line_subseg **pss, *ss;
+  struct line_seg *s;
+  struct line_subseg **pss, *lss;
 
   if (seg == last_seg && subseg == last_subseg)
     return last_line_subseg;
 
-  for (ps = &all_segs; (s = *ps) != NULL; ps = &s->next)
-    if (s->seg == seg)
-      goto found_seg;
-
-  s = (struct line_seg *) xmalloc (sizeof (*s));
-  s->next = NULL;
-  s->seg = seg;
-  s->head = NULL;
-  *ps = s;
+  s = (struct line_seg *) hash_find (all_segs_hash, seg->name);
+  if (s == NULL)
+    {
+      s = (struct line_seg *) xmalloc (sizeof (*s));
+      s->next = NULL;
+      s->seg = seg;
+      s->head = NULL;
+      *last_seg_ptr = s;
+      last_seg_ptr = &s->next;
+      hash_insert (all_segs_hash, seg->name, s);
+    }
+  gas_assert (seg == s->seg);
 
- found_seg:
-  for (pss = &s->head; (ss = *pss) != NULL ; pss = &ss->next)
+  for (pss = &s->head; (lss = *pss) != NULL ; pss = &lss->next)
     {
-      if (ss->subseg == subseg)
+      if (lss->subseg == subseg)
        goto found_subseg;
-      if (ss->subseg > subseg)
+      if (lss->subseg > subseg)
        break;
     }
 
-  ss = (struct line_subseg *) xmalloc (sizeof (*ss));
-  ss->next = *pss;
-  ss->subseg = subseg;
-  ss->head = NULL;
-  ss->ptail = &ss->head;
-  *pss = ss;
+  lss = (struct line_subseg *) xmalloc (sizeof (*lss));
+  lss->next = *pss;
+  lss->subseg = subseg;
+  lss->head = NULL;
+  lss->ptail = &lss->head;
+  *pss = lss;
 
  found_subseg:
   last_seg = seg;
   last_subseg = subseg;
-  last_line_subseg = ss;
+  last_line_subseg = lss;
 
-  return ss;
+  return lss;
 }
 
 /* Record an entry for LOC occurring at LABEL.  */
@@ -273,7 +281,7 @@ get_line_subseg (segT seg, subsegT subseg)
 static void
 dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
 {
-  struct line_subseg *ss;
+  struct line_subseg *lss;
   struct line_entry *e;
 
   e = (struct line_entry *) xmalloc (sizeof (*e));
@@ -281,9 +289,9 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
   e->label = label;
   e->loc = *loc;
 
-  ss = get_line_subseg (now_seg, now_subseg);
-  *ss->ptail = e;
-  ss->ptail = &e->next;
+  lss = get_line_subseg (now_seg, now_subseg);
+  *lss->ptail = e;
+  lss->ptail = &e->next;
 }
 
 /* Record an entry for LOC occurring at OFS within the current fragment.  */
@@ -331,6 +339,7 @@ dwarf2_where (struct dwarf2_line_info *line)
       line->column = 0;
       line->flags = DWARF2_FLAG_IS_STMT;
       line->isa = current.isa;
+      line->discriminator = current.discriminator;
     }
   else
     *line = current;
@@ -379,6 +388,7 @@ dwarf2_consume_line_info (void)
   current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
                     | DWARF2_FLAG_PROLOGUE_END
                     | DWARF2_FLAG_EPILOGUE_BEGIN);
+  current.discriminator = 0;
 }
 
 /* Called for each (preferably code) label.  If dwarf2_loc_mark_labels
@@ -463,7 +473,7 @@ get_filenum (const char *filename, unsigned int num)
                     xrealloc (dirs, (dir + 32) * sizeof (const char *));
            }
 
-         dirs[dir] = xmalloc (dir_len + 1);
+         dirs[dir] = (char *) xmalloc (dir_len + 1);
          memcpy (dirs[dir], filename, dir_len);
          dirs[dir][dir_len] = '\0';
          dirs_in_use = dir + 1;
@@ -581,6 +591,7 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
 
   current.filenum = filenum;
   current.line = line;
+  current.discriminator = 0;
 
 #ifndef NO_LISTING
   if (listing)
@@ -659,6 +670,18 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
              return;
            }
        }
+      else if (strcmp (p, "discriminator") == 0)
+       {
+         *input_line_pointer = c;
+         value = get_absolute_expression ();
+         if (value >= 0)
+           current.discriminator = value;
+         else
+           {
+             as_bad (_("discriminator less than zero"));
+             return;
+           }
+       }
       else
        {
          as_bad (_("unknown .loc sub-directive `%s'"), p);
@@ -748,6 +771,14 @@ out_uleb128 (addressT value)
   output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
 }
 
+/* Emit a signed "little-endian base 128" number.  */
+
+static void
+out_leb128 (addressT value)
+{
+  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
+}
+
 /* Emit a tuple for .debug_abbrev.  */
 
 static inline void
@@ -782,16 +813,16 @@ get_frag_fix (fragS *frag, segT seg)
 static void
 out_set_addr (symbolS *sym)
 {
-  expressionS expr;
+  expressionS exp;
 
   out_opcode (DW_LNS_extended_op);
   out_uleb128 (sizeof_address + 1);
 
   out_opcode (DW_LNE_set_address);
-  expr.X_op = O_symbol;
-  expr.X_add_symbol = sym;
-  expr.X_add_number = 0;
-  emit_expr (&expr, sizeof_address);
+  exp.X_op = O_symbol;
+  exp.X_add_symbol = sym;
+  exp.X_add_number = 0;
+  emit_expr (&exp, sizeof_address);
 }
 
 #if DWARF2_LINE_MIN_INSN_LENGTH > 1
@@ -888,7 +919,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
 
   /* Line number sequences cannot go backward in addresses.  This means
      we've incorrectly ordered the statements in the sequence.  */
-  assert ((offsetT) addr_delta >= 0);
+  gas_assert ((offsetT) addr_delta >= 0);
 
   /* Scale the address delta by the minimum instruction length.  */
   scale_addr_delta (&addr_delta);
@@ -969,7 +1000,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
     *p++ = tmp;
 
  done:
-  assert (p == end);
+  gas_assert (p == end);
 }
 
 /* Handy routine to combine calls to the above two routines.  */
@@ -1021,13 +1052,13 @@ static void
 emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
                          char *p, int len)
 {
-  expressionS *exp;
+  expressionS *pexp;
   segT line_seg;
   char *end = p + len;
 
   /* Line number sequences cannot go backward in addresses.  This means
      we've incorrectly ordered the statements in the sequence.  */
-  assert ((offsetT) addr_delta >= 0);
+  gas_assert ((offsetT) addr_delta >= 0);
 
   /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.  */
   if (line_delta != INT_MAX)
@@ -1036,7 +1067,7 @@ emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
       p += output_leb128 (p, line_delta, 1);
     }
 
-  exp = symbol_get_value_expression (frag->fr_symbol);
+  pexp = symbol_get_value_expression (frag->fr_symbol);
   line_seg = subseg_get (".debug_line", 0);
 
   /* The DW_LNS_fixed_advance_pc opcode has a 2-byte operand so it can
@@ -1047,26 +1078,26 @@ emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
   if (addr_delta > 50000)
     {
       symbolS *to_sym;
-      expressionS expr;
+      expressionS exp;
 
-      assert (exp->X_op = O_subtract);
-      to_sym = exp->X_add_symbol;
+      gas_assert (pexp->X_op = O_subtract);
+      to_sym = pexp->X_add_symbol;
 
       *p++ = DW_LNS_extended_op;
       p += output_leb128 (p, sizeof_address + 1, 0);
       *p++ = DW_LNE_set_address;
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = to_sym;
-      expr.X_add_number = 0;
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = to_sym;
+      exp.X_add_number = 0;
       subseg_change (line_seg, 0);
-      emit_expr_fix (&expr, sizeof_address, frag, p);
+      emit_expr_fix (&exp, sizeof_address, frag, p);
       p += sizeof_address;
     }
   else
     {
       *p++ = DW_LNS_fixed_advance_pc;
       subseg_change (line_seg, 0);
-      emit_expr_fix (exp, 2, frag, p);
+      emit_expr_fix (pexp, 2, frag, p);
       p += 2;
     }
 
@@ -1079,7 +1110,7 @@ emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
   else
     *p++ = DW_LNS_copy;
 
-  assert (p == end);
+  gas_assert (p == end);
 }
 
 /* Generate a variant frag that we can use to relax address/line
@@ -1088,13 +1119,13 @@ emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
 static void
 relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
 {
-  expressionS expr;
+  expressionS exp;
   int max_chars;
 
-  expr.X_op = O_subtract;
-  expr.X_add_symbol = to_sym;
-  expr.X_op_symbol = from_sym;
-  expr.X_add_number = 0;
+  exp.X_op = O_subtract;
+  exp.X_add_symbol = to_sym;
+  exp.X_op_symbol = from_sym;
+  exp.X_add_number = 0;
 
   /* The maximum size of the frag is the line delta with a maximum
      sized address delta.  */
@@ -1105,7 +1136,7 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
     max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH);
 
   frag_var (rs_dwarf2dbg, max_chars, max_chars, 1,
-           make_expr_symbol (&expr), line_delta, NULL);
+           make_expr_symbol (&exp), line_delta, NULL);
 }
 
 /* The function estimates the size of a rs_dwarf2dbg variant frag
@@ -1158,7 +1189,7 @@ dwarf2dbg_convert_frag (fragS *frag)
   /* fr_var carries the max_chars that we created the fragment with.
      fr_subtype carries the current expected length.  We must, of
      course, have allocated enough memory earlier.  */
-  assert (frag->fr_var >= (int) frag->fr_subtype);
+  gas_assert (frag->fr_var >= (int) frag->fr_subtype);
 
   if (DWARF2_USE_FIXED_ADVANCE_PC)
     emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
@@ -1208,6 +1239,14 @@ process_entries (segT seg, struct line_entry *e)
          out_uleb128 (column);
        }
 
+      if (e->loc.discriminator != 0)
+       {
+         out_opcode (DW_LNS_extended_op);
+         out_leb128 (1 + sizeof_leb128 (e->loc.discriminator, 0));
+         out_opcode (DW_LNE_set_discriminator);
+         out_uleb128 (e->loc.discriminator);
+       }
+
       if (isa != e->loc.isa)
        {
          isa = e->loc.isa;
@@ -1329,7 +1368,7 @@ out_file_list (void)
    to the end of the section.  */
 
 static int
-out_header (asection *sec, expressionS *expr)
+out_header (asection *sec, expressionS *exp)
 {
   symbolS *start_sym;
   symbolS *end_sym;
@@ -1339,26 +1378,26 @@ out_header (asection *sec, expressionS *expr)
   end_sym = symbol_temp_make ();
 
   /* Total length of the information.  */
-  expr->X_op = O_subtract;
-  expr->X_add_symbol = end_sym;
-  expr->X_op_symbol = start_sym;
+  exp->X_op = O_subtract;
+  exp->X_add_symbol = end_sym;
+  exp->X_op_symbol = start_sym;
 
   switch (DWARF2_FORMAT (sec))
     {
     case dwarf2_format_32bit:
-      expr->X_add_number = -4;
-      emit_expr (expr, 4);
+      exp->X_add_number = -4;
+      emit_expr (exp, 4);
       return 4;
 
     case dwarf2_format_64bit:
-      expr->X_add_number = -12;
+      exp->X_add_number = -12;
       out_four (-1);
-      emit_expr (expr, 8);
+      emit_expr (exp, 8);
       return 8;
 
     case dwarf2_format_64bit_irix:
-      expr->X_add_number = -8;
-      emit_expr (expr, 8);
+      exp->X_add_number = -8;
+      emit_expr (exp, 8);
       return 8;
     }
 
@@ -1371,23 +1410,23 @@ out_header (asection *sec, expressionS *expr)
 static void
 out_debug_line (segT line_seg)
 {
-  expressionS expr;
+  expressionS exp;
   symbolS *prologue_end;
   symbolS *line_end;
   struct line_seg *s;
   int sizeof_offset;
 
-  sizeof_offset = out_header (line_seg, &expr);
-  line_end = expr.X_add_symbol;
+  sizeof_offset = out_header (line_seg, &exp);
+  line_end = exp.X_add_symbol;
 
   /* Version.  */
   out_two (2);
 
   /* Length of the prologue following this length.  */
   prologue_end = symbol_temp_make ();
-  expr.X_add_symbol = prologue_end;
-  expr.X_add_number = - (4 + 2 + 4);
-  emit_expr (&expr, sizeof_offset);
+  exp.X_add_symbol = prologue_end;
+  exp.X_add_number = - (4 + 2 + 4);
+  emit_expr (&exp, sizeof_offset);
 
   /* Parameters of the state machine.  */
   out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
@@ -1426,7 +1465,7 @@ out_debug_ranges (segT ranges_seg)
 {
   unsigned int addr_size = sizeof_address;
   struct line_seg *s;
-  expressionS expr;
+  expressionS exp;
   unsigned int i;
 
   subseg_set (ranges_seg, 0);
@@ -1451,15 +1490,15 @@ out_debug_ranges (segT ranges_seg)
       end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
       s->text_end = end;
 
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = beg;
-      expr.X_add_number = 0;
-      emit_expr (&expr, addr_size);
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = beg;
+      exp.X_add_number = 0;
+      emit_expr (&exp, addr_size);
 
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = end;
-      expr.X_add_number = 0;
-      emit_expr (&expr, addr_size);
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = end;
+      exp.X_add_number = 0;
+      emit_expr (&exp, addr_size);
     }
 
   /* End of Range Entry.   */
@@ -1476,13 +1515,13 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
 {
   unsigned int addr_size = sizeof_address;
   struct line_seg *s;
-  expressionS expr;
+  expressionS exp;
   symbolS *aranges_end;
   char *p;
   int sizeof_offset;
 
-  sizeof_offset = out_header (aranges_seg, &expr);
-  aranges_end = expr.X_add_symbol;
+  sizeof_offset = out_header (aranges_seg, &exp);
+  aranges_end = exp.X_add_symbol;
 
   /* Version.  */
   out_two (2);
@@ -1512,16 +1551,16 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
       end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
       s->text_end = end;
 
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = beg;
-      expr.X_add_number = 0;
-      emit_expr (&expr, addr_size);
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = beg;
+      exp.X_add_number = 0;
+      emit_expr (&exp, addr_size);
 
-      expr.X_op = O_subtract;
-      expr.X_add_symbol = end;
-      expr.X_op_symbol = beg;
-      expr.X_add_number = 0;
-      emit_expr (&expr, addr_size);
+      exp.X_op = O_subtract;
+      exp.X_add_symbol = end;
+      exp.X_op_symbol = beg;
+      exp.X_add_number = 0;
+      emit_expr (&exp, addr_size);
     }
 
   p = frag_more (2 * addr_size);
@@ -1578,14 +1617,14 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
   char producer[128];
   const char *comp_dir;
   const char *dirname;
-  expressionS expr;
+  expressionS exp;
   symbolS *info_end;
   char *p;
   int len;
   int sizeof_offset;
 
-  sizeof_offset = out_header (info_seg, &expr);
-  info_end = expr.X_add_symbol;
+  sizeof_offset = out_header (info_seg, &exp);
+  info_end = exp.X_add_symbol;
 
   /* DWARF version.  */
   out_two (2);
@@ -1608,16 +1647,16 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
   if (all_segs->next == NULL)
     {
       /* DW_AT_low_pc */
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = all_segs->text_start;
-      expr.X_add_number = 0;
-      emit_expr (&expr, sizeof_address);
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = all_segs->text_start;
+      exp.X_add_number = 0;
+      emit_expr (&exp, sizeof_address);
 
       /* DW_AT_high_pc */
-      expr.X_op = O_symbol;
-      expr.X_add_symbol = all_segs->text_end;
-      expr.X_add_number = 0;
-      emit_expr (&expr, sizeof_address);
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = all_segs->text_end;
+      exp.X_add_number = 0;
+      emit_expr (&exp, sizeof_address);
     }
   else
     {
@@ -1636,9 +1675,15 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
     {
       dirname = remap_debug_filename (dirs[files[1].dir]);
       len = strlen (dirname);
+#ifdef TE_VMS
+      /* Already has trailing slash.  */
+      p = frag_more (len);
+      memcpy (p, dirname, len);
+#else
       p = frag_more (len + 1);
       memcpy (p, dirname, len);
       INSERT_DIR_SEPARATOR (p, len);
+#endif
     }
   len = strlen (files[1].filename) + 1;
   p = frag_more (len);
@@ -1663,6 +1708,14 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
   symbol_set_value_now (info_end);
 }
 
+void
+dwarf2_init (void)
+{
+  all_segs_hash = hash_new ();
+  last_seg_ptr = &all_segs;
+}
+
+
 /* 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,
@@ -1697,13 +1750,13 @@ dwarf2_finish (void)
   /* For each subsection, chain the debug entries together.  */
   for (s = all_segs; s; s = s->next)
     {
-      struct line_subseg *ss = s->head;
-      struct line_entry **ptail = ss->ptail;
+      struct line_subseg *lss = s->head;
+      struct line_entry **ptail = lss->ptail;
 
-      while ((ss = ss->next) != NULL)
+      while ((lss = lss->next) != NULL)
        {
-         *ptail = ss->head;
-         ptail = ss->ptail;
+         *ptail = lss->head;
+         ptail = lss->ptail;
        }
     }
 
@@ -1718,7 +1771,7 @@ dwarf2_finish (void)
       segT aranges_seg;
       segT ranges_seg;
 
-      assert (all_segs);
+      gas_assert (all_segs);
 
       info_seg = subseg_new (".debug_info", 0);
       abbrev_seg = subseg_new (".debug_abbrev", 0);