aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2015-08-11 21:44:31 +0100
committerJiong Wang <jiong.wang@arm.com>2015-08-11 21:44:31 +0100
commit07f9ddfeba5b572451471f905473f7ddbba1d472 (patch)
treeb3a2c40afe3a4a0e86a2709ef7c79d46cf340a79 /bfd
parent40fbed84815b00960f7fac8d2e7857942df4308c (diff)
downloadgdb-07f9ddfeba5b572451471f905473f7ddbba1d472.zip
gdb-07f9ddfeba5b572451471f905473f7ddbba1d472.tar.gz
gdb-07f9ddfeba5b572451471f905473f7ddbba1d472.tar.bz2
[AArch64] PR18668, repair long branch veneer for plt stub
2015-08-11 Jiong Wang <jiong.wang@arm.com> bfd/ PR ld/18668 * elfnn-aarch64.c (aarch64_type_of_stub): Update destination for calls go through plt stub. (elfNN_aarch64_final_link_relocate): Adjust code logic for CALL26, JUMP26 relocation to support inserting veneer for call to plt stub. ld/testsuite/ * ld-aarch64/farcall-b-gsym.s: New test. * ld-aarch64/farcall-b-plt.s: Likewise. * ld-aarch64/farcall-bl-plt.s: Likewise. * ld-aarch64/farcall-b-gsym.d: New expect file. * ld-aarch64/farcall-b-plt.d: Likewise. * ld-aarch64/farcall-bl-plt.d: Likewise.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elfnn-aarch64.c51
2 files changed, 28 insertions, 31 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 97fffdd..e2378fe 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,13 @@
2015-08-11 Jiong Wang <jiong.wang@arm.com>
+ PR ld/18668
+ * elfnn-aarch64.c (aarch64_type_of_stub): Update destination for
+ calls go through plt stub.
+ (elfNN_aarch64_final_link_relocate): Adjust code logic for CALL26,
+ JUMP26 relocation to support inserting veneer for call to plt stub.
+
+2015-08-11 Jiong Wang <jiong.wang@arm.com>
+
* elfnn-aarch64.c (IS_AARCH64_TLS_RELOC): Recognize
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12.
(aarch64_reloc_got_type): Likewise.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index c8ad421..097a275 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -2333,9 +2333,11 @@ aarch64_type_of_stub (struct bfd_link_info *info,
globals = elf_aarch64_hash_table (info);
via_plt_p = (globals->root.splt != NULL && hash != NULL
&& hash->root.plt.offset != (bfd_vma) - 1);
-
+ /* Make sure call to plt stub can fit into the branch range. */
if (via_plt_p)
- return stub_type;
+ destination = (globals->root.splt->output_section->vma
+ + globals->root.splt->output_offset
+ + hash->root.plt.offset);
/* Determine where the call point is. */
location = (input_sec->output_offset
@@ -4890,38 +4892,25 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
/* If the call goes through a PLT entry, make sure to
check distance to the right destination address. */
if (via_plt_p)
- {
- value = (splt->output_section->vma
- + splt->output_offset + h->plt.offset);
- *unresolved_reloc_p = FALSE;
- }
-
- /* If the target symbol is global and marked as a function the
- relocation applies a function call or a tail call. In this
- situation we can veneer out of range branches. The veneers
- use IP0 and IP1 hence cannot be used arbitrary out of range
- branches that occur within the body of a function. */
- if (h && h->type == STT_FUNC)
- {
- /* Check if a stub has to be inserted because the destination
- is too far away. */
- if (! aarch64_valid_branch_p (value, place))
- {
- /* The target is out of reach, so redirect the branch to
- the local stub for this function. */
- struct elf_aarch64_stub_hash_entry *stub_entry;
- stub_entry = elfNN_aarch64_get_stub_entry (input_section,
- sym_sec, h,
- rel, globals);
- if (stub_entry != NULL)
- value = (stub_entry->stub_offset
- + stub_entry->stub_sec->output_offset
- + stub_entry->stub_sec->output_section->vma);
- }
- }
+ value = (splt->output_section->vma
+ + splt->output_offset + h->plt.offset);
+
+ /* Check if a stub has to be inserted because the destination
+ is too far away. */
+ struct elf_aarch64_stub_hash_entry *stub_entry = NULL;
+ if (! aarch64_valid_branch_p (value, place))
+ /* The target is out of reach, so redirect the branch to
+ the local stub for this function. */
+ stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h,
+ rel, globals);
+ if (stub_entry != NULL)
+ value = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
}
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
signed_addend, weak_undef_p);
+ *unresolved_reloc_p = FALSE;
break;
case BFD_RELOC_AARCH64_16_PCREL: