diff options
author | Jiong Wang <jiong.wang@arm.com> | 2015-08-11 21:44:31 +0100 |
---|---|---|
committer | Jiong Wang <jiong.wang@arm.com> | 2015-08-11 21:44:31 +0100 |
commit | 07f9ddfeba5b572451471f905473f7ddbba1d472 (patch) | |
tree | b3a2c40afe3a4a0e86a2709ef7c79d46cf340a79 /bfd | |
parent | 40fbed84815b00960f7fac8d2e7857942df4308c (diff) | |
download | gdb-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/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 51 |
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: |