* dwarf2dbg.c (out_sleb128): Delete.
	(size_fixed_inc_line_addr, emit_fixed_inc_line_addr): New.
	(out_fixed_inc_line_addr): Delete.
	(relax_inc_line_addr, dwarf2dbg_estimate_size_before_relax): Call new
	size_fixed_inc_line_addr if DWARF2_USE_FIXED_ADVANCE_PC is set.
	(dwarf2dbg_convert_frag): Likewise for emit_fixed_inc_line_addr.
	(process_entries): Remove calls to out_fixed_inc_line_addr.  When
	DWARF2_USE_FIXED_ADVANCE_PC is set, call relax_inc_line_addr.
	* read.h (emit_expr_fix): New prototype.
	* read.c (emit_expr): Move code to emit_expr_fix and use it here.
	(emit_expr_fix): New.
testsuite/
	* gas/lns/lns.exp: Run new lns-big-delta test for targets that set
	DWARF2_USE_FIXED_ADVANCE_PC.
	* gas/lns/lns-big-delta.s: New.
	* gas/lns/lns-big-delta.d: New.
This commit is contained in:
Bob Wilson 2008-01-09 17:30:59 +00:00
parent 39d5313e31
commit 7ddd14deff
8 changed files with 185 additions and 80 deletions

View File

@ -1,3 +1,17 @@
2008-01-09 Bob Wilson <bob.wilson@acm.org>
* dwarf2dbg.c (out_sleb128): Delete.
(size_fixed_inc_line_addr, emit_fixed_inc_line_addr): New.
(out_fixed_inc_line_addr): Delete.
(relax_inc_line_addr, dwarf2dbg_estimate_size_before_relax): Call new
size_fixed_inc_line_addr if DWARF2_USE_FIXED_ADVANCE_PC is set.
(dwarf2dbg_convert_frag): Likewise for emit_fixed_inc_line_addr.
(process_entries): Remove calls to out_fixed_inc_line_addr. When
DWARF2_USE_FIXED_ADVANCE_PC is set, call relax_inc_line_addr.
* read.h (emit_expr_fix): New prototype.
* read.c (emit_expr): Move code to emit_expr_fix and use it here.
(emit_expr_fix): New.
2008-01-09 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (match_template): Check register size

View File

