[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:
parent
40fbed8481
commit
07f9ddfeba
10 changed files with 160 additions and 30 deletions
|
@ -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>
|
||||
|
||||
* elfnn-aarch64.c (IS_AARCH64_TLS_RELOC): Recognize
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
value = (splt->output_section->vma
|
||||
+ splt->output_offset + h->plt.offset);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
/* 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:
|
||||
|
|
|
@ -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>
|
||||
|
||||
* ld-aarch64/emit-relocs-529.s: New testcase.
|
||||
|
|
|
@ -127,6 +127,9 @@ run_dump_test "limit-b"
|
|||
run_dump_test "limit-bl"
|
||||
run_dump_test "farcall-section"
|
||||
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-b"
|
||||
run_dump_test "farcall-b-none-function"
|
||||
|
|
5
ld/testsuite/ld-aarch64/farcall-b-gsym.d
Normal file
5
ld/testsuite/ld-aarch64/farcall-b-gsym.d
Normal 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'.*
|
17
ld/testsuite/ld-aarch64/farcall-b-gsym.s
Normal file
17
ld/testsuite/ld-aarch64/farcall-b-gsym.s
Normal 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
|
38
ld/testsuite/ld-aarch64/farcall-b-plt.d
Normal file
38
ld/testsuite/ld-aarch64/farcall-b-plt.d
Normal 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
|
||||
...
|
11
ld/testsuite/ld-aarch64/farcall-b-plt.s
Normal file
11
ld/testsuite/ld-aarch64/farcall-b-plt.s
Normal 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
|
38
ld/testsuite/ld-aarch64/farcall-bl-plt.d
Normal file
38
ld/testsuite/ld-aarch64/farcall-bl-plt.d
Normal 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
|
||||
...
|
12
ld/testsuite/ld-aarch64/farcall-bl-plt.s
Normal file
12
ld/testsuite/ld-aarch64/farcall-bl-plt.s
Normal 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
|
Loading…
Reference in a new issue