+2020-08-25 Alan Modra <amodra@gmail.com>
+
+ 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 <amodra@gmail.com>
PR 26419
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;
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;
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
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. */
/* 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