diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 14 | ||||
-rw-r--r-- | gas/dwarf2dbg.c | 155 | ||||
-rw-r--r-- | gas/read.c | 62 | ||||
-rw-r--r-- | gas/read.h | 3 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gas/testsuite/gas/lns/lns-big-delta.d | 14 | ||||
-rw-r--r-- | gas/testsuite/gas/lns/lns-big-delta.s | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/lns/lns.exp | 1 |
8 files changed, 183 insertions, 78 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 331727f..46f36be 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 8befbd0..615d644 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -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) + len = 1 + sizeof_leb128 (line_delta, 1); + + 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) { - out_opcode (DW_LNS_fixed_advance_pc); - expr.X_op = O_subtract; + *p++ = DW_LNS_advance_line; + p += output_leb128 (p, line_delta, 1); + } + + exp = symbol_get_value_expression (frag->fr_symbol); + line_seg = subseg_get (".debug_line", 0); + + /* 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; + + 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_op_symbol = from_sym; expr.X_add_number = 0; - emit_expr (&expr, 2); - - out_opcode (DW_LNS_extended_op); - out_byte (1); - out_opcode (DW_LNE_end_sequence); - return; + 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; } - out_opcode (DW_LNS_advance_line); - out_sleb128 (line_delta); - - 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) + { + *p++ = DW_LNS_extended_op; + *p++ = 1; + *p++ = DW_LNE_end_sequence; + } + else + *p++ = DW_LNS_copy; - out_opcode (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 { @@ -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); +} + +void +emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p) +{ + memset (p, 0, nbytes); - /* Now we need to generate a fixS to record the symbol value. */ + /* 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 @@ -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); diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index cedaa25..fb0aa85 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -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 diff --git a/gas/testsuite/gas/lns/lns-big-delta.d b/gas/testsuite/gas/lns/lns-big-delta.d new file mode 100644 index 0000000..6190138 --- /dev/null +++ b/gas/testsuite/gas/lns/lns-big-delta.d @@ -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 diff --git a/gas/testsuite/gas/lns/lns-big-delta.s b/gas/testsuite/gas/lns/lns-big-delta.s new file mode 100644 index 0000000..a959748 --- /dev/null +++ b/gas/testsuite/gas/lns/lns-big-delta.s @@ -0,0 +1,5 @@ + .file 1 "foo.c" + .loc 1 1 0 + .loc 1 2 0 + .space 75000 + .loc 1 3 0 diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp index b292f2e..e3f176f 100644 --- a/gas/testsuite/gas/lns/lns.exp +++ b/gas/testsuite/gas/lns/lns.exp @@ -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 { |