new .loc_mark_blocks directive

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

new .loc_mark_blocks directive

Richard Henderson-2
Adds a directive that puts the assembler in a mode in which it
adds a line number entry with the basic_block flag whenever a
label is seen in a code section.

The intent is to be able to have the basic_block flag be able
to mark extended basic blocks -- even with inline assembly --
with 100% reliability.  Of course, this sort of thing doesn't
help if the user does stuff like "beq reg, .+8".  I havn't
decided what, if anything, to do about that.

The expected consumers are binary code patching applications,
like systemtap.  With the markers one can tell where incoming
control flow may be possible.  Or in particular, where it is
not possible, and thus larger direct branch to fixup code
sequences can be used instead of smaller but slower trap insns.

Tested on alpha, arm, cris, pa, ia64, x86_64, m68hc11, m68k,
mips, ms1, ppc, sh64, and xtensa.

Xtensa produces output that is not ideal, but is not incorrect.
It probably needs to do something similar to ia64.  But since
it isn't actively wrong, I didn't bother.


r~



        * dwarf2dbg.c (struct line_entry): Replace frag and frag_ofs
        with label.
        (dwarf2_loc_mark_labels): New.
        (dwarf2_gen_line_info_1): Split out of ...
        (dwarf2_gen_line_info): ... here.  Create the temp symbol here.
        (dwarf2_emit_label): New.
        (dwarf2_directive_loc_mark_labels): New.
        (out_set_addr): Take a symbol instead of frag+ofs.
        (relax_inc_line_addr): Likewise.
        (emit_inc_line_addr): Assert delta non-negative.
        (process_entries): Remove dead code.  Update to work with temp
        symbols instead of frag+ofs.
        * dwarf2dbg.h (dwarf2_directive_loc_mark_labels): Declare.
        (dwarf2_emit_label, dwarf2_loc_mark_labels): Declare.
        * config/obj-elf.c (elf_pseudo_tab): Add loc_mark_labels.
        * config/obj-elf.h (obj_frob_label): New.
        * config/tc-alpha.c (alpha_define_label): Call dwarf2_emit_label.
        * config/tc-arm.c, config/tc-hppa.c, config/tc-m68k.c,
        config/tc-mips.c, config/tc-ppc.c, config/tc-sh.c, config/tc-xtensa.c:
        Similarly in the respective tc_frob_label implementation functions.
        * config/tc-i386.c (md_pseudo_table): Move file and loc to
        non-elf section; add loc_mark_labels.
        * config/tc-ia64.c (struct label_fix): Add dw2_mark_labels.
        (ia64_flush_insns): Check for marked labels; emit line entry if so.
        (emit_one_bundle): Similarly.
        (ia64_frob_label): Record marked labels.
        * config/tc-m68hc11.h (tc_frob_label): Remove.
        * config/tc-ms1.c (md_pseudo_table): Remove file and loc.
        * config/tc-sh.h (tc_frob_label): Pass sym to sh_frob_label.
        * config/tc-sh64.h (tc_frob_label): Likewise.
        * doc/as.texinfo (LNS directives): Docuement .loc_mark_blocks.

Index: dwarf2dbg.c
===================================================================
RCS file: /cvs/src/src/gas/dwarf2dbg.c,v
retrieving revision 1.78
diff -u -p -d -r1.78 dwarf2dbg.c
--- dwarf2dbg.c 7 Sep 2005 19:22:40 -0000 1.78
+++ dwarf2dbg.c 20 Sep 2005 18:01:30 -0000
@@ -105,8 +105,7 @@
 
 struct line_entry {
   struct line_entry *next;
-  fragS *frag;
-  addressT frag_ofs;
+  symbolS *label;
   struct dwarf2_line_info loc;
 };
 
@@ -147,6 +146,10 @@ static unsigned int dirs_allocated;
    doing work when there's nothing to do.  */
 static bfd_boolean loc_directive_seen;
 
+/* TRUE when we're supposed to set the basic block mark whenever a
+   label is seen.  */
+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,
@@ -167,12 +170,11 @@ static void out_four (int);
 static void out_abbrev (int, int);
 static void out_uleb128 (addressT);
 static offsetT get_frag_fix (fragS *);
