[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.
This commit is contained in:
Jiong Wang
2015-08-11 21:44:31 +01:00
parent 40fbed8481
commit 07f9ddfeba
10 changed files with 160 additions and 30 deletions

View File

@ -1,3 +1,11 @@
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> 2015-08-11 Jiong Wang <jiong.wang@arm.com>
* elfnn-aarch64.c (IS_AARCH64_TLS_RELOC): Recognize * elfnn-aarch64.c (IS_AARCH64_TLS_RELOC): Recognize

View File

@ -2333,9 +2333,11 @@ aarch64_type_of_stub (struct bfd_link_info *info,
globals = elf_aarch64_hash_table (info); globals = elf_aarch64_hash_table (info);
via_plt_p = (globals->root.splt != NULL && hash != NULL via_plt_p = (globals->root.splt != NULL && hash != NULL
&& hash->root.plt.offset != (bfd_vma) - 1); && hash->root.plt.offset != (bfd_vma) - 1);
/* Make sure call to plt stub can fit into the branch range. */
if (via_plt_p) 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. */ /* Determine where the call point is. */
location = (input_sec->output_offset 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 /* If the call goes through a PLT entry, make sure to
check distance to the right destination address. */ check distance to the right destination address. */
if (via_plt_p) if (via_plt_p)
{ value = (splt->output_section->vma
value = (splt->output_section->vma + splt->output_offset + h->plt.offset);
+ splt->output_offset + h->plt.offset);
*unresolved_reloc_p = FALSE;
}
/* If the target symbol is global and marked as a function the /* Check if a stub has to be inserted because the destination
relocation applies a function call or a tail call. In this is too far away. */
situation we can veneer out of range branches. The veneers struct elf_aarch64_stub_hash_entry *stub_entry = NULL;
use IP0 and IP1 hence cannot be used arbitrary out of range if (! aarch64_valid_branch_p (value, place))
branches that occur within the body of a function. */ /* The target is out of reach, so redirect the branch to
if (h && h->type == STT_FUNC) the local stub for this function. */
{ stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h,
/* Check if a stub has to be inserted because the destination rel, globals);
is too far away. */ if (stub_entry != NULL)
if (! aarch64_valid_branch_p (value, place)) value = (stub_entry->stub_offset
{ + stub_entry->stub_sec->output_offset
/* The target is out of reach, so redirect the branch to + stub_entry->stub_sec->output_section->vma);
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 = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
signed_addend, weak_undef_p); signed_addend, weak_undef_p);
*unresolved_reloc_p = FALSE;
break; break;
case BFD_RELOC_AARCH64_16_PCREL: case BFD_RELOC_AARCH64_16_PCREL:

View File

@ -1,3 +1,12 @@
2015-08-11 Jiong Wang <jiong.wang@arm.com>
* 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.
2015-08-11 Jiong Wang <jiong.wang@arm.com> 2015-08-11 Jiong Wang <jiong.wang@arm.com>
* ld-aarch64/emit-relocs-529.s: New testcase. * ld-aarch64/emit-relocs-529.s: New testcase.

View File

@ -127,6 +127,9 @@ run_dump_test "limit-b"
run_dump_test "limit-bl" run_dump_test "limit-bl"
run_dump_test "farcall-section" run_dump_test "farcall-section"
run_dump_test "farcall-back" run_dump_test "farcall-back"
run_dump_test "farcall-b-gsym"
run_dump_test "farcall-b-plt"
run_dump_test "farcall-bl-plt"
run_dump_test "farcall-bl" run_dump_test "farcall-bl"
run_dump_test "farcall-b" run_dump_test "farcall-b"
run_dump_test "farcall-b-none-function" run_dump_test "farcall-b-none-function"

View File

@ -0,0 +1,5 @@
#name: aarch64-farcall-b-gsym
#source: farcall-b-gsym.s
#as:
#ld: -Ttext 0x1000
#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar_gsym'.*

View File

@ -0,0 +1,17 @@
.global _start
.global bar_gsym
# We will place the section .text at 0x1000.
.text
_start:
# for long jump (JUMP26) to global symbol, we shouldn't insert veneer
# as the veneer will clobber IP0/IP1 which is caller saved, gcc only
# reserve them for function call relocation (CALL26).
b bar_gsym
# ((1 << 25) - 1) << 2
.skip 134217724, 0
bar_gsym:
nop
ret

View File

@ -0,0 +1,38 @@
#name: aarch64-farcall-b-plt
#source: farcall-b-plt.s
#as:
#ld: -shared
#objdump: -dr
#...
Disassembly of section .plt:
.* <foo@plt-0x20>:
.*: a9bf7bf0 stp x16, x30, \[sp,#-16\]!
.*: 90040090 adrp x16, 8010000 <__foo_veneer\+.*>
.*: f941f611 ldr x17, \[x16,#1000\]
.*: 910fa210 add x16, x16, #0x3e8
.*: d61f0220 br x17
.*: d503201f nop
.*: d503201f nop
.*: d503201f nop
.* <foo@plt>:
.*: 90040090 adrp x16, 8010000 <__foo_veneer\+.*>
.*: f941fa11 ldr x17, \[x16,#1008\]
.*: 910fc210 add x16, x16, #0x3f0
.*: d61f0220 br x17
Disassembly of section .text:
.* <_start>:
...
.*: 14000003 b 80002c8 <__foo_veneer>
.*: d65f03c0 ret
.*: 14000007 b 80002e0 <__foo_veneer\+.*>
.* <__foo_veneer>:
.*: 90fc0010 adrp x16, 0 <foo@plt-0x2b0>
.*: 910ac210 add x16, x16, #0x2b0
.*: d61f0200 br x16
...

View File

@ -0,0 +1,11 @@
.global _start
.global foo
.type foo, @function
.text
_start:
# ((1 << 25) - 1) << 2
# jump26 relocation out of range to plt stub,
# we need long branch veneer.
.skip 134217724, 0
b foo
ret

View File

@ -0,0 +1,38 @@
#name: aarch64-farcall-bl-plt
#source: farcall-bl-plt.s
#as:
#ld: -shared
#objdump: -dr
#...
Disassembly of section .plt:
.* <foo@plt-0x20>:
.*: a9bf7bf0 stp x16, x30, \[sp,#-16\]!
.*: 90040090 adrp x16, 8010000 <__foo_veneer\+.*>
.*: f941f611 ldr x17, \[x16,#1000\]
.*: 910fa210 add x16, x16, #0x3e8
.*: d61f0220 br x17
.*: d503201f nop
.*: d503201f nop
.*: d503201f nop
.* <foo@plt>:
.*: 90040090 adrp x16, 8010000 <__foo_veneer\+.*>
.*: f941fa11 ldr x17, \[x16,#1008\]
.*: 910fc210 add x16, x16, #0x3f0
.*: d61f0220 br x17
Disassembly of section .text:
.* <_start>:
...
.*: 94000003 bl 80002c8 <__foo_veneer>
.*: d65f03c0 ret
.*: 14000007 b 80002e0 <__foo_veneer\+.*>
.* <__foo_veneer>:
.*: 90fc0010 adrp x16, 0 <foo@plt-0x2b0>
.*: 910ac210 add x16, x16, #0x2b0
.*: d61f0200 br x16
...

View File

@ -0,0 +1,12 @@
.global _start
.global foo
.type foo, @function
.text
_start:
# ((1 << 25) - 1) << 2
# call26 relocation out of range to plt stub,
# we need long branch veneer.
.skip 134217724, 0
bl foo
ret