PR17488, powerpc64-linux-ld segfault
authorAlan Modra <amodra@gmail.com>
Wed, 15 Oct 2014 23:08:09 +0000 (09:38 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 28 Oct 2014 06:12:56 +0000 (16:42 +1030)
For binary ouput, we don't have an ELF bfd output so can't access
elf_elfheader.  The elf64-ppc.c changes are really just a tidy,
triggered by looking at all places where the abiversion bits are
accessed.

bfd/
* elf64-ppc.c (ppc64_elf_before_check_relocs): Do .opd processing
even when output is not ppc64 ELF.  Remove redundant tests on
type of input bfd.
ld/
PR 17488
* emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't attempt
to access ELF header e_flags when not ppc64 ELF output.

bfd/ChangeLog
bfd/elf64-ppc.c
ld/ChangeLog
ld/emultempl/ppc64elf.em

index aa6ea5b..9727555 100644 (file)
@@ -1,6 +1,11 @@
 2014-10-28  Alan Modra  <amodra@gmail.com>
 
        Apply trunk patches
+       2014-10-16  Alan Modra  <amodra@gmail.com>
+       * elf64-ppc.c (ppc64_elf_before_check_relocs): Do .opd processing
+       even when output is not ppc64 ELF.  Remove redundant tests on
+       type of input bfd.
+
        2014-10-15  Alan Modra  <amodra@gmail.com>
        PR 17481
        * aoutx.h (NAME (aout, find_nearest_line)): Add "discriminator_ptr"
index 123a33a..974f992 100644 (file)
@@ -4962,81 +4962,77 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
   struct ppc_link_hash_entry **p, *eh;
+  asection *opd = bfd_get_section_by_name (ibfd, ".opd");
 
-  if (!is_ppc64_elf (info->output_bfd))
-    return TRUE;
-  htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  if (is_ppc64_elf (ibfd))
+  if (opd != NULL && opd->size != 0)
     {
-      asection *opd = bfd_get_section_by_name (ibfd, ".opd");
-
-      if (opd != NULL && opd->size != 0)
+      if (abiversion (ibfd) == 0)
+       set_abiversion (ibfd, 1);
+      else if (abiversion (ibfd) == 2)
        {
-         if (abiversion (ibfd) == 0)
-           set_abiversion (ibfd, 1);
-         else if (abiversion (ibfd) == 2)
-           {
-             info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
-                                       " version %d\n"),
-                                     ibfd, abiversion (ibfd));
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-
-         if ((ibfd->flags & DYNAMIC) == 0
-             && (opd->flags & SEC_RELOC) != 0
-             && opd->reloc_count != 0
-             && !bfd_is_abs_section (opd->output_section))
-           {
-             /* Garbage collection needs some extra help with .opd sections.
-                We don't want to necessarily keep everything referenced by
-                relocs in .opd, as that would keep all functions.  Instead,
-                if we reference an .opd symbol (a function descriptor), we
-                want to keep the function code symbol's section.  This is
-                easy for global symbols, but for local syms we need to keep
-                information about the associated function section.  */
-             bfd_size_type amt;
-             asection **opd_sym_map;
-
-             amt = opd->size * sizeof (*opd_sym_map) / 8;
-             opd_sym_map = bfd_zalloc (ibfd, amt);
-             if (opd_sym_map == NULL)
-               return FALSE;
-             ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
-             BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
-             ppc64_elf_section_data (opd)->sec_type = sec_opd;
-           }
+         info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
+                                   " version %d\n"),
+                                 ibfd, abiversion (ibfd));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
        }
 
-      /* For input files without an explicit abiversion in e_flags
-        we should have flagged any with symbol st_other bits set
-        as ELFv1 and above flagged those with .opd as ELFv2.
-        Set the output abiversion if not yet set, and for any input
-        still ambiguous, take its abiversion from the output.
-        Differences in ABI are reported later.  */
-      if (abiversion (info->output_bfd) == 0)
-       set_abiversion (info->output_bfd, abiversion (ibfd));
-      else if (abiversion (ibfd) == 0)
-       set_abiversion (ibfd, abiversion (info->output_bfd));
-
-      p = &htab->dot_syms;
-      while ((eh = *p) != NULL)
+      if ((ibfd->flags & DYNAMIC) == 0
+         && (opd->flags & SEC_RELOC) != 0
+         && opd->reloc_count != 0
+         && !bfd_is_abs_section (opd->output_section))
        {
-         *p = NULL;
-         if (&eh->elf == htab->elf.hgot)
-           ;
-         else if (htab->elf.hgot == NULL
-                  && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
-           htab->elf.hgot = &eh->elf;
-         else if (!add_symbol_adjust (eh, info))
+         /* Garbage collection needs some extra help with .opd sections.
+            We don't want to necessarily keep everything referenced by
+            relocs in .opd, as that would keep all functions.  Instead,
+            if we reference an .opd symbol (a function descriptor), we
+            want to keep the function code symbol's section.  This is
+            easy for global symbols, but for local syms we need to keep
+            information about the associated function section.  */
+         bfd_size_type amt;
+         asection **opd_sym_map;
+
+         amt = opd->size * sizeof (*opd_sym_map) / 8;
+         opd_sym_map = bfd_zalloc (ibfd, amt);
+         if (opd_sym_map == NULL)
            return FALSE;
-         p = &eh->u.next_dot_sym;
+         ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
+         BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
+         ppc64_elf_section_data (opd)->sec_type = sec_opd;
        }
     }
 
+  if (!is_ppc64_elf (info->output_bfd))
+    return TRUE;
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
+  /* For input files without an explicit abiversion in e_flags
+     we should have flagged any with symbol st_other bits set
+     as ELFv1 and above flagged those with .opd as ELFv2.
+     Set the output abiversion if not yet set, and for any input
+     still ambiguous, take its abiversion from the output.
+     Differences in ABI are reported later.  */
+  if (abiversion (info->output_bfd) == 0)
+    set_abiversion (info->output_bfd, abiversion (ibfd));
+  else if (abiversion (ibfd) == 0)
+    set_abiversion (ibfd, abiversion (info->output_bfd));
+
+  p = &htab->dot_syms;
+  while ((eh = *p) != NULL)
+    {
+      *p = NULL;
+      if (&eh->elf == htab->elf.hgot)
+       ;
+      else if (htab->elf.hgot == NULL
+              && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
+       htab->elf.hgot = &eh->elf;
+      else if (!add_symbol_adjust (eh, info))
+       return FALSE;
+      p = &eh->u.next_dot_sym;
+    }
+
   /* Clear the list for non-ppc64 input files.  */
   p = &htab->dot_syms;
   while ((eh = *p) != NULL)
index 27da9d4..a1ec84f 100644 (file)
@@ -1,3 +1,11 @@
+2014-10-28  Alan Modra  <amodra@gmail.com>
+
+       Apply trunk patches
+       2014-10-16  Alan Modra  <amodra@gmail.com>
+       PR 17488
+       * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't attempt
+       to access ELF header e_flags when not ppc64 ELF output.
+
 2014-10-24  Tejas Belagod  <tejas.belagod@arm.com>
 
        * emultempl/aarch64elf.em: Add command-line option for erratum
index 914fc52..59ea786 100644 (file)
@@ -531,7 +531,8 @@ gld${EMULATION_NAME}_finish (void)
   /* e_entry on PowerPC64 points to the function descriptor for
      _start.  If _start is missing, default to the first function
      descriptor in the .opd section.  */
-  if ((elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1)
+  if (stub_file != NULL
+      && (elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1)
     entry_section = ".opd";
 
   if (params.emit_stub_syms < 0)