-static void out_set_addr (segT, fragS *, addressT);
+static void out_set_addr (symbolS *);
 static int size_inc_line_addr (int, addressT);
 static void emit_inc_line_addr (int, addressT, char *, int);
 static void out_inc_line_addr (int, addressT);
-static void relax_inc_line_addr (int, segT, fragS *, addressT,
- fragS *, addressT);
+static void relax_inc_line_addr (int, symbolS *, symbolS *);
 static void process_entries (segT, struct line_entry *);
 static void out_file_list (void);
 static void out_debug_line (segT);
@@ -247,16 +249,34 @@ get_line_subseg (segT seg, subsegT subse
   return ss;
 }
 
+/* Record an entry for LOC occurring at LABEL.  */
+
+static void
+dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
+{
+  struct line_subseg *ss;
+  struct line_entry *e;
+
+  e = (struct line_entry *) xmalloc (sizeof (*e));
+  e->next = NULL;
+  e->label = label;
+  e->loc = *loc;
+
+  ss = get_line_subseg (now_seg, now_subseg);
+  *ss->ptail = e;
+  ss->ptail = &e->next;
+}
+
 /* Record an entry for LOC occurring at OFS within the current fragment.  */
 
 void
 dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
 {
-  struct line_subseg *ss;
-  struct line_entry *e;
   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;
@@ -272,15 +292,8 @@ dwarf2_gen_line_info (addressT ofs, stru
   line = loc->line;
   filenum = loc->filenum;
 
-  e = (struct line_entry *) xmalloc (sizeof (*e));
-  e->next = NULL;
-  e->frag = frag_now;
-  e->frag_ofs = ofs;
-  e->loc = *loc;
-
-  ss = get_line_subseg (now_seg, now_subseg);
-  *ss->ptail = e;
-  ss->ptail = &e->next;
+  sym = symbol_temp_new (now_seg, ofs, frag_now);
+  dwarf2_gen_line_info_1 (sym, loc);
 }
 
 /* Returns the current source information.  If .file directives have
@@ -349,6 +362,38 @@ dwarf2_emit_insn (int size)
      | DWARF2_FLAG_EPILOGUE_BEGIN);
 }
 
+/* Called for each (preferably code) label.  If dwarf2_loc_mark_labels
+   is enabled, emit a basic block marker.  */
+
+void
+dwarf2_emit_label (symbolS *label)
+{
+  struct dwarf2_line_info loc;
+
+  if (!dwarf2_loc_mark_labels)
+    return;
+  if (S_GET_SEGMENT (label) != now_seg)
+    return;
+  if (!(bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE))
+    return;
+  
+  if (debug_type == DEBUG_DWARF2)
+    dwarf2_where (&loc);
+  else
+    {
+      loc = current;
+      loc_directive_seen = FALSE;
+    }
+
+  loc.flags |= DWARF2_FLAG_BASIC_BLOCK;
+
+  current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
+     | DWARF2_FLAG_PROLOGUE_END
+     | DWARF2_FLAG_EPILOGUE_BEGIN);
+
+  dwarf2_gen_line_info_1 (label, &loc);
+}
+
 /* Get a .debug_line file number for FILENAME.  If NUM is nonzero,
    allocate it on that file table slot, otherwise return the first
    empty one.  */
@@ -603,6 +648,23 @@ dwarf2_directive_loc (int dummy ATTRIBUT
   demand_empty_rest_of_line ();
   loc_directive_seen = TRUE;
 }
+
+void
+dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
+{
+  offsetT value = get_absolute_expression ();
+
+  if (value != 0 && value != 1)
+    {
+      as_bad (_("expected 0 or 1"));
+      ignore_rest_of_line ();
+    }
+  else
+    {
+      dwarf2_loc_mark_labels = value != 0;
+      demand_empty_rest_of_line ();
+    }
+}
 
 static struct frag *
 first_frag_for_seg (segT seg)
@@ -702,12 +764,9 @@ get_frag_fix (fragS *frag)
 /* Set an absolute address (may result in a relocation entry).  */
 
 static void
