summaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2008-06-09 14:53:13 +0000
committerDaniel Jacobowitz <drow@false.org>2008-06-09 14:53:13 +0000
commitf4ac8484646f3c9e8e7a89d49f2d01b5bdd1c39f (patch)
tree238040e369d5cbec1440b619dd6984f7dd0f2e25 /bfd/elf32-arm.c
parent2424f303731f7ad383eb8b1dc885e11c3b9f7385 (diff)
downloadbinutils-gdb-f4ac8484646f3c9e8e7a89d49f2d01b5bdd1c39f.tar.gz
2008-06-03 Christophe Lyon <christophe.lyon@st.com>
bfd/ * elf32-arm.c (arm_stub_is_thumb): Define. (elf32_arm_final_link_relocate): Handle near mode switching stubs. ld/testsuite/ * ld-arm/farcall-thumb-thumb-m.d: Fix branch type. * ld-arm/farcall-thumb-arm.d: Likewise.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r--bfd/elf32-arm.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 1e32554dc0f..1101369917e 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2713,6 +2713,23 @@ using_thumb2 (struct elf32_arm_link_hash_table *globals)
return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7;
}
+static bfd_boolean
+arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
+{
+ switch (stub_type)
+ {
+ case arm_thumb_thumb_stub_long_branch:
+ case arm_thumb_arm_v4t_stub_long_branch:
+ return TRUE;
+ case arm_stub_none:
+ BFD_FAIL ();
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
/* Determine the type of stub needed, if any, for a call. */
static enum elf32_arm_stub_type
@@ -6426,7 +6443,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
||
(thumb2
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
- || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))))
+ || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
+ || ((sym_flags != STT_ARM_TFUNC) && !globals->use_blx))
{
/* The target is out of reach or we are changing modes, so
redirect the branch to the local stub for this
@@ -6439,8 +6457,14 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
+ stub_entry->stub_sec->output_offset
+ stub_entry->stub_sec->output_section->vma);
- /* This call becomes a call to Arm for sure. Force BLX. */
- lower_insn = (lower_insn & ~0x1000) | 0x0800;
+ /* If this call becomes a call to Arm, force BLX. */
+ if (globals->use_blx)
+ {
+ if ((stub_entry
+ && !arm_stub_is_thumb (stub_entry->stub_type))
+ || (sym_flags != STT_ARM_TFUNC))
+ lower_insn = (lower_insn & ~0x1000) | 0x0800;
+ }
}
}