@ -1,5 +1,5 @@
/* dwarf2dbg.c - DWARF2 debug support
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
@ -198,13 +198,13 @@ static void out_two (int);
static void out_four (int);
static void out_abbrev (int, int);
static void out_uleb128 (addressT);
static void out_sleb128 (addressT);
static offsetT get_frag_fix (fragS *, segT);
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 int size_fixed_inc_line_addr (int, addressT);
static void emit_fixed_inc_line_addr (int, addressT, fragS *, char *, int);
static void out_inc_line_addr (int, addressT);
static void out_fixed_inc_line_addr (int, symbolS *, symbolS *);
static void relax_inc_line_addr (int, symbolS *, symbolS *);
static void process_entries (segT, struct line_entry *);
static void out_file_list (void);
@ -762,14 +762,6 @@ 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_sleb128 (addressT value)
{
output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
}
/* Emit a tuple for .debug_abbrev. */
static inline void
@ -1005,41 +997,103 @@ out_inc_line_addr (int line_delta, addressT addr_delta)
/* Write out an alternative form of line and address skips using
DW_LNS_fixed_advance_pc opcodes. This uses more space than the default
line and address information, but it helps support linker relaxation that
changes the code offsets. */
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. */
static void
out_fixed_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
static int
size_fixed_inc_line_addr (int line_delta, addressT addr_delta)
{
expressionS expr;
int len = 0;
/* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. */
if (line_delta == INT_MAX)
{
out_opcode (DW_LNS_fixed_advance_pc);
expr.X_op = O_subtract;
expr.X_add_symbol = to_sym;
expr.X_op_symbol = from_sym;
expr.X_add_number = 0;
emit_expr (&expr, 2);
if (line_delta != INT_MAX)
len = 1 + sizeof_leb128 (line_delta, 1);
out_opcode (DW_LNS_extended_op);
out_byte (1);
out_opcode (DW_LNE_end_sequence);
return;
if (addr_delta > 50000)
{
/* DW_LNS_extended_op */
len += 1 + sizeof_leb128 (sizeof_address + 1, 0);
/* DW_LNE_set_address */
len += 1 + sizeof_address;
}
else
/* DW_LNS_fixed_advance_pc */
len += 3;
if (line_delta == INT_MAX)
/* DW_LNS_extended_op + DW_LNE_end_sequence */
len += 3;
else
/* DW_LNS_copy */
len += 1;
return len;
}
static void
emit_fixed_inc_line_addr (int line_delta, addressT addr_delta, fragS *frag,
char *p, int len)
{
expressionS *exp;
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);
/* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. */
if (line_delta != INT_MAX)
{
*p++ = DW_LNS_advance_line;
p += output_leb128 (p, line_delta, 1);
}
out_opcode (DW_LNS_advance_line);
out_sleb128 (line_delta);
exp = symbol_get_value_expression (frag->fr_symbol);
line_seg = subseg_get (".debug_line", 0);
out_opcode (DW_LNS_fixed_advance_pc);
expr.X_op = O_subtract;
expr.X_add_symbol = to_sym;
expr.X_op_symbol = from_sym;
expr.X_add_number = 0;
emit_expr (&expr, 2);
/* The DW_LNS_fixed_advance_pc opcode has a 2-byte operand so it can
advance the address by at most 64K. Linker relaxation (without
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)
{
symbolS *to_sym;
expressionS expr;
out_opcode (DW_LNS_copy);
assert (exp->X_op = O_subtract);
to_sym = exp->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;
subseg_change (line_seg, 0);
emit_expr_fix (&expr, 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);
p += 2;
}
if (line_delta == INT_MAX)
{
*p++ = DW_LNS_extended_op;
*p++ = 1;
*p++ = DW_LNE_end_sequence;
}
else
*p++ = DW_LNS_copy;
assert (p == end);
}
/* Generate a variant frag that we can use to relax address/line
@ -1058,7 +1112,11 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
/* The maximum size of the frag is the line delta with a maximum
sized address delta. */
max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH);
if (DWARF2_USE_FIXED_ADVANCE_PC)
max_chars = size_fixed_inc_line_addr (line_delta,
-DWARF2_LINE_MIN_INSN_LENGTH);
else
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);
@ -1075,7 +1133,10 @@ dwarf2dbg_estimate_size_before_relax (fragS *frag)
int size;
addr_delta = resolve_symbol_value (frag->fr_symbol);
size = size_inc_line_addr (frag->fr_offset, addr_delta);
if (DWARF2_USE_FIXED_ADVANCE_PC)
size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
else
size = size_inc_line_addr (frag->fr_offset, addr_delta);
frag->fr_subtype = size;
@ -1113,8 +1174,13 @@ dwarf2dbg_convert_frag (fragS *frag)
course, have allocated enough memory earlier. */
assert (frag->fr_var >= (int) frag->fr_subtype);
emit_inc_line_addr (frag->fr_offset, addr_diff,
frag->fr_literal + frag->fr_fix, frag->fr_subtype);
if (DWARF2_USE_FIXED_ADVANCE_PC)
emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
frag->fr_literal + frag->fr_fix,
frag->fr_subtype);
else
emit_inc_line_addr (frag->fr_offset, addr_diff,
frag->fr_literal + frag->fr_fix, frag->fr_subtype);
frag->fr_fix += frag->fr_subtype;
frag->fr_type = rs_fill;
@ -1192,9 +1258,7 @@ process_entries (segT seg, struct line_entry *e)
out_set_addr (lab);
out_inc_line_addr (line_delta, 0);
}
else if (DWARF2_USE_FIXED_ADVANCE_PC)
out_fixed_inc_line_addr (line_delta, lab, last_lab);
else if (frag == last_frag)
else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
else
relax_inc_line_addr (line_delta, lab, last_lab);
@ -1213,12 +1277,7 @@ process_entries (segT seg, struct line_entry *e)
/* Emit a DW_LNE_end_sequence for the end of the section. */
frag = last_frag_for_seg (seg);
frag_ofs = get_frag_fix (frag, seg);
if (DWARF2_USE_FIXED_ADVANCE_PC)
{
lab = symbol_temp_new (seg, frag_ofs, frag);
out_fixed_inc_line_addr (INT_MAX, lab, last_lab);
}
else if (frag == last_frag)
if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
else
{

View File

@ -1,6 +1,6 @@
/* read.c - read a source file -
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -4175,41 +4175,45 @@ emit_expr (expressionS *exp, unsigned int nbytes)
}
}
else
{
memset (p, 0, nbytes);
emit_expr_fix (exp, nbytes, frag_now, p);
}
/* Now we need to generate a fixS to record the symbol value. */
void
emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p)
{
memset (p, 0, nbytes);
/* Generate a fixS to record the symbol value. */
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
TC_CONS_FIX_NEW (frag, p - frag->fr_literal, nbytes, exp);
#else
{
bfd_reloc_code_real_type r;
{
bfd_reloc_code_real_type r;
switch (nbytes)
{
case 1:
r = BFD_RELOC_8;
break;
case 2:
r = BFD_RELOC_16;
break;
case 4:
r = BFD_RELOC_32;
break;
case 8:
r = BFD_RELOC_64;
break;
default:
as_bad (_("unsupported BFD relocation size %u"), nbytes);
r = BFD_RELOC_32;
break;
}
fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
0, r);
switch (nbytes)
{
case 1:
r = BFD_RELOC_8;
break;
case 2:
r = BFD_RELOC_16;
break;
case 4:
r = BFD_RELOC_32;
break;
case 8:
r = BFD_RELOC_64;
break;
default:
as_bad (_("unsupported BFD relocation size %u"), nbytes);
r = BFD_RELOC_32;
break;
}
fix_new_exp (frag, p - frag->fr_literal, (int) nbytes, exp,
0, r);
}
#endif
}
}
#ifdef BITFIELD_CONS_EXPRESSIONS

