This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC][ARM][AARCH64] Set DWARF2_LINE_MIN_INSN_LENGTH to 1


Hi Renlin,

If any cases left the last frag unaligned(size of the frag) to
DWARF2_LINE_MIN_INSN_LENGTH, and assembled with -gdwarf-2 flag,
The following error will be triggered.

'''Error: unaligned opcodes detected in executable segment'''.

For the following code snippet;

.text
ret
.byte 0xf  --> data in .text section, minimum size is different.

I do not think that this is a bug. The assembler is correctly reporting that the user has created a code section that ends not on a code alignment boundary. It does appear however that this kind of thing is expected to work. (See eg gas/testsuite/gas/elf/section7.s). So maybe a solution is needed.

Setting DWARF2_LINE_MIN_INSN_LENGTH to 1 seems wrong to me. For the normal case we want to use a dwarf insn length that matches the architecture's insn length. So instead, how about the attached patch? It changes the dwarf2dbg.c code so that it computes a maximum allowable value for DWARF2_LINE_MIN_INSN_LENGTH automatically, using the target supplied value as a starting point, but reducing it if necessary to support pathological assembly programming.

What do you think ?

Cheers
  Nick








diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
index e67c992..4724f31 100644
--- a/gas/dwarf2dbg.c
+++ b/gas/dwarf2dbg.c
@@ -143,6 +143,7 @@
      bytes).  This value should be rather too small than too big.  */
 # define DWARF2_LINE_MIN_INSN_LENGTH	1
 #endif
+static unsigned int dwarf2_line_min_insn_length = 1;
 
 /* Flag that indicates the initial value of the is_stmt_start flag.  */
 #define	DWARF2_LINE_DEFAULT_IS_STMT	1
@@ -869,20 +870,100 @@ out_set_addr (symbolS *sym)
   emit_expr (&exp, sizeof_address);
 }
 
-static void scale_addr_delta (addressT *);
+/* Compute the maximum possible value for the minimum instruction length.
+   Normally this will be the value DWARF2_LINE_MIN_INSN_LENGTH set by the
+   target.  But if the assembly source includes non-instruction bytes in
+   a code section then it may need to be smaller.  For an example see:
+   gas/testsuite/gas/elf/dwarf2-5.s.  */
+
+static void
+compute_line_min_insn_length (void)
+{
+  struct line_seg *s;
+
+  dwarf2_line_min_insn_length = DWARF2_LINE_MIN_INSN_LENGTH;
+
+  if (dwarf2_line_min_insn_length == 1 || DWARF2_USE_FIXED_ADVANCE_PC)
+    return;
+
+  for (s = all_segs; s; s = s->next)
+    {
+      segT                 seg = s->seg;
+      struct line_entry *  e;
+      symbolS *            lab;
+      fragS *              last_frag = NULL;
+      fragS *              frag;
+      addressT             last_frag_ofs = 0;
+      addressT             frag_ofs;
+
+      if (! SEG_NORMAL (seg))
+	continue;
+
+      e = s->head->head;
+
+      while (e)
+	{
+	  lab = e->label;
+	  frag = symbol_get_frag (lab);
+	  frag_ofs = S_GET_VALUE (lab);
+
+	  if (frag == last_frag)
+	    {
+	      addressT delta = frag_ofs - last_frag_ofs;
+
+	      if ((delta % dwarf2_line_min_insn_length) != 0)
+		{
+		  do
+		    {
+		      dwarf2_line_min_insn_length >>= 1;
+		    }
+		  while (delta % dwarf2_line_min_insn_length != 0);
+
+		  if (dwarf2_line_min_insn_length == 1)
+		    return;
+		}
+	    }
+
+	  last_frag = frag;
+	  last_frag_ofs = frag_ofs;
+	  e = e->next;
+	}
+
+      frag = last_frag_for_seg (seg);
+      if (frag == last_frag)
+	{
+	  addressT delta;
+
+	  frag_ofs = get_frag_fix (frag, seg);
+	  delta = frag_ofs - last_frag_ofs;
+
+	  if ((delta % dwarf2_line_min_insn_length) != 0)
+	    {
+	      do
+		{
+		  dwarf2_line_min_insn_length >>= 1;
+		}
+	      while (delta % dwarf2_line_min_insn_length != 0);
+	    }
+	}
+    }
+}
 
 static void
 scale_addr_delta (addressT *addr_delta)
 {
   static int printed_this = 0;
-  if (DWARF2_LINE_MIN_INSN_LENGTH > 1)
+
+  if (dwarf2_line_min_insn_length > 1)
     {
-      if (*addr_delta % DWARF2_LINE_MIN_INSN_LENGTH != 0  && !printed_this)
+      if (*addr_delta % dwarf2_line_min_insn_length != 0 && !printed_this)
         {
+	  /* FIXME: If this warning is triggered then the code in
+	     compute_line_min_insn_length () above has failed.  */
 	  as_bad("unaligned opcodes detected in executable segment");
           printed_this = 1;
         }
-      *addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH;
+      *addr_delta /= dwarf2_line_min_insn_length;
     }
 }
 
@@ -1173,9 +1254,9 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
      sized address delta.  */
   if (DWARF2_USE_FIXED_ADVANCE_PC)
     max_chars = size_fixed_inc_line_addr (line_delta,
-					  -DWARF2_LINE_MIN_INSN_LENGTH);
+					  - dwarf2_line_min_insn_length);
   else
-    max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH);
+    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 (&exp), line_delta, NULL);
@@ -1538,8 +1619,10 @@ out_debug_line (segT line_seg)
   emit_expr (&exp, sizeof_offset);
   symbol_set_value_now (prologue_start);
 
+  compute_line_min_insn_length ();
+
   /* Parameters of the state machine.  */
-  out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
+  out_byte (dwarf2_line_min_insn_length);
   out_byte (DWARF2_LINE_DEFAULT_IS_STMT);
   out_byte (DWARF2_LINE_BASE);
   out_byte (DWARF2_LINE_RANGE);
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 47b5a21..cfe7c47 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -200,6 +200,7 @@ if { [is_elf_format] } then {
     run_dump_test "dwarf2-2"
     run_dump_test "dwarf2-3"
     run_dump_test "dwarf2-4"
+    gas_test "dwarf2-5.s" "-gdwarf-2" "" "DWARF2: non-aligned code sections"
     run_dump_test "bad-section-flag"
     run_dump_test "bad-size"
     run_dump_test "bad-group"
--- /dev/null	2015-04-01 08:58:06.478958567 +0100
+++ gas/testsuite/gas/elf/dwarf2-5.s	2015-04-01 16:30:07.001070045 +0100
@@ -0,0 +1,16 @@
+# When the following is assembled with -gdwarf-2 enabled the assembler used to
+# report:
+#
+#   dwarf2-5.s: Assembler messages:
+#   dwarf2-5.s: Error: unaligned opcodes detected in executable segment
+#
+# This indicates that the target concerned had an instruction size greater than 1.
+# This should now be fixed by dwarf2dbg.c:compute_line_min_insn_length().
+
+	.text
+	nop
+	.byte 0xf
+
+        .data
+        .byte 2
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]