aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.c
diff options
context:
space:
mode:
authorTerry Guo <terry.guo@arm.com>2014-08-21 18:00:35 +0800
committerTerry Guo <terry.guo@arm.com>2014-08-21 18:00:35 +0800
commitc542398150124a0b5adbbeeb274e55ee56d3120a (patch)
tree6aad77db344e75217caa41097faf6fc474c49fa9 /bfd/elf32-arm.c
parentde589d04f30e658fcf4ba37a678c9487c128f97f (diff)
downloadgdb-c542398150124a0b5adbbeeb274e55ee56d3120a.zip
gdb-c542398150124a0b5adbbeeb274e55ee56d3120a.tar.gz
gdb-c542398150124a0b5adbbeeb274e55ee56d3120a.tar.bz2
bfd/ChangeLog
2014-08-21 Tony Wang <tony.wang@arm.com> * elf32-arm.c (elf32_arm_final_link_relocate): Implement the veneer routine for R_ARM_THM_JUMP19. (arm_type_of_stub): Add conditional clause for R_ARM_THM_JUMP19 (elf32_arm_size_stub): Ditto. ld/testsuite/ChangeLog 2014-08-21 Tony Wang <tony.wang@arm.com> * ld-arm/jump-reloc-veneers-cond.s: New test. * ld-arm/farcall-cond-thumb-arm.s: Ditto. * ld-arm/jump-reloc-veneers-cond-short.d: Expected output for target without a veneer generation. * ld-arm/jump-reloc-veneers-cond-long.d: Expected output for target with a veneer generation. * ld-arm/farcall-cond-thumb-arm.d: Expected output for inter working veneer generation. * ld-arm/arm-elf.exp: Add tests for conditional branch veneer.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r--bfd/elf32-arm.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 73b5fb0..89d51c1 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2283,6 +2283,8 @@ static const bfd_vma elf32_arm_nacl_plt_entry [] =
#define THM_MAX_BWD_BRANCH_OFFSET (-(1 << 22) + 4)
#define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
+#define THM2_MAX_FWD_COND_BRANCH_OFFSET (((1 << 20) -2) + 4)
+#define THM2_MAX_BWD_COND_BRANCH_OFFSET (-(1 << 20) + 4)
enum stub_insn_type
{
@@ -3667,7 +3669,8 @@ arm_type_of_stub (struct bfd_link_info *info,
/* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
are considering a function call relocation. */
- if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
+ if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
+ || r_type == R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
branch_type = ST_BRANCH_TO_THUMB;
@@ -3711,7 +3714,7 @@ arm_type_of_stub (struct bfd_link_info *info,
branch_offset = (bfd_signed_vma)(destination - location);
if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
- || r_type == R_ARM_THM_TLS_CALL)
+ || r_type == R_ARM_THM_TLS_CALL || r_type == R_ARM_THM_JUMP19)
{
/* Handle cases where:
- this call goes too far (different Thumb/Thumb2 max
@@ -3727,10 +3730,15 @@ arm_type_of_stub (struct bfd_link_info *info,
|| (thumb2
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
+ || (thumb2
+ && (branch_offset > THM2_MAX_FWD_COND_BRANCH_OFFSET
+ || (branch_offset < THM2_MAX_BWD_COND_BRANCH_OFFSET))
+ && (r_type == R_ARM_THM_JUMP19))
|| (branch_type == ST_BRANCH_TO_ARM
&& (((r_type == R_ARM_THM_CALL
|| r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx)
- || (r_type == R_ARM_THM_JUMP24))
+ || (r_type == R_ARM_THM_JUMP24)
+ || (r_type == R_ARM_THM_JUMP19))
&& !use_plt))
{
if (branch_type == ST_BRANCH_TO_THUMB)
@@ -5347,7 +5355,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* For historical reasons, use the existing names for
ARM-to-Thumb and Thumb-to-ARM stubs. */
if ((r_type == (unsigned int) R_ARM_THM_CALL
- || r_type == (unsigned int) R_ARM_THM_JUMP24)
+ || r_type == (unsigned int) R_ARM_THM_JUMP24
+ || r_type == (unsigned int) R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
sprintf (stub_entry->output_name,
THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
@@ -9125,6 +9134,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_signed_vma reloc_signed_max = 0xffffe;
bfd_signed_vma reloc_signed_min = -0x100000;
bfd_signed_vma signed_check;
+ enum elf32_arm_stub_type stub_type = arm_stub_none;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct elf32_arm_link_hash_entry *hash;
/* Need to refetch the addend, reconstruct the top three bits,
and squish the two 11 bit pieces together. */
@@ -9156,8 +9168,25 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
*unresolved_reloc_p = FALSE;
}
- /* ??? Should handle interworking? GCC might someday try to
- use this for tail calls. */
+ hash = (struct elf32_arm_link_hash_entry *)h;
+
+ stub_type = arm_type_of_stub (info, input_section, rel,
+ st_type, &branch_type,
+ hash, value, sym_sec,
+ input_bfd, sym_name);
+ if (stub_type != arm_stub_none)
+ {
+ stub_entry = elf32_arm_get_stub_entry (input_section,
+ sym_sec, h,
+ rel, globals,
+ stub_type);
+ if (stub_entry != NULL)
+ {
+ value = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
+ }
+ }
relocation = value + signed_addend;
relocation -= (input_section->output_section->vma