-out_set_addr (segT seg, fragS *frag, addressT ofs)
+out_set_addr (symbolS *sym)
 {
   expressionS expr;
-  symbolS *sym;
-
-  sym = symbol_temp_new (seg, ofs, frag);
 
   out_opcode (DW_LNS_extended_op);
   out_uleb128 (sizeof_address + 1);
@@ -811,6 +870,10 @@ emit_inc_line_addr (int line_delta, addr
   int need_copy = 0;
   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);
+
   /* Scale the address delta by the minimum instruction length.  */
   scale_addr_delta (&addr_delta);
 
@@ -906,17 +969,11 @@ out_inc_line_addr (int line_delta, addre
    increments between fragments of the target segment.  */
 
 static void
-relax_inc_line_addr (int line_delta, segT seg,
-     fragS *to_frag, addressT to_ofs,
-     fragS *from_frag, addressT from_ofs)
+relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
 {
-  symbolS *to_sym, *from_sym;
   expressionS expr;
   int max_chars;
 
-  to_sym = symbol_temp_new (seg, to_ofs, to_frag);
-  from_sym = symbol_temp_new (seg, from_ofs, from_frag);
-
   expr.X_op = O_subtract;
   expr.X_add_symbol = to_sym;
   expr.X_op_symbol = from_sym;
@@ -999,22 +1056,20 @@ process_entries (segT seg, struct line_e
   unsigned column = 0;
   unsigned isa = 0;
   unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
-  fragS *frag = NULL;
-  fragS *last_frag;
-  addressT frag_ofs = 0;
-  addressT last_frag_ofs;
+  fragS *last_frag = NULL, *frag;
+  addressT last_frag_ofs = 0, frag_ofs;
+  symbolS *last_lab, *lab;
   struct line_entry *next;
 
   while (e)
     {
-      int changed = 0;
+      int line_delta;
 
       if (filenum != e->loc.filenum)
  {
   filenum = e->loc.filenum;
   out_opcode (DW_LNS_set_file);
   out_uleb128 (filenum);
-  changed = 1;
  }
 
       if (column != e->loc.column)
@@ -1022,7 +1077,6 @@ process_entries (segT seg, struct line_e
   column = e->loc.column;
   out_opcode (DW_LNS_set_column);
   out_uleb128 (column);
-  changed = 1;
  }
 
       if (isa != e->loc.isa)
@@ -1030,62 +1084,46 @@ process_entries (segT seg, struct line_e
   isa = e->loc.isa;
   out_opcode (DW_LNS_set_isa);
   out_uleb128 (isa);
-  changed = 1;
  }
 
       if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT)
  {
   flags = e->loc.flags;
   out_opcode (DW_LNS_negate_stmt);
-  changed = 1;
  }
 
       if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
- {
-  out_opcode (DW_LNS_set_basic_block);
-  changed = 1;
- }
+ out_opcode (DW_LNS_set_basic_block);
 
       if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
- {
-  out_opcode (DW_LNS_set_prologue_end);
-  changed = 1;
- }
+ out_opcode (DW_LNS_set_prologue_end);
 
       if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
- {
-  out_opcode (DW_LNS_set_epilogue_begin);
-  changed = 1;
- }
+ out_opcode (DW_LNS_set_epilogue_begin);
 
       /* Don't try to optimize away redundant entries; gdb wants two
  entries for a function where the code starts on the same line as
  the {, and there's no way to identify that case here.  Trust gcc
  to optimize appropriately.  */
-      if (1 /* line != e->loc.line || changed */)
- {
-  int line_delta = e->loc.line - line;
-  if (frag == NULL)
-    {
-      out_set_addr (seg, e->frag, e->frag_ofs);
-      out_inc_line_addr (line_delta, 0);
-    }
-  else if (frag == e->frag)
-    out_inc_line_addr (line_delta, e->frag_ofs - frag_ofs);
-  else
-    relax_inc_line_addr (line_delta, seg, e->frag, e->frag_ofs,
- frag, frag_ofs);
+      line_delta = e->loc.line - line;
+      lab = e->label;
+      frag = symbol_get_frag (lab);
+      frag_ofs = S_GET_VALUE (lab);
 
-  frag = e->frag;
-  frag_ofs = e->frag_ofs;
-  line = e->loc.line;
- }
-      else if (frag == NULL)
+      if (last_frag == NULL)
  {
-  out_set_addr (seg, e->frag, e->frag_ofs);
-  frag = e->frag;
-  frag_ofs = e->frag_ofs;
+  out_set_addr (lab);
+  out_inc_line_addr (line_delta, 0);
  }
+      else if (frag == last_frag)
+ out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
+      else
+ relax_inc_line_addr (line_delta, lab, last_lab);
+
+      line = e->loc.line;
+      last_lab = lab;
+      last_frag = frag;
+      last_frag_ofs = frag_ofs;
 
       next = e->next;
       free (e);
@@ -1093,13 +1131,15 @@ process_entries (segT seg, struct line_e
     }
 
   /* Emit a DW_LNE_end_sequence for the end of the section.  */
-  last_frag = last_frag_for_seg (seg);
-  last_frag_ofs = get_frag_fix (last_frag);
+  frag = last_frag_for_seg (seg);
+  frag_ofs = get_frag_fix (frag);
   if (frag == last_frag)
-    out_inc_line_addr (INT_MAX, last_frag_ofs - frag_ofs);
+    out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
   else
-    relax_inc_line_addr (INT_MAX, seg, last_frag, last_frag_ofs,
- frag, frag_ofs);
+    {
+      lab = symbol_temp_new (seg, frag_ofs, frag);
+      relax_inc_line_addr (INT_MAX, lab, last_lab);
+    }
 }
 
 /* Emit the directory and file tables for .debug_line.  */
Index: dwarf2dbg.h
===================================================================
RCS file: /cvs/src/src/gas/dwarf2dbg.h,v
retrieving revision 1.17
diff -u -p -d -r1.17 dwarf2dbg.h
--- dwarf2dbg.h 7 Sep 2005 19:22:40 -0000 1.17
+++ dwarf2dbg.h 20 Sep 2005 18:01:30 -0000
@@ -49,6 +49,9 @@ extern char *dwarf2_directive_file (int
    used.  */
 extern void dwarf2_directive_loc (int dummy);
 
+/* Implements the .loc_mark_labels {0,1} directive.  */
+extern void dwarf2_directive_loc_mark_labels (int dummy);
+
 /* Returns the current source information.  If .file directives have
    been encountered, the info for the corresponding source file is
    returned.  Otherwise, the info for the assembly source file is
@@ -69,6 +72,14 @@ extern void dwarf2_gen_line_info (addres
 /* Must be called for each generated instruction.  */
 extern void dwarf2_emit_insn (int);
 
+/* Should be called for each code label.  */
+extern void dwarf2_emit_label (symbolS *);
+
+/* True when we're supposed to set the basic block mark whenever a label
+   is seen.  Unless the target is doing Something Weird, just call
+   dwarf2_emit_label.  */
+bfd_boolean dwarf2_loc_mark_labels;
+
 extern void dwarf2_finish (void);
 
 extern int dwarf2dbg_estimate_size_before_relax (fragS *);
Index: config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.95
diff -u -p -d -r1.95 obj-elf.c
--- config/obj-elf.c 25 Jul 2005 15:41:07 -0000 1.95
+++ config/obj-elf.c 20 Sep 2005 18:01:30 -0000
@@ -115,6 +115,7 @@ static const pseudo_typeS elf_pseudo_tab
   /* These are used for dwarf2.  */
   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
   { "loc",  dwarf2_directive_loc,  0 },
+  { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
 
   /* We need to trap the section changing calls to handle .previous.  */
   {"data", obj_elf_data, 0},
Index: config/obj-elf.h
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.h,v
retrieving revision 1.27
diff -u -p -d -r1.27 obj-elf.h
--- config/obj-elf.h 25 Jul 2005 15:41:07 -0000 1.27
+++ config/obj-elf.h 20 Sep 2005 18:01:30 -0000
@@ -156,6 +156,13 @@ extern void elf_frob_file_before_adjust
 #endif
 extern void elf_frob_file_after_relocs (void);
 
+/* If the target doesn't have special processing for labels, take care of
+   dwarf2 output at the object file level.  */
+#ifndef tc_frob_label
+#include "dwarf2dbg.h"
+#define obj_frob_label  dwarf2_emit_label
+#endif
+
 #ifndef obj_app_file
 #define obj_app_file elf_file_symbol
 #endif
Index: config/tc-alpha.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.c,v
retrieving revision 1.69
diff -u -p -d -r1.69 tc-alpha.c
--- config/tc-alpha.c 7 Jun 2005 17:54:15 -0000 1.69
+++ config/tc-alpha.c 20 Sep 2005 18:01:32 -0000
@@ -5464,6 +5464,9 @@ void
 alpha_define_label (symbolS *sym)
 {
   alpha_insn_label = sym;
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* Return true if we must always emit a reloc for a type and false if
Index: config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.226
diff -u -p -d -r1.226 tc-arm.c
--- config/tc-arm.c 8 Sep 2005 12:49:22 -0000 1.226
+++ config/tc-arm.c 20 Sep 2005 18:01:34 -0000
@@ -8092,6 +8092,10 @@ arm_frob_label (symbolS * sym)
 
       label_is_thumb_function_name = FALSE;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 int
Index: config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.123
diff -u -p -d -r1.123 tc-hppa.c
--- config/tc-hppa.c 19 Jul 2005 01:14:10 -0000 1.123
+++ config/tc-hppa.c 20 Sep 2005 18:01:35 -0000
@@ -1287,6 +1287,10 @@ pa_define_label (symbol)
 
       label_symbols_rootp = label_chain;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (symbol);
+#endif
 }
 
 /* Removes a label definition for the current space.
Index: config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.196
diff -u -p -d -r1.196 tc-i386.c
--- config/tc-i386.c 14 Sep 2005 06:33:25 -0000 1.196
+++ config/tc-i386.c 20 Sep 2005 18:01:36 -0000
@@ -469,10 +469,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"code64", set_code_flag, CODE_64BIT},
   {"intel_syntax", set_intel_syntax, 1},
   {"att_syntax", set_intel_syntax, 0},
-  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
-  {"loc", dwarf2_directive_loc, 0},
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   {"largecomm", handle_large_common, 0},
+#else
+  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
+  {"loc", dwarf2_directive_loc, 0},
+  {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
 #endif
 #ifdef TE_PE
   {"secrel32", pe_directive_secrel, 0},
Index: config/tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.174
diff -u -p -d -r1.174 tc-ia64.c
--- config/tc-ia64.c 27 Jul 2005 06:32:45 -0000 1.174
+++ config/tc-ia64.c 20 Sep 2005 18:01:38 -0000
@@ -159,6 +159,7 @@ struct label_fix
 {
   struct label_fix *next;
   struct symbol *sym;
+  bfd_boolean dw2_mark_labels;
 };
 
 /* This is the endianness of the current section.  */
@@ -1083,6 +1084,7 @@ ia64_flush_insns ()
   segT saved_seg;
   subsegT saved_subseg;
   unw_rec_list *ptr;
+  bfd_boolean mark;
 
   if (!md.last_text_seg)
     return;
@@ -1096,18 +1098,23 @@ ia64_flush_insns ()
     emit_one_bundle (); /* force out queued instructions */
 
   /* In case there are labels following the last instruction, resolve
-     those now:  */
+     those now.  */
+  mark = FALSE;
   for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      symbol_set_value_now (lfix->sym);
+      mark |= lfix->dw2_mark_labels;
     }
-  CURR_SLOT.label_fixups = 0;
-  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+  if (mark)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      dwarf2_where (&CURR_SLOT.debug_line);
+      CURR_SLOT.debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+      dwarf2_gen_line_info (frag_now_fix (), &CURR_SLOT.debug_line);
     }
+  CURR_SLOT.label_fixups = 0;
+
+  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+    symbol_set_value_now (lfix->sym);
   CURR_SLOT.tag_fixups = 0;
 
   /* In case there are unwind directives following the last instruction,
@@ -6647,6 +6654,7 @@ emit_one_bundle ()
   int n, i, j, first, curr, last_slot;
   bfd_vma t0 = 0, t1 = 0;
   struct label_fix *lfix;
+  bfd_boolean mark_label;
   struct insn_fix *ifix;
   char mnemonic[16];
   fixS *fix;
@@ -6967,11 +6975,30 @@ emit_one_bundle ()
       if (insn_unit != required_unit)
  continue; /* Try next slot.  */
 
-      if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen)
+      /* Now is a good time to fix up the labels for this insn.  */
+      mark_label = FALSE;
+      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
+ {
+  S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
+  symbol_set_frag (lfix->sym, frag_now);
+  mark_label |= lfix->dw2_mark_labels;
+ }
+      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
+ {
+  S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
+  symbol_set_frag (lfix->sym, frag_now);
+ }
+
+      if (debug_type == DEBUG_DWARF2
+  || md.slot[curr].loc_directive_seen
+  || mark_label)
  {
   bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i;
 
   md.slot[curr].loc_directive_seen = 0;
+  if (mark_label)
+    md.slot[curr].debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+
   dwarf2_gen_line_info (addr, &md.slot[curr].debug_line);
  }
 
@@ -7000,19 +7027,6 @@ emit_one_bundle ()
       --md.num_slots_in_use;
       last_slot = i;
 
-      /* now is a good time to fix up the labels for this insn:  */
-      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
- {
-  S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
-  symbol_set_frag (lfix->sym, frag_now);
- }
-      /* and fix up the tags also.  */
-      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
- {
-  S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
-  symbol_set_frag (lfix->sym, frag_now);
- }
-
       for (j = 0; j < md.slot[curr].num_fixups; ++j)
  {
   ifix = md.slot[curr].fixup + j;
@@ -7904,6 +7918,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.tag_fixups;
+      fix->dw2_mark_labels = FALSE;
       CURR_SLOT.tag_fixups = fix;
 
       return;
@@ -7915,6 +7930,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.label_fixups;
+      fix->dw2_mark_labels = dwarf2_loc_mark_labels;
       CURR_SLOT.label_fixups = fix;
 
       /* Keep track of how many code entry points we've seen.  */
Index: config/tc-m68hc11.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68hc11.h,v
retrieving revision 1.20
diff -u -p -d -r1.20 tc-m68hc11.h
--- config/tc-m68hc11.h 11 Aug 2005 01:25:27 -0000 1.20
+++ config/tc-m68hc11.h 20 Sep 2005 18:01:38 -0000
@@ -101,9 +101,6 @@ extern int tc_m68hc11_force_relocation (
 extern int tc_m68hc11_fix_adjustable (struct fix *);
 
 #define md_operand(x)
-#define tc_frob_label(sym) do {\
-  S_SET_VALUE (sym, (valueT) frag_now_fix ()); \
-} while (0)
 
 #define elf_tc_final_processing m68hc11_elf_final_processing
 extern void m68hc11_elf_final_processing (void);
Index: config/tc-m68k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68k.c,v
retrieving revision 1.69
diff -u -p -d -r1.69 tc-m68k.c
--- config/tc-m68k.c 11 Aug 2005 01:25:27 -0000 1.69
+++ config/tc-m68k.c 20 Sep 2005 18:01:39 -0000
@@ -4394,6 +4394,10 @@ m68k_frob_label (symbolS *sym)
   n->text = 0;
   labels = n;
   current_label = n;
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* This is called when a value that is not an instruction is emitted.  */
Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.321
diff -u -p -d -r1.321 tc-mips.c
--- config/tc-mips.c 7 Sep 2005 11:39:17 -0000 1.321
+++ config/tc-mips.c 20 Sep 2005 18:01:41 -0000
@@ -13594,6 +13594,10 @@ mips_define_label (symbolS *sym)
   l->label = sym;
   l->next = insn_labels;
   insn_labels = l;
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
Index: config/tc-ms1.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ms1.c,v
retrieving revision 1.1
diff -u -p -d -r1.1 tc-ms1.c
--- config/tc-ms1.c 5 Jul 2005 13:08:08 -0000 1.1
+++ config/tc-ms1.c 20 Sep 2005 18:01:41 -0000
@@ -63,8 +63,6 @@ const char FLT_CHARS[]            = "dD"
 const pseudo_typeS md_pseudo_table[] =
 {
     { "word",   cons,                   4 },
-    { "file", (void (*) (int)) dwarf2_directive_file, 0 },
-    { "loc", dwarf2_directive_loc, 0 },
     { NULL, NULL, 0 }
 };
 
Index: config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.106
diff -u -p -d -r1.106 tc-ppc.c
--- config/tc-ppc.c 23 Aug 2005 06:18:45 -0000 1.106
+++ config/tc-ppc.c 20 Sep 2005 18:01:42 -0000
@@ -4840,6 +4840,10 @@ ppc_frob_label (sym)
      &symbol_rootP, &symbol_lastP);
       symbol_get_tc (ppc_current_csect)->within = sym;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* This variable is set by ppc_frob_symbol if any absolute symbols are
Index: config/tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.111
diff -u -p -d -r1.111 tc-sh.c
--- config/tc-sh.c 18 Aug 2005 11:54:33 -0000 1.111
+++ config/tc-sh.c 20 Sep 2005 18:01:43 -0000
@@ -2876,7 +2876,7 @@ md_assemble (char *str)
    emits a BFD_RELOC_SH_LABEL reloc if necessary.  */
 
 void
-sh_frob_label (void)
+sh_frob_label (symbolS *sym)
 {
   static fragS *last_label_frag;
   static int last_label_offset;
@@ -2895,6 +2895,8 @@ sh_frob_label (void)
   last_label_offset = offset;
  }
     }
+
+  dwarf2_emit_label (sym);
 }
 
 /* This routine is called when the assembler is about to output some
Index: config/tc-sh.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.h,v
retrieving revision 1.39
diff -u -p -d -r1.39 tc-sh.h
--- config/tc-sh.h 18 Aug 2005 11:54:33 -0000 1.39
+++ config/tc-sh.h 20 Sep 2005 18:01:43 -0000
@@ -103,8 +103,8 @@ struct sh_segment_info_type
 
 /* We call a routine to emit a reloc for a label, so that the linker
    can align loads and stores without crossing a label.  */
