aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-08-05 19:44:03 +0930
committerAlan Modra <amodra@gmail.com>2018-08-07 18:43:54 +0930
commite81b4c933c1b88e29f4b27627dd9ea0bf9189944 (patch)
treec89195d2bf33cb1a0faf7c5e2afcea1f10d9248d /bfd
parent99f8774ccaca5b1bfa4a035c6c705bc7ef47e75f (diff)
downloadgdb-e81b4c933c1b88e29f4b27627dd9ea0bf9189944.zip
gdb-e81b4c933c1b88e29f4b27627dd9ea0bf9189944.tar.gz
gdb-e81b4c933c1b88e29f4b27627dd9ea0bf9189944.tar.bz2
__tls_get_addr_opt stubs and tocsave optimization
This patch fixes a bug in the handling of the __tls_get_addr_opt stub. Calls via this stub don't have a toc restoring instruction following the "bl", and the stub itself doesn't have an initial toc save instruction. Thus it is incorrect to skip over the first instruction when a __tls_get_addr call is marked with a tocsave reloc. * elf64-ppc.c (ppc64_elf_relocate_section): Don't skip first instruction of __tls_get_addr_opt stub. (plt_stub_size): Omit ALWAYS_EMIT_R2SAVE condition when dealing with __tls_get_addr_opt stub. (build_tls_get_addr_stub, ppc_size_one_stub): Likewise.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf64-ppc.c13
2 files changed, 15 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b12e024..b8fd5be 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2018-08-07 Alan Modra <amodra@gmail.com>
+
+ * elf64-ppc.c (ppc64_elf_relocate_section): Don't skip first
+ instruction of __tls_get_addr_opt stub.
+ (plt_stub_size): Omit ALWAYS_EMIT_R2SAVE condition when
+ dealing with __tls_get_addr_opt stub.
+ (build_tls_get_addr_stub, ppc_size_one_stub): Likewise.
+
2018-08-06 Claudiu Zissulescu <claziss@synopsys.com>
* elf32-arc.c (arc_elf_merge_private_bfd_data): Complain about
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 008d352..5e20bbd 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11027,8 +11027,7 @@ plt_stub_size (struct ppc_link_hash_table *htab,
&& htab->params->tls_get_addr_opt)
{
size += 7 * 4;
- if (ALWAYS_EMIT_R2SAVE
- || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+ if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
size += 6 * 4;
}
return size;
@@ -11273,8 +11272,7 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
bfd_put_32 (obfd, MR_R3_R0, p), p += 4;
if (r != NULL)
r[0].r_offset += 7 * 4;
- if (!ALWAYS_EMIT_R2SAVE
- && stub_entry->stub_type != ppc_stub_plt_call_r2save)
+ if (stub_entry->stub_type != ppc_stub_plt_call_r2save)
return build_plt_stub (htab, stub_entry, p, offset, r);
bfd_put_32 (obfd, MFLR_R11, p), p += 4;
@@ -11928,8 +11926,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
&& (stub_entry->h == htab->tls_get_addr_fd
|| stub_entry->h == htab->tls_get_addr)
&& htab->params->tls_get_addr_opt
- && (ALWAYS_EMIT_R2SAVE
- || stub_entry->stub_type == ppc_stub_plt_call_r2save))
+ && stub_entry->stub_type == ppc_stub_plt_call_r2save)
stub_entry->group->tls_get_addr_opt_bctrl
= stub_entry->stub_offset + size - 5 * 4;
@@ -15336,6 +15333,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
&& ALWAYS_EMIT_R2SAVE)
|| stub_entry->stub_type == ppc_stub_plt_call_r2save
|| stub_entry->stub_type == ppc_stub_plt_call_both)
+ && !(h != NULL
+ && (h == htab->tls_get_addr_fd
+ || h == htab->tls_get_addr)
+ && htab->params->tls_get_addr_opt)
&& rel + 1 < relend
&& rel[1].r_offset == rel->r_offset + 4
&& ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)