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]

Commit: Patch: GAS: Fix DWARF line number generation for target that use linker relaxation


Hi Guys,

  I am applying the patch below to fix a problem with DWARF line number
  debug information generation by GAS.  For targets which use linker
  relaxation the address deltas between changes in line numbers cannot
  be computed at assembly time.  Instead relocations must be generated
  and the deltas computed at final link time.  Most of the framework to
  do this is already in gas/dwarf2dbg.c, but this patch makes sure that
  it will work for all targets that use linker relaxation.

  Tested with lots of toolchains, especially mn10300-elf and xtensa-elf.

Cheers
  Nick

gas/ChangeLog
2012-06-28  Nick Clifton  <nickc@redhat.com>

	* dwarf2dbg.c (DWARF2_USE_FIXED_ADVANCE_PC): Enable when using
	linker relaxation.
	(dwarf2_gen_line_info): Generate real, local, labels for line
	numbers.
	(dwarf2dbg_convert_frag): Do not finalize the computation of the
	frag's symbol value when linker relaxation is enabled.
	(ADDR_DELTA_LIMIT): Define.
	(size_fixed_inc_line_addr): Use ADDR_DELTA_LIMIT.
	(emit_fixed_inc_line_addr): Likewise.
	* write.c (fixup_segment): If the subtraction of two symbols
	cannot be resolved but is valid, then prevent bogus range warnings
	by pre-biasing add_number.
	* config/tc-h8300.h (DWARF2_USE_FIXED_ADVANCE_PC): Define to 0.

gas/testsuite/ChangeLog
2012-06-28  Nick Clifton  <nickc@redhat.com>

	* gas/lns/lns.exp: Use alternate lns-common test for targets
	enabling linker relaxation.
	* gas/lns/lns-big-delta.d: Allow for output from architectures
	with 32-bit addresses.

Index: gas/dwarf2dbg.c
===================================================================
RCS file: /cvs/src/src/gas/dwarf2dbg.c,v
retrieving revision 1.115
diff -u -3 -p -r1.115 dwarf2dbg.c
--- gas/dwarf2dbg.c	30 Apr 2012 14:32:28 -0000	1.115
+++ gas/dwarf2dbg.c	28 Jun 2012 10:56:43 -0000
@@ -119,7 +119,7 @@
    opcodes and variable-length operands cannot be used.  If this macro is
    nonzero, use the DW_LNS_fixed_advance_pc opcode instead.  */
 #ifndef DWARF2_USE_FIXED_ADVANCE_PC
-# define DWARF2_USE_FIXED_ADVANCE_PC	0
+# define DWARF2_USE_FIXED_ADVANCE_PC	linkrelax
 #endif
 
 /* First special line opcde - leave room for the standard opcodes.
@@ -361,7 +361,17 @@ dwarf2_gen_line_info (addressT ofs, stru
   filenum = loc->filenum;
 
   dwarf2_push_line (loc);
-  dwarf2_flush_pending_lines (symbol_temp_new (now_seg, ofs, frag_now));
+  if (linkrelax)
+    {
+      char name[120];
+
+      /* Use a non-fake name for the line number location,
+	 so that it can be referred to by relocations.  */
+      sprintf (name, ".Loc.%u.%u", line, filenum);
+      dwarf2_flush_pending_lines (symbol_new (name, now_seg, ofs, frag_now));
+    }
+  else
+    dwarf2_flush_pending_lines (symbol_temp_new (now_seg, ofs, frag_now));
 }
 
 /* Returns the current source information.  If .file directives have
@@ -1064,6 +1074,7 @@ out_inc_line_addr (int line_delta, addre
    line and address information, but it is required if linker relaxation
    could change the code offsets.  The following two routines *must* be
    kept in sync.  */
+#define ADDR_DELTA_LIMIT 50000
 
 static int
 size_fixed_inc_line_addr (int line_delta, addressT addr_delta)