-extern void sh_frob_label (void);
-#define tc_frob_label(sym) sh_frob_label ()
+extern void sh_frob_label (symbolS *);
+#define tc_frob_label(sym) sh_frob_label (sym)
 
 /* We call a routine to flush pending output in order to output a DATA
    reloc when required.  */
Index: config/tc-sh64.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh64.h,v
retrieving revision 1.11
diff -u -p -d -r1.11 tc-sh64.h
--- config/tc-sh64.h 9 May 2005 14:20:51 -0000 1.11
+++ config/tc-sh64.h 20 Sep 2005 18:01:43 -0000
@@ -144,7 +144,7 @@ extern void sh64_frob_label (symbolS *);
 
 #undef  tc_frob_label
 #define tc_frob_label(sym) \
-  do { sh_frob_label (); sh64_frob_label (sym); } while (0)
+  do { sh_frob_label (sym); sh64_frob_label (sym); } while (0)
 
 #define tc_symbol_new_hook(s) sh64_frob_label (s)
 
Index: config/tc-xtensa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.c,v
retrieving revision 1.44
diff -u -p -d -r1.44 tc-xtensa.c
--- config/tc-xtensa.c 7 Jun 2005 18:31:34 -0000 1.44
+++ config/tc-xtensa.c 20 Sep 2005 18:01:45 -0000
@@ -5054,7 +5054,7 @@ xtensa_frob_label (symbolS *sym)
 
       xtensa_set_frag_assembly_state (frag_now);
       xtensa_move_labels (frag_now, 0, TRUE);