View File

@ -1,6 +1,6 @@
/* read.h - of read.c
Copyright 1986, 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2007
2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -111,6 +111,7 @@ extern void add_include_dir (char *path);
extern void cons (int nbytes);
extern void demand_empty_rest_of_line (void);
extern void emit_expr (expressionS *exp, unsigned int nbytes);
extern void emit_expr_fix (expressionS *, unsigned int, fragS *, char *);
extern void equals (char *sym_name, int reassign);
extern void float_cons (int float_type);
extern void ignore_rest_of_line (void);

View File

@ -1,3 +1,10 @@
2008-01-09 Bob Wilson <bob.wilson@acm.org>
* gas/lns/lns.exp: Run new lns-big-delta test for targets that set
DWARF2_USE_FIXED_ADVANCE_PC.
* gas/lns/lns-big-delta.s: New.
* gas/lns/lns-big-delta.d: New.
2008-01-08 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR gas/5322

View File

@ -0,0 +1,14 @@
#source: lns-big-delta.s
#readelf: -wl
#name: lns-big-delta
Dump of debug contents of section \.debug_line:
#...
Line Number Statements:
Extended opcode 2: set Address to .*
Copy
Advance Line by 1 to 2
Extended opcode 2: set Address to .*
Copy
Advance PC by fixed size amount 0 to .*
Extended opcode 1: End of Sequence
#pass

View File

@ -0,0 +1,5 @@
.file 1 "foo.c"
.loc 1 1 0
.loc 1 2 0
.space 75000
.loc 1 3 0

View File

@ -22,6 +22,7 @@ if {
# Use alternate file for targets using DW_LNS_fixed_advance_pc opcodes.
if { [istarget xtensa-*-*] } {
run_dump_test "lns-common-1-alt"
run_dump_test "lns-big-delta"
} elseif { [istarget ia64*-*-*] } {
run_dump_test "lns-common-1" { { source "lns-common-1-ia64.s" } }
} else {