PowerPC64 localentry:0 plt calls

These don't need a following nop.  Also, a localentry:0 plt call
marked with an R_PPC64_TOCSAVE reloc should ignore the tocsave.
There's no need to save r2 in the prologue for such calls.

	* elf64-ppc.c (ppc64_elf_size_stubs): Test for localentry:0 plt
	calls before tocsave calls.
	(ppc64_elf_relocate_section): Allow localentry:0 plt calls without
	following nop.
This commit is contained in:
Alan Modra
2017-06-21 15:03:25 +09:30
parent 81209eff90
commit 6e1816be66
2 changed files with 25 additions and 15 deletions

View File

@ -1,3 +1,10 @@
2017-06-21 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_size_stubs): Test for localentry:0 plt
calls before tocsave calls.
(ppc64_elf_relocate_section): Allow localentry:0 plt calls without
following nop.
2017-06-21 Nick Clifton <nickc@redhat.com> 2017-06-21 Nick Clifton <nickc@redhat.com>
PR binutils/21645 PR binutils/21645

View File

@ -12634,18 +12634,19 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
if (stub_type == ppc_stub_plt_call) if (stub_type == ppc_stub_plt_call)
{ {
if (irela + 1 < irelaend if (!htab->opd_abi
&& irela[1].r_offset == irela->r_offset + 4 && htab->params->plt_localentry0 != 0
&& ELF64_R_TYPE (irela[1].r_info) == R_PPC64_TOCSAVE) && is_elfv2_localentry0 (&hash->elf))
htab->has_plt_localentry0 = 1;
else if (irela + 1 < irelaend
&& irela[1].r_offset == irela->r_offset + 4
&& (ELF64_R_TYPE (irela[1].r_info)
== R_PPC64_TOCSAVE))
{ {
if (!tocsave_find (htab, INSERT, if (!tocsave_find (htab, INSERT,
&local_syms, irela + 1, input_bfd)) &local_syms, irela + 1, input_bfd))
goto error_ret_free_internal; goto error_ret_free_internal;
} }
else if (!htab->opd_abi
&& htab->params->plt_localentry0 != 0
&& is_elfv2_localentry0 (&hash->elf))
htab->has_plt_localentry0 = 1;
else else
stub_type = ppc_stub_plt_call_r2save; stub_type = ppc_stub_plt_call_r2save;
} }
@ -14212,10 +14213,19 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{ {
bfd_boolean can_plt_call = FALSE; bfd_boolean can_plt_call = FALSE;
if (stub_entry->stub_type == ppc_stub_plt_call
&& !htab->opd_abi
&& htab->params->plt_localentry0 != 0
&& is_elfv2_localentry0 (&h->elf))
{
/* The function doesn't use or change r2. */
can_plt_call = TRUE;
}
/* All of these stubs may modify r2, so there must be a /* All of these stubs may modify r2, so there must be a
branch and link followed by a nop. The nop is branch and link followed by a nop. The nop is
replaced by an insn to restore r2. */ replaced by an insn to restore r2. */
if (rel->r_offset + 8 <= input_section->size) else if (rel->r_offset + 8 <= input_section->size)
{ {
unsigned long br; unsigned long br;
@ -14237,13 +14247,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{ {
/* Special stub used, leave nop alone. */ /* Special stub used, leave nop alone. */
} }
else if (stub_entry->stub_type == ppc_stub_plt_call
&& !htab->opd_abi
&& htab->params->plt_localentry0 != 0
&& is_elfv2_localentry0 (&h->elf))
{
/* The function doesn't use or change r2. */
}
else else
bfd_put_32 (input_bfd, bfd_put_32 (input_bfd,
LD_R2_0R1 + STK_TOC (htab), LD_R2_0R1 + STK_TOC (htab),