-  }
+    }
 
   /* No target aligning in the absolute section.  */
   if (now_seg != absolute_section
@@ -5083,6 +5083,8 @@ xtensa_frob_label (symbolS *sym)
   /* Loops only go forward, so they can be identified here.  */
   if (symbol_get_tc (sym)->is_loop_target)
     symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
+
+  dwarf2_emit_label (sym);
 }
 
 
Index: doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.128
diff -u -p -d -r1.128 as.texinfo
--- doc/as.texinfo 8 Sep 2005 18:05:14 -0000 1.128
+++ doc/as.texinfo 20 Sep 2005 18:01:46 -0000
@@ -4103,6 +4103,15 @@ either 0 or 1.
 @item isa @var{value}
 This directive will set the @code{isa} register in the @code{.debug_line}
 state machine to @var{value}, which must be an unsigned integer.
+
+@section @code{.loc_mark_blocks @var{enable}}
+@cindex @code{loc_mark_blocks} directive
+The @code{.loc_mark_blocks} directive makes the assembler emit an entry
+to the @code{.debug_line} line number matrix with the @code{basic_block}
+register in the state machine set whenever a code label is seen.
+The @var{enable} argument should be either 1 or 0, to enable or disable
+this function respectively.
+
 @end table
 
 @node Data
