diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1f06e7e9cf..b817554130 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2014-09-22 Andrew Bennett + + * elfxx-mips.c (mips_elf_calculate_relocation): Don't sign extend + the addend if relocations are RELA. + 2014-09-22 Kuan-Lin Chen * elf32-nds32.c (nds32_elf_ex9_build_hash_table, diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 2c7b35f113..7343835792 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -5714,7 +5714,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, return bfd_reloc_continue; case R_MIPS_16: - value = symbol + _bfd_mips_elf_sign_extend (addend, 16); + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 16); + value = symbol + addend; overflowed_p = mips_elf_overflow_p (value, 16); break; @@ -5786,8 +5788,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, if (was_local_p) value = addend | ((p + 4) & (0xfc000000 << shift)); - else + else if (howto->partial_inplace) value = _bfd_mips_elf_sign_extend (addend, 26 + shift); + else + value = addend; value = (value + symbol) >> shift; if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak) overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift)); @@ -5972,7 +5976,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MIPS_PC16: case R_MIPS_GNU_REL16_S2: - value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p; + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 18); + + if ((symbol + addend) & 3) + return bfd_reloc_outofrange; + + value = symbol + addend - p; overflowed_p = mips_elf_overflow_p (value, 18); value >>= howto->rightshift; value &= howto->dst_mask; @@ -6044,28 +6054,36 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, break; case R_MICROMIPS_PC7_S1: - value = symbol + _bfd_mips_elf_sign_extend (addend, 8) - p; + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 8); + value = symbol + addend - p; overflowed_p = mips_elf_overflow_p (value, 8); value >>= howto->rightshift; value &= howto->dst_mask; break; case R_MICROMIPS_PC10_S1: - value = symbol + _bfd_mips_elf_sign_extend (addend, 11) - p; + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 11); + value = symbol + addend - p; overflowed_p = mips_elf_overflow_p (value, 11); value >>= howto->rightshift; value &= howto->dst_mask; break; case R_MICROMIPS_PC16_S1: - value = symbol + _bfd_mips_elf_sign_extend (addend, 17) - p; + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 17); + value = symbol + addend - p; overflowed_p = mips_elf_overflow_p (value, 17); value >>= howto->rightshift; value &= howto->dst_mask; break; case R_MICROMIPS_PC23_S2: - value = symbol + _bfd_mips_elf_sign_extend (addend, 25) - ((p | 3) ^ 3); + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 25); + value = symbol + addend - ((p | 3) ^ 3); overflowed_p = mips_elf_overflow_p (value, 25); value >>= howto->rightshift; value &= howto->dst_mask;