summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-06-21 15:03:25 +0930
committerAlan Modra <amodra@gmail.com>2017-06-21 22:45:15 +0930
commit6e1816be66892d06e1a983f08407135fa7f7fc17 (patch)
tree0a2d291a1e35252d38fee88b05a438d43b07311b
parent81209eff905bf76a01bbc3dc07b8973d1d0cdaad (diff)
downloadbinutils-gdb-6e1816be66892d06e1a983f08407135fa7f7fc17.tar.gz
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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf64-ppc.c33
2 files changed, 25 insertions, 15 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1d9ba02a577..7b2927fb3ea 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
PR binutils/21645
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 42abb96d961..319d58f86a0 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -12634,18 +12634,19 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
if (stub_type == ppc_stub_plt_call)
{
- if (irela + 1 < irelaend
- && irela[1].r_offset == irela->r_offset + 4
- && ELF64_R_TYPE (irela[1].r_info) == R_PPC64_TOCSAVE)
+ if (!htab->opd_abi
+ && htab->params->plt_localentry0 != 0
+ && 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,
&local_syms, irela + 1, input_bfd))
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
stub_type = ppc_stub_plt_call_r2save;
}
@@ -14212,10 +14213,19 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{
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
branch and link followed by a nop. The nop is
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;
@@ -14237,13 +14247,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{
/* 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
bfd_put_32 (input_bfd,
LD_R2_0R1 + STK_TOC (htab),