+2017-08-23  Alan Modra  <amodra@gmail.com>
+
+       PR 21988
+       * elf64-ppc.c (ensure_undef_dynamic): Rename from
+       ensure_undefweak_dynamic.  Handle undefined too.
+       * elf32-ppc.c (ensure_undef_dynamic): Likewise.
+       * elf32-hppa.c (ensure_undef_dynamic): Likewise.
+       (allocate_dynrelocs): Discard undefined non-default visibility
+       relocs first.  Make undefined syms dynamic.  Tidy goto.
+
 2017-08-21  Alan Modra  <amodra@gmail.com>
            H.J. Lu  <hongjiu.lu@intel.com>
 
 
   return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
 }
 
-/* Make an undefined weak symbol dynamic.  */
+/* If EH is undefined, make it dynamic if that makes sense.  */
 
 static bfd_boolean
-ensure_undef_weak_dynamic (struct bfd_link_info *info,
-                          struct elf_link_hash_entry *eh)
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *eh)
 {
-  if (eh->dynindx == -1
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+
+  if (htab->dynamic_sections_created
+      && (eh->root.type == bfd_link_hash_undefweak
+         || eh->root.type == bfd_link_hash_undefined)
+      && eh->dynindx == -1
       && !eh->forced_local
       && eh->type != STT_PARISC_MILLI
-      && eh->root.type == bfd_link_hash_undefweak
       && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT)
     return bfd_elf_link_record_dynamic_symbol (info, eh);
   return TRUE;
   if (htab->etab.dynamic_sections_created
       && eh->plt.refcount > 0)
     {
-      if (!ensure_undef_weak_dynamic (info, eh))
+      if (!ensure_undef_dynamic (info, eh))
        return FALSE;
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), eh))
 
   if (eh->got.refcount > 0)
     {
-      if (!ensure_undef_weak_dynamic (info, eh))
+      if (!ensure_undef_dynamic (info, eh))
        return FALSE;
 
       sec = htab->etab.sgot;
      changes.  */
   if (bfd_link_pic (info))
     {
+      /* Discard relocs on undefined syms with non-default visibility.  */
+      if ((eh->root.type == bfd_link_hash_undefined
+          || eh->root.type == bfd_link_hash_undefweak)
+         && ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
+       hh->dyn_relocs = NULL;
+
 #if RELATIVE_DYNRELOCS
-      if (SYMBOL_CALLS_LOCAL (info, eh))
+      else if (SYMBOL_CALLS_LOCAL (info, eh))
        {
          struct elf32_hppa_dyn_reloc_entry **hdh_pp;
 
        }
 #endif
 
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
-      if (hh->dyn_relocs != NULL
-         && eh->root.type == bfd_link_hash_undefweak)
+      if (hh->dyn_relocs != NULL)
        {
-         if (ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
-           hh->dyn_relocs = NULL;
-
-         else if (!ensure_undef_weak_dynamic (info, eh))
+         if (!ensure_undef_dynamic (info, eh))
            return FALSE;
        }
     }
                   && (eh->root.type == bfd_link_hash_undefweak
                       || eh->root.type == bfd_link_hash_undefined))))
        {
-         if (!ensure_undef_weak_dynamic (info, eh))
+         if (!ensure_undef_dynamic (info, eh))
            return FALSE;
 
-         /* If that succeeded, we know we'll be keeping all the
-            relocs.  */
-         if (eh->dynindx != -1)
-           goto keep;
+         if (eh->dynindx == -1)
+           hh->dyn_relocs = NULL;
        }
-
-      hh->dyn_relocs = NULL;
-      return TRUE;
-
-    keep: ;
+      else
+       hh->dyn_relocs = NULL;
     }
 
   /* Finally, allocate space.  */
 
   return where;
 }
 
-/* If H is undefined weak, make it dynamic if that makes sense.  */
+/* If H is undefined, make it dynamic if that makes sense.  */
 
 static bfd_boolean
-ensure_undefweak_dynamic (struct bfd_link_info *info,
-                         struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *h)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   if (htab->dynamic_sections_created
-      && info->dynamic_undefined_weak != 0
-      && h->root.type == bfd_link_hash_undefweak
+      && ((info->dynamic_undefined_weak != 0
+          && h->root.type == bfd_link_hash_undefweak)
+         || h->root.type == bfd_link_hash_undefined)
       && h->dynindx == -1
       && !h->forced_local
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
     {
       unsigned int need;
 
-      /* Make sure this symbol is output as a dynamic symbol.
-        Undefined weak syms won't yet be marked as dynamic.  */
-      if (!ensure_undefweak_dynamic (info, &eh->elf))
+      /* Make sure this symbol is output as a dynamic symbol.  */
+      if (!ensure_undef_dynamic (info, &eh->elf))
        return FALSE;
 
       need = 0;
 
       if (eh->dyn_relocs != NULL)
        {
-         /* Make sure undefined weak symbols are output as a dynamic
-            symbol in PIEs.  */
-         if (!ensure_undefweak_dynamic (info, h))
+         /* Make sure this symbol is output as a dynamic symbol.  */
+         if (!ensure_undef_dynamic (info, h))
            return FALSE;
        }
     }
               && eh->has_addr16_lo
               && htab->params->pic_fixup > 0))
        {
-         /* Make sure this symbol is output as a dynamic symbol.
-            Undefined weak syms won't yet be marked as dynamic.  */
-         if (!ensure_undefweak_dynamic (info, h))
+         /* Make sure this symbol is output as a dynamic symbol.  */
+         if (!ensure_undef_dynamic (info, h))
            return FALSE;
 
          if (h->dynindx == -1)
 
          }
 }
 
-/* If H is undefined weak, make it dynamic if that makes sense.  */
+/* If H is undefined, make it dynamic if that makes sense.  */
 
 static bfd_boolean
-ensure_undefweak_dynamic (struct bfd_link_info *info,
-                         struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *h)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   if (htab->dynamic_sections_created
-      && info->dynamic_undefined_weak != 0
-      && h->root.type == bfd_link_hash_undefweak
+      && ((info->dynamic_undefined_weak != 0
+          && h->root.type == bfd_link_hash_undefweak)
+         || h->root.type == bfd_link_hash_undefined)
       && h->dynindx == -1
       && !h->forced_local
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
   for (gent = h->got.glist; gent != NULL; gent = gent->next)
     if (!gent->is_indirect)
       {
-       /* Make sure this symbol is output as a dynamic symbol.
-          Undefined weak syms won't yet be marked as dynamic.  */
-       if (!ensure_undefweak_dynamic (info, h))
+       /* Make sure this symbol is output as a dynamic symbol.  */
+       if (!ensure_undef_dynamic (info, h))
          return FALSE;
 
        if (!is_ppc64_elf (gent->owner))
 
          if (eh->dyn_relocs != NULL)
            {
-             /* Make sure this symbol is output as a dynamic symbol.
-                Undefined weak syms won't yet be marked as dynamic.  */
-             if (!ensure_undefweak_dynamic (info, h))
+             /* Make sure this symbol is output as a dynamic symbol.  */
+             if (!ensure_undef_dynamic (info, h))
                return FALSE;
            }
        }
          if (!h->non_got_ref
              && !h->def_regular)
            {
-             /* Make sure this symbol is output as a dynamic symbol.
-                Undefined weak syms won't yet be marked as dynamic.  */
-             if (!ensure_undefweak_dynamic (info, h))
+             /* Make sure this symbol is output as a dynamic symbol.  */
+             if (!ensure_undef_dynamic (info, h))
                return FALSE;
 
              if (h->dynindx == -1)