diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f1f0e322fe1..a24957a8c19 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2020-08-25 Alan Modra + + PR 26422 + * elf32-arm.c (elf32_arm_final_link_relocate): Use the appropriate + bfd_get_x size function to read addends out of fields. Apply + rightshift adjustment too. Don't apply the now unnecessary + howto->size shift to branch REL addends. Don't refetch R_ARM_ABS8 + and R_ARM_ABS16 addends. Don't refetch thumb branch addends. + Correct R_ARM_THM_JUMP6 addend. + 2020-08-25 Alan Modra PR 26419 diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 66930c0c7dc..8fec76e4e1d 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -10348,16 +10348,22 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (globals->use_rel) { - addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask; + bfd_vma sign; - if (addend & ((howto->src_mask + 1) >> 1)) + switch (howto->size) { - signed_addend = -1; - signed_addend &= ~ howto->src_mask; - signed_addend |= addend; + case 0: addend = bfd_get_8 (input_bfd, hit_data); break; + case 1: addend = bfd_get_16 (input_bfd, hit_data); break; + case 2: addend = bfd_get_32 (input_bfd, hit_data); break; + default: addend = 0; break; } - else - signed_addend = addend; + /* Note: the addend and signed_addend calculated here are + incorrect for any split field. */ + addend &= howto->src_mask; + sign = howto->src_mask & ~(howto->src_mask >> 1); + signed_addend = (addend ^ sign) - sign; + signed_addend = (bfd_vma) signed_addend << howto->rightshift; + addend <<= howto->rightshift; } else addend = signed_addend = rel->r_addend; @@ -10752,11 +10758,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, value -= (input_section->output_section->vma + input_section->output_offset); value -= rel->r_offset; - if (globals->use_rel) - value += (signed_addend << howto->size); - else - /* RELA addends do not have to be adjusted by howto->size. */ - value += signed_addend; + value += signed_addend; signed_addend = value; signed_addend >>= howto->rightshift; @@ -10860,9 +10862,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, return bfd_reloc_ok; case R_ARM_ABS8: - /* PR 16202: Refectch the addend using the correct size. */ - if (globals->use_rel) - addend = bfd_get_8 (input_bfd, hit_data); value += addend; /* There is no way to tell whether the user intended to use a signed or @@ -10875,9 +10874,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, return bfd_reloc_ok; case R_ARM_ABS16: - /* PR 16202: Refectch the addend using the correct size. */ - if (globals->use_rel) - addend = bfd_get_16 (input_bfd, hit_data); value += addend; /* See comment for R_ARM_ABS8. */ @@ -11356,25 +11352,12 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* CZB cannot jump backward. */ if (r_type == R_ARM_THM_JUMP6) - reloc_signed_min = 0; - - if (globals->use_rel) { - /* Need to refetch addend. */ - addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask; - if (addend & ((howto->src_mask + 1) >> 1)) - { - signed_addend = -1; - signed_addend &= ~ howto->src_mask; - signed_addend |= addend; - } - else - signed_addend = addend; - /* The value in the insn has been right shifted. We need to - undo this, so that we can perform the address calculation - in terms of bytes. */ - signed_addend <<= howto->rightshift; + reloc_signed_min = 0; + if (globals->use_rel) + signed_addend = ((addend & 0x200) >> 3) | ((addend & 0xf8) >> 2); } + relocation = value + signed_addend; relocation -= (input_section->output_section->vma