Reply | Threaded
Open this post in threaded view
|

Re: new .loc_mark_blocks directive

Andreas Schwab
Richard Henderson <[hidden email]> writes:

> Adds a directive that puts the assembler in a mode in which it
> adds a line number entry with the basic_block flag whenever a
> label is seen in a code section.

This breaks the ia64 assembler and miscompiles the Linux kernel.

$ cat xdata.s
 .section ".data.patch.vtop", "a"
 .previous
 .text
 .align 16
        nop 0
[1:] movl r2 = 1f
        .xdata4 ".data.patch.vtop", 1b-.
1: nop 0
$ as.bad -o a.out.bad xdata.s; objdump -r a.out.bad > a.out.bad.dump
$ as.good -o a.out.good xdata.s; objdump -r a.out.good > a.out.good.dump
$ diff -u a.out.*.dump
--- a.out.bad.dump 2005-11-29 00:04:23.000000000 +0100
+++ a.out.good.dump 2005-11-29 00:04:30.000000000 +0100
@@ -1,5 +1,5 @@
 
-a.out.bad:     file format elf64-ia64-little
+a.out.good:     file format elf64-ia64-little
 
 RELOCATION RECORDS FOR [.text]:
 OFFSET           TYPE              VALUE
@@ -8,6 +8,6 @@
 
 RELOCATION RECORDS FOR [.data.patch.vtop]:
 OFFSET           TYPE              VALUE
