aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.h
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-arm.h')
-rw-r--r--bfd/elf32-arm.h41
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;