diff options
Diffstat (limited to 'bfd/elf32-arm.h')
-rw-r--r-- | bfd/elf32-arm.h | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index afe3c8f..3a5939d 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -1499,6 +1499,47 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, } break; + case R_ARM_THM_PC11: + /* Thumb B (branch) instruction). */ + { + bfd_vma relocation; + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + bfd_vma check; + bfd_signed_vma signed_check; + +#ifdef USE_REL + /* Need to refetch addend. */ + addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask; + /* ??? Need to determine shift amount from operand size. */ + addend >>= howto->rightshift; +#endif + relocation = value + addend; + + relocation -= (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); + + check = relocation >> howto->rightshift; + + /* If this is a signed value, the rightshift just + dropped leading 1 bits (assuming twos complement). */ + if ((bfd_signed_vma) relocation >= 0) + signed_check = check; + else + signed_check = check | ~((bfd_vma) -1 >> howto->rightshift); + + relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask)); + + bfd_put_16 (input_bfd, relocation, hit_data); + + /* Assumes two's complement. */ + if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) + return bfd_reloc_overflow; + + return bfd_reloc_ok; + } + case R_ARM_GNU_VTINHERIT: case R_ARM_GNU_VTENTRY: return bfd_reloc_ok; |