-0000000000000000 PCREL32LSB        .text+0x0000000000000001
+0000000000000000 PCREL32LSB        .text+0x0000000000000002
 
 

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstra?e 5, 90409 N?rnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: new .loc_mark_blocks directive

Jim Wilson-6
On Mon, 2005-11-28 at 15:42, Andreas Schwab wrote:
> This breaks the ia64 assembler and miscompiles the Linux kernel.
> -0000000000000000 PCREL32LSB        .text+0x0000000000000001
> +0000000000000000 PCREL32LSB        .text+0x0000000000000002

This looks like FSF Binutils PR 1433, which was fixed with a linux
kernel patch.  The linux kernel patch is in the PR.

The linux kernel is wrong to insist that a movl instruction in slot 1
must have a tag pointing at slot 2.  But the kernel got it wrong only
because binutils got it wrong first.  There are additional comments in
the PR.
--
Jim Wilson, GNU Tools Support, http://www.specifix.com

Reply | Threaded
Open this post in threaded view
|

Re: new .loc_mark_blocks directive

Andreas Schwab
James E Wilson <[hidden email]> writes:

> On Mon, 2005-11-28 at 15:42, Andreas Schwab wrote:
>> This breaks the ia64 assembler and miscompiles the Linux kernel.
>> -0000000000000000 PCREL32LSB        .text+0x0000000000000001
>> +0000000000000000 PCREL32LSB        .text+0x0000000000000002
>
> This looks like FSF Binutils PR 1433, which was fixed with a linux
> kernel patch.  The linux kernel patch is in the PR.

Thanks for the pointer.  Looks like 2.6.14 is just too old. :-/

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstra?e 5, 90409 N?rnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."