PR24355, segmentation fault in function called from ppc_finish_symbols
authorAlan Modra <amodra@gmail.com>
Mon, 18 Mar 2019 11:08:36 +0000 (21:38 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 18 Mar 2019 12:08:29 +0000 (22:38 +1030)
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.

bfd/ChangeLog
bfd/elf32-ppc.c

index f92b273ecd6d89c50e3a4bcdba4f465de3fa2fcd..9cdd4fe176728c448d1ec9a3dcc20424531af544 100644 (file)
@@ -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-03-16  Alan Modra  <amodra@gmail.com>
 
        PR 24337
index 593ef475926be71f0e277390be1d9809cfc30ddf..6991e8ddc1e544d0d9aea6f4abe48b11a8ea3128 100644 (file)
@@ -9704,6 +9704,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))
@@ -9748,14 +9749,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;
              }
          }
 
This page took 0.028963 seconds and 4 git commands to generate.