aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h30
2 files changed, 32 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e159ac507..38ac2ac26c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-26 Alan Modra <amodra@gmail.com>
+
+ * sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_fixup_plt):
+ Don't segfault if ifunc resolver returns a NULL. Do set plt to
+ zero for undefined weak.
+ (elf_machine_plt_conflict): Similarly.
+
2015-03-25 Joseph Myers <joseph@codesourcery.com>
* math/auto-libm-test-in: Add more tests of acosh, asinh and
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 55ac73624b..0576781909 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -472,19 +472,32 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
Elf64_Addr offset = 0;
+ Elf64_FuncDesc zero_fd = {0, 0, 0};
PPC_DCBT (&plt->fd_aux);
PPC_DCBT (&plt->fd_func);
- PPC_DCBT (&rel->fd_aux);
- PPC_DCBT (&rel->fd_func);
- /* If sym_map is NULL, it's a weak undefined sym; Leave the plt zero. */
+ /* If sym_map is NULL, it's a weak undefined sym; Set the plt to
+ zero. finaladdr should be zero already in this case, but guard
+ against invalid plt relocations with non-zero addends. */
if (sym_map == NULL)
- return 0;
+ finaladdr = 0;
+
+ /* Don't die here if finaladdr is zero, die if this plt entry is
+ actually called. Makes a difference when LD_BIND_NOW=1.
+ finaladdr may be zero for a weak undefined symbol, or when an
+ ifunc resolver returns zero. */
+ if (finaladdr == 0)
+ rel = &zero_fd;
+ else
+ {
+ PPC_DCBT (&rel->fd_aux);
+ PPC_DCBT (&rel->fd_func);
+ }
/* If the opd entry is not yet relocated (because it's from a shared
object that hasn't been processed yet), then manually reloc it. */
- if (map != sym_map && !sym_map->l_relocated
+ if (finaladdr != 0 && map != sym_map && !sym_map->l_relocated
#if !defined RTLD_BOOTSTRAP && defined SHARED
/* Bootstrap map doesn't have l_relocated set for it. */
&& sym_map != &GL(dl_rtld_map)
@@ -522,6 +535,13 @@ elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
#if _CALL_ELF != 2
Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
+ Elf64_FuncDesc zero_fd = {0, 0, 0};
+
+ if (sym_map == NULL)
+ finaladdr = 0;
+
+ if (finaladdr == 0)
+ rel = &zero_fd;
plt->fd_func = rel->fd_func;
plt->fd_aux = rel->fd_aux;