This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Commit: Patch: GAS: Fix DWARF line number generation for target that use linker relaxation
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Thu, 28 Jun 2012 12:25:44 +0100
- Subject: 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*-*-*] } {