summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-03-18 21:38:36 +1030
committerAlan Modra <amodra@gmail.com>2019-03-18 22:53:07 +1030
commitdba17838ab20a814e6c8ba51afe6962d1c400227 (patch)
tree23634311f2966e9586a99dfe3727529b45e8ee00
parent88739f776b733b0b84600b283417f862a010bb5d (diff)
downloadbinutils-gdb-dba17838ab20a814e6c8ba51afe6962d1c400227.tar.gz
PR24355, segmentation fault in function called from ppc_finish_symbols
This one looks to be a bug going back to 2009, git commit e054468f6c "STT_GNU_IFUNC support for PowerPC". That bug was carried over with git commit 49c09209d0 "Rearrange PLT reloc output on powerpc". If the refcount for an ifunc local sym plt entry was zero, ppc_elf_size_dynamic_sections would correctly set plt.offset to -1 but leave glink_offset uninitialized. That leads to occasional segfaults (which can be made solid with MALLOC_PERTURB_=1 when using glibc). So, guard the write_glink_stub call with plt.offset != -1. Also, remove the totally ineffective attempt at writing multiple-use glink stubs only once. PR 24355 * elf32-ppc.c (ppc_finish_symbols): Don't call write_glink_stub for local iplt syms with ent->plt.offset == -1. Remove ineffective attempt at writing glink stubs only once. (cherry picked from commit 8cd1fe1bf525b59f4d07e5790d11d49eee7e8494)
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-ppc.c8
2 files changed, 9 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4582b8c5086..eb32e2dd679 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2019-03-18 Alan Modra <amodra@gmail.com>
+
+ PR 24355
+ * elf32-ppc.c (ppc_finish_symbols): Don't call write_glink_stub
+ for local iplt syms with ent->plt.offset == -1. Remove ineffective
+ attempt at writing glink stubs only once.
+
2019-02-18 Nick Clifton <nickc@redhat.com>
Import from the mainline:
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 5e9251bdb9f..f4a329a1327 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -10828,6 +10828,7 @@ ppc_finish_symbols (struct bfd_link_info *info)
bfd_byte *loc;
bfd_vma val;
Elf_Internal_Rela rela;
+ unsigned char *p;
if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
lplt - local_plt, ibfd))
@@ -10872,14 +10873,9 @@ ppc_finish_symbols (struct bfd_link_info *info)
loc = relplt->contents + (relplt->reloc_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
- }
- if ((ent->glink_offset & 1) == 0)
- {
- unsigned char *p = ((unsigned char *) htab->glink->contents
- + ent->glink_offset);
+ p = (unsigned char *) htab->glink->contents + ent->glink_offset;
write_glink_stub (NULL, ent, htab->elf.iplt, p, info);
- ent->glink_offset |= 1;
}
}