[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>
* 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);
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:

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>
* 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 "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"

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