diff options
Diffstat (limited to 'gas/dwarf2dbg.c')
-rw-r--r-- | gas/dwarf2dbg.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index f428f0d..2ec329a 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -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, struct dwarf2_line_info *loc) 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, addressT addr_delta) 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, addressT addr_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, addressT addr_delta, fragS *frag, 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 |