From 2ff09d18f9d671b755bce1b22d9adf78a314199d Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 15 Nov 2011 13:08:16 +0000 Subject: * write.c (dump_section_relocs): Don't convert PC-relative relocs that have an in-place addend narrower than the addresses used. --- gas/write.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'gas/write.c') diff --git a/gas/write.c b/gas/write.c index cf59d7da88..a1e0205f86 100644 --- a/gas/write.c +++ b/gas/write.c @@ -654,15 +654,21 @@ dump_section_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, FILE *stream) static void resolve_reloc_expr_symbols (void) { + bfd_vma addr_mask = 1; struct reloc_list *r; + /* Avoid a shift by the width of type. */ + addr_mask <<= bfd_arch_bits_per_address (stdoutput) - 1; + addr_mask <<= 1; + addr_mask -= 1; + for (r = reloc_list; r; r = r->next) { + reloc_howto_type *howto = r->u.a.howto; expressionS *symval; symbolS *sym; bfd_vma offset, addend; asection *sec; - reloc_howto_type *howto; resolve_symbol_value (r->u.a.offset_sym); symval = symbol_get_value_expression (r->u.a.offset_sym); @@ -709,7 +715,16 @@ resolve_reloc_expr_symbols (void) } else if (sym != NULL) { - if (S_IS_LOCAL (sym) && !symbol_section_p (sym)) + /* Convert relocs against local symbols to refer to the + corresponding section symbol plus offset instead. Keep + PC-relative relocs of the REL variety intact though to + prevent the offset from overflowing the relocated field, + unless it has enough bits to cover the whole address + space. */ + if (S_IS_LOCAL (sym) && !symbol_section_p (sym) + && !(howto->partial_inplace + && howto->pc_relative + && howto->src_mask != addr_mask)) { asection *symsec = S_GET_SEGMENT (sym); if (!(((symsec->flags & SEC_MERGE) != 0 @@ -730,8 +745,6 @@ resolve_reloc_expr_symbols (void) sym = abs_section_sym; } - howto = r->u.a.howto; - r->u.b.sec = sec; r->u.b.s = symbol_get_bfdsym (sym); r->u.b.r.sym_ptr_ptr = &r->u.b.s; -- cgit v1.2.1