@@ -1074,7 +1085,7 @@ size_fixed_inc_line_addr (int line_delta
   if (line_delta != INT_MAX)
     len = 1 + sizeof_leb128 (line_delta, 1);
 
-  if (addr_delta > 50000)
+  if (addr_delta > ADDR_DELTA_LIMIT)
     {
       /* DW_LNS_extended_op */
       len += 1 + sizeof_leb128 (sizeof_address + 1, 0);
@@ -1122,7 +1133,7 @@ emit_fixed_inc_line_addr (int line_delta
      which this function would not be used) could change the operand by
      an unknown amount.  If the address increment is getting close to
      the limit, just reset the address.  */
-  if (addr_delta > 50000)
+  if (addr_delta > ADDR_DELTA_LIMIT)
     {
       symbolS *to_sym;
       expressionS exp;
@@ -1231,7 +1242,24 @@ dwarf2dbg_convert_frag (fragS *frag)
 {
   offsetT addr_diff;
 
-  addr_diff = resolve_symbol_value (frag->fr_symbol);
+  if (DWARF2_USE_FIXED_ADVANCE_PC)
+    {
+      /* If linker relaxation is enabled then the distance bewteen the two
+	 symbols in the frag->fr_symbol expression might change.  Hence we
+	 cannot rely upon the value computed by resolve_symbol_value.
+	 Instead we leave the expression unfinalized and allow
+	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
+	 relocation) that will allow the linker to correctly compute the
+	 actual address difference.  We have to use a fixed line advance for
+	 this as we cannot (easily) relocate leb128 encoded values.  */
+      int saved_finalize_syms = finalize_syms;
+
+      finalize_syms = 0;
+      addr_diff = resolve_symbol_value (frag->fr_symbol);
+      finalize_syms = saved_finalize_syms;
+    }
+  else
+    addr_diff = resolve_symbol_value (frag->fr_symbol);
 
   /* fr_var carries the max_chars that we created the fragment with.
      fr_subtype carries the current expected length.  We must, of
Index: gas/write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.149
diff -u -3 -p -r1.149 write.c
--- gas/write.c	21 Feb 2012 13:39:36 -0000	1.149
+++ gas/write.c	28 Jun 2012 10:56:43 -0000
@@ -1019,6 +1020,11 @@ fixup_segment (fixS *fixP, segT this_seg
 			      S_GET_NAME (fixP->fx_subsy),
 			      segment_name (sub_symbol_segment));
 	    }
+	  else
+	    /* If the fix is valid, subtract fx_subsy here.  The addition of
+	       fx_addsy will be performed below.  Doing this prevents bogus
+	       warnings from the range check below.  */
+	      add_number -= S_GET_VALUE (fixP->fx_subsy);
 	}
 
       if (fixP->fx_addsy)
Index: gas/config/tc-h8300.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-h8300.h,v
retrieving revision 1.24
diff -u -3 -p -r1.24 tc-h8300.h
--- gas/config/tc-h8300.h	2 Sep 2009 07:24:20 -0000	1.24
+++ gas/config/tc-h8300.h	28 Jun 2012 10:56:45 -0000
@@ -51,6 +51,7 @@ struct internal_reloc;
 
 /* Minimum instruction is of 16 bits.  */
 #define DWARF2_LINE_MIN_INSN_LENGTH 2
+#define DWARF2_USE_FIXED_ADVANCE_PC 0
 
 #ifdef OBJ_ELF
 /* Provide mappings from the original H8 COFF relocation names to
Index: gas/testsuite/gas/lns/lns-big-delta.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/lns/lns-big-delta.d,v
retrieving revision 1.3
diff -u -3 -p -r1.3 lns-big-delta.d
--- gas/testsuite/gas/lns/lns-big-delta.d	24 May 2012 15:36:33 -0000	1.3
+++ gas/testsuite/gas/lns/lns-big-delta.d	28 Jun 2012 10:56:46 -0000
@@ -10,8 +10,8 @@ Raw dump of debug contents of section \.
   Advance PC by fixed size amount 0 to 0x0
   Copy
   Advance Line by 1 to 3
-  Extended opcode 2: set Address to 0x124fc
+  Extended opcode 2: set Address to 0x.....
   Copy
-  Advance PC by fixed size amount 4 to 0x12500
+  Advance PC by fixed size amount . to 0x.....
   Extended opcode 1: End of Sequence
 #pass
Index: gas/testsuite/gas/lns/lns.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/lns/lns.exp,v
retrieving revision 1.13
diff -u -3 -p -r1.13 lns.exp
--- gas/testsuite/gas/lns/lns.exp	29 Sep 2009 14:17:10 -0000	1.13
+++ gas/testsuite/gas/lns/lns.exp	28 Jun 2012 10:56:46 -0000
@@ -17,7 +17,10 @@ if {
      && ![istarget s390*-*-*]
 } {
     # Use alternate file for targets using DW_LNS_fixed_advance_pc opcodes.
-    if { [istarget xtensa*-*-*] } {
+    if {    [istarget xtensa*-*-*]
+	 || [istarget am3*-*-*]
+	 || [istarget cr16-*-*]
+	 || [istarget mn10*-*-*] } {
       run_dump_test "lns-common-1-alt"
       run_dump_test "lns-big-delta"
     } elseif { [istarget ia64*-*-*] } {


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