Implement -z dynamic-undefined-weak
authorAlan Modra <amodra@gmail.com>
Tue, 18 Apr 2017 15:56:57 +0000 (01:26 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 19 Apr 2017 11:09:52 +0000 (20:39 +0930)
-z nodynamic-undefined-weak is only implemented for x86.  (The sparc
backend has some support code but doesn't enable the option by
including ld/emulparams/dynamic_undefined_weak.sh, and since the
support looks like it may be broken I haven't enabled it.)  This patch
adds the complementary -z dynamic-undefined-weak, extends both options
to affect building of shared libraries as well as executables, and
adds support for the option on powerpc.

include/
* bfdlink.h (struct bfd_link_info <dynamic_undefined_weak>):
Revise comment.
bfd/
* elflink.c (_bfd_elf_adjust_dynamic_symbol): Hide undefweak
or make dynamic for info->dynamic_undefined_weak 0 and 1.
* elf32-ppc.c:Formatting.
(ensure_undefweak_dynamic): Don't make dynamic when
info->dynamic_undefined_weak is zero.
(allocate_dynrelocs): Discard undefweak dyn_relocs for
info->dynamic_undefined_weak.  Discard undef dyn_relocs when
not default visibility.  Discard undef and undefweak
dyn_relocs earlier.
(ppc_elf_relocate_section): Adjust to suit.
* elf64-ppc.c: Formatting.
(ensure_undefweak_dynamic): Don't make dynamic when
info->dynamic_undefined_weak is zero.
(allocate_dynrelocs): Discard undefweak dyn_relocs for
info->dynamic_undefined_weak.  Discard them earlier.
ld/
* ld.texinfo (dynamic-undefined-weak): Document.
(nodynamic-undefined-weak): Document that this option now can
be used with shared libs.
* emulparams/dynamic_undefined_weak.sh: Support -z
dynamic-undefined-weak.
* emulparams/elf32ppccommon.sh: Include dynamic_undefined_weak.sh.
* testsuite/ld-undefined/weak-undef.exp (undef_weak_so),
(undef_weak_exe): New.  Use them.  Add -z dynamic-undefined-weak
and -z nodynamic-undefined-weak tests.
* Makefile.am: Update powerpc dependencies.
* Makefile.in: Regenerate.

13 files changed:
bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c
bfd/elflink.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/emulparams/dynamic_undefined_weak.sh
ld/emulparams/elf32ppccommon.sh
ld/ld.texinfo
ld/testsuite/ld-undefined/weak-undef.exp

index f1ca8b4755e41fe6c5162c5bf4b1fa5f861ac7e1..b66ade684340f9dc186dfd37220184ce13c9f13c 100644 (file)
@@ -1,3 +1,21 @@
+2017-04-19  Alan Modra  <amodra@gmail.com>
+
+       * elflink.c (_bfd_elf_adjust_dynamic_symbol): Hide undefweak
+       or make dynamic for info->dynamic_undefined_weak 0 and 1.
+       * elf32-ppc.c:Formatting.
+       (ensure_undefweak_dynamic): Don't make dynamic when
+       info->dynamic_undefined_weak is zero.
+       (allocate_dynrelocs): Discard undefweak dyn_relocs for
+       info->dynamic_undefined_weak.  Discard undef dyn_relocs when
+       not default visibility.  Discard undef and undefweak
+       dyn_relocs earlier.
+       (ppc_elf_relocate_section): Adjust to suit.
+       * elf64-ppc.c: Formatting.
+       (ensure_undefweak_dynamic): Don't make dynamic when
+       info->dynamic_undefined_weak is zero.
+       (allocate_dynrelocs): Discard undefweak dyn_relocs for
+       info->dynamic_undefined_weak.  Discard them earlier.
+
 2017-04-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/21389
index 4bd58e2696efaf6a6ccc9fa4e3af5a93be778761..6a24a460391d3379b8148d27a9f9dd2026ce7243 100644 (file)
@@ -2609,7 +2609,7 @@ ppc_elf_modify_segment_map (bfd *abfd,
       amt += (m->count - j - 1) * sizeof (asection *);
       n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
       if (n == NULL)
-        return FALSE;
+       return FALSE;
 
       n->p_type = PT_LOAD;
       n->count = m->count - j;
@@ -5947,6 +5947,7 @@ ensure_undefweak_dynamic (struct bfd_link_info *info,
   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
       && h->dynindx == -1
       && !h->forced_local
@@ -6036,6 +6037,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   else
     eh->elf.got.offset = (bfd_vma) -1;
 
+  /* If no dynamic sections we can't have dynamic relocs, except for
+     IFUNCs which are handled even in static executables.  */
   if (!htab->elf.dynamic_sections_created
       && h->type != STT_GNU_IFUNC)
     eh->dyn_relocs = NULL;
@@ -6050,13 +6053,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
      changes.  */
   else if (bfd_link_pic (info))
     {
+      /* Discard relocs on undefined symbols that must be local.  */
+      if (h->root.type == bfd_link_hash_undefined
+         && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+       eh->dyn_relocs = NULL;
+
+      /* Also discard relocs on undefined weak syms with non-default
+        visibility, or when dynamic_undefined_weak says so.  */
+      else if (h->root.type == bfd_link_hash_undefweak
+              && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+                  || info->dynamic_undefined_weak == 0))
+       eh->dyn_relocs = NULL;
+
       /* Relocs that use pc_count are those that appear on a call insn,
         or certain REL relocs (see must_be_dyn_reloc) that can be
         generated via assembly.  We want calls to protected symbols to
         resolve directly to the function rather than going via the plt.
         If people want function pointer comparisons to work as expected
         then they should avoid writing weird assembly.  */
-      if (SYMBOL_CALLS_LOCAL (info, h))
+      else if (SYMBOL_CALLS_LOCAL (info, h))
        {
          struct elf_dyn_relocs **pp;
 
@@ -6084,24 +6099,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            }
        }
 
-      /* Discard relocs on undefined symbols that must be local.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefined
-         && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
-             || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
-       eh->dyn_relocs = NULL;
-
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefweak)
+      if (eh->dyn_relocs != NULL)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
-
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
-         else if (!ensure_undefweak_dynamic (info, h))
+         if (!ensure_undefweak_dynamic (info, h))
            return FALSE;
        }
     }
@@ -8859,10 +8861,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
          if ((bfd_link_pic (info)
               && !(h != NULL
                    && ((h->root.type == bfd_link_hash_undefined
-                        && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
-                            || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+                        && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
                        || (h->root.type == bfd_link_hash_undefweak
-                           && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))
+                           && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+                               || info->dynamic_undefined_weak == 0))))
               && (must_be_dyn_reloc (info, r_type)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
@@ -10979,7 +10981,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define elf_backend_finish_dynamic_sections    ppc_elf_finish_dynamic_sections
 #define elf_backend_fake_sections              ppc_elf_fake_sections
 #define elf_backend_additional_program_headers ppc_elf_additional_program_headers
-#define elf_backend_modify_segment_map         ppc_elf_modify_segment_map
+#define elf_backend_modify_segment_map         ppc_elf_modify_segment_map
 #define elf_backend_grok_prstatus              ppc_elf_grok_prstatus
 #define elf_backend_grok_psinfo                        ppc_elf_grok_psinfo
 #define elf_backend_write_core_note            ppc_elf_write_core_note
@@ -11049,7 +11051,7 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd)
   if (ret)
     {
       struct ppc_elf_link_hash_table *htab
-        = (struct ppc_elf_link_hash_table *)ret;
+       = (struct ppc_elf_link_hash_table *)ret;
       htab->is_vxworks = 1;
       htab->plt_type = PLT_VXWORKS;
       htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
index e48d67d19b6c5ca9aec2c114b8a111b025ab1755..fc699649f07ca91d28e7e3b7f72929a9898e3be4 100644 (file)
@@ -9695,6 +9695,7 @@ ensure_undefweak_dynamic (struct bfd_link_info *info,
   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
       && h->dynindx == -1
       && !h->forced_local
@@ -9785,10 +9786,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        allocate_got (h, info, gent);
       }
 
+  /* If no dynamic sections we can't have dynamic relocs, except for
+     IFUNCs which are handled even in static executables.  */
   if (!htab->elf.dynamic_sections_created
       && h->type != STT_GNU_IFUNC)
     eh->dyn_relocs = NULL;
 
+  /* Also discard relocs on undefined weak syms with non-default
+     visibility, or when dynamic_undefined_weak says so.  */
+  else if (h->root.type == bfd_link_hash_undefweak
+          && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+              || info->dynamic_undefined_weak == 0))
+    eh->dyn_relocs = NULL;
+
   if (eh->dyn_relocs != NULL)
     {
       struct elf_dyn_relocs *p, **pp;
@@ -9821,17 +9831,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                }
            }
 
-         /* Also discard relocs on undefined weak syms with
-            non-default visibility.  */
-         if (eh->dyn_relocs != NULL
-             && h->root.type == bfd_link_hash_undefweak)
+         if (eh->dyn_relocs != NULL)
            {
-             if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-               eh->dyn_relocs = NULL;
-
              /* Make sure this symbol is output as a dynamic symbol.
                 Undefined weak syms won't yet be marked as dynamic.  */
-             else if (!ensure_undefweak_dynamic (info, h))
+             if (!ensure_undefweak_dynamic (info, h))
                return FALSE;
            }
        }
@@ -14320,7 +14324,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              addend = 0;
              reloc_dest = DEST_STUB;
 
-             if ((stub_entry->stub_type == ppc_stub_plt_call
+             if ((stub_entry->stub_type == ppc_stub_plt_call
                   || stub_entry->stub_type == ppc_stub_plt_call_r2save)
                  && (ALWAYS_EMIT_R2SAVE
                      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
index b93d4f37c175b0264f838d732d153ce63104943f..0add01b5ad9fb094985fd88c5338a3a5260fa652 100644 (file)
@@ -2803,6 +2803,24 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (! _bfd_elf_fix_symbol_flags (h, eif))
     return FALSE;
 
+  if (h->root.type == bfd_link_hash_undefweak)
+    {
+      if (eif->info->dynamic_undefined_weak == 0)
+       _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+      else if (eif->info->dynamic_undefined_weak > 0
+              && h->ref_regular
+              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              && !bfd_hide_sym_by_version (eif->info->version_info,
+                                           h->root.root.string))
+       {
+         if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
+           {
+             eif->failed = TRUE;
+             return FALSE;
+           }
+       }
+    }
+
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
      object, ignore it.  We do have to handle a weak defined symbol,
index b0e30ab7b5e5afb1aeaaca2f1a2a6463e9b56305..90c4c8d3044bc02545889d7e5388398164c2810b 100644 (file)
@@ -1,3 +1,8 @@
+2017-04-19  Alan Modra  <amodra@gmail.com>
+
+       * bfdlink.h (struct bfd_link_info <dynamic_undefined_weak>):
+       Revise comment.
+
 2017-04-11  Alan Modra  <amodra@gmail.com>
 
        * opcode/ppc.h (PPC_OPCODE_ALTIVEC2): Delete.
index 3835fcb0d3094d6f108424cf42b2596aca86d40f..18dea0c7318a278de4209c270df43cbc05e2d292 100644 (file)
@@ -584,8 +584,9 @@ struct bfd_link_info
      backend to decide.  */
   int extern_protected_data;
 
-  /* > 0 to treat undefined weak symbol in the executable as dynamic,
-     requiring dynamic relocation.  */
+  /* 1 to make undefined weak symbols dynamic when building a dynamic
+     object.  0 to resolve undefined weak symbols to zero.  -1 to let
+     the backend decide.  */
   int dynamic_undefined_weak;
 
   /* Non-zero if auto-import thunks for DATA items in pei386 DLLs
index a5732a555ae1e2cbdc6c3d253037954a028cc6a5..c20ed75f0cab8f7511a6877e3138bb4f68044a5b 100644 (file)
@@ -1,3 +1,17 @@
+2017-04-19  Alan Modra  <amodra@gmail.com>
+
+       * ld.texinfo (dynamic-undefined-weak): Document.
+       (nodynamic-undefined-weak): Document that this option now can
+       be used with shared libs.
+       * emulparams/dynamic_undefined_weak.sh: Support -z
+       dynamic-undefined-weak.
+       * emulparams/elf32ppccommon.sh: Include dynamic_undefined_weak.sh.
+       * testsuite/ld-undefined/weak-undef.exp (undef_weak_so),
+       (undef_weak_exe): New.  Use them.  Add -z dynamic-undefined-weak
+       and -z nodynamic-undefined-weak tests.
+       * Makefile.am: Update powerpc dependencies.
+       * Makefile.in: Regenerate.
+
 2017-04-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/21389
index 9dd31ffefe4aa6c109c08a8aaf86a7d0d496ae9b..3aa7e80467f11c1fc6c43c040f6a256c6ec56929 100644 (file)
@@ -1157,23 +1157,27 @@ eelf32lmip.c: $(srcdir)/emulparams/elf32lmip.sh \
 eelf32lppc.c: $(srcdir)/emulparams/elf32lppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emulparams/elf32ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppclinux.c: $(srcdir)/emulparams/elf32lppclinux.sh \
   $(srcdir)/emulparams/elf32lppc.sh $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppcnto.c: $(srcdir)/emulparams/elf32lppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppcsim.c: $(srcdir)/emulparams/elf32lppcsim.sh \
   $(srcdir)/emulparams/elf32lppc.sh $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
@@ -1253,31 +1257,37 @@ eelf32or1k_linux.c: $(srcdir)/emulparams/elf32or1k_linux.sh \
 
 eelf32ppc.c: $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppc_fbsd.c: $(srcdir)/emulparams/elf32ppc_fbsd.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppclinux.c: $(srcdir)/emulparams/elf32ppclinux.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcnto.c: $(srcdir)/emulparams/elf32ppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcsim.c: $(srcdir)/emulparams/elf32ppcsim.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcvxworks.c: $(srcdir)/emulparams/elf32ppcvxworks.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh $(srcdir)/emulparams/vxworks.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(srcdir)/emultempl/vxworks.em \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
@@ -1976,8 +1986,9 @@ eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS}
 
 eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \
-  $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
-  ldemul-list.h \
+  $(srcdir)/emulparams/elf64ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
+  $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf64lriscv.c: $(srcdir)/emulparams/elf64lriscv.sh \
@@ -2000,11 +2011,13 @@ eelf64mmix.c: $(srcdir)/emulparams/elf64mmix.sh \
   $(ELF_DEPS) $(srcdir)/emultempl/mmix-elfnmmo.em \
   $(srcdir)/emultempl/mmixelf.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
-eelf64ppc.c: $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
-  ldemul-list.h \
+eelf64ppc.c: $(srcdir)/emulparams/elf64ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
+  $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf64ppc_fbsd.c: $(srcdir)/emulparams/elf64ppc_fbsd.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
index c4643021da7f37df55ef9549f70f1197cd428965..f485f4f8f5c99d62c0941ff69d075fc7c0f64945 100644 (file)
@@ -2721,23 +2721,27 @@ eelf32lmip.c: $(srcdir)/emulparams/elf32lmip.sh \
 eelf32lppc.c: $(srcdir)/emulparams/elf32lppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emulparams/elf32ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppclinux.c: $(srcdir)/emulparams/elf32lppclinux.sh \
   $(srcdir)/emulparams/elf32lppc.sh $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppcnto.c: $(srcdir)/emulparams/elf32lppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32lppcsim.c: $(srcdir)/emulparams/elf32lppcsim.sh \
   $(srcdir)/emulparams/elf32lppc.sh $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
@@ -2817,31 +2821,37 @@ eelf32or1k_linux.c: $(srcdir)/emulparams/elf32or1k_linux.sh \
 
 eelf32ppc.c: $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppc_fbsd.c: $(srcdir)/emulparams/elf32ppc_fbsd.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppclinux.c: $(srcdir)/emulparams/elf32ppclinux.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcnto.c: $(srcdir)/emulparams/elf32ppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcsim.c: $(srcdir)/emulparams/elf32ppcsim.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf32ppcvxworks.c: $(srcdir)/emulparams/elf32ppcvxworks.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh $(srcdir)/emulparams/vxworks.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc32elf.em ldemul-list.h \
   $(srcdir)/emultempl/vxworks.em \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
@@ -3540,8 +3550,9 @@ eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS}
 
 eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \
-  $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
-  ldemul-list.h \
+  $(srcdir)/emulparams/elf64ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
+  $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf64lriscv.c: $(srcdir)/emulparams/elf64lriscv.sh \
@@ -3564,11 +3575,13 @@ eelf64mmix.c: $(srcdir)/emulparams/elf64mmix.sh \
   $(ELF_DEPS) $(srcdir)/emultempl/mmix-elfnmmo.em \
   $(srcdir)/emultempl/mmixelf.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
-eelf64ppc.c: $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
-  ldemul-list.h \
+eelf64ppc.c: $(srcdir)/emulparams/elf64ppc.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
+  $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
 eelf64ppc_fbsd.c: $(srcdir)/emulparams/elf64ppc_fbsd.sh \
+  $(srcdir)/emulparams/dynamic_undefined_weak.sh \
   $(srcdir)/emultempl/ppc64elf.em ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
index 82d88d6c8de98db4a58a7759fe7fda171b71cc1b..a20bbd409a603130806a808059501b4210a47146 100644 (file)
@@ -1,12 +1,15 @@
-PARSE_AND_LIST_OPTIONS_NODYNAMIC_UNDEFINED_WEAK='
+PARSE_AND_LIST_OPTIONS_DYNAMIC_UNDEFINED_WEAK='
   fprintf (file, _("\
-  -z nodynamic-undefined-weak Do not treat undefined weak symbol as dynamic\n"));
+  -z dynamic-undefined-weak   Make undefined weak symbols dynamic\n\
+  -z nodynamic-undefined-weak Do not make undefined weak symbols dynamic\n"));
 '
 
-PARSE_AND_LIST_ARGS_CASE_Z_NODYNAMIC_UNDEFINED_WEAK='
+PARSE_AND_LIST_ARGS_CASE_Z_DYNAMIC_UNDEFINED_WEAK='
+      else if (strcmp (optarg, "dynamic-undefined-weak") == 0)
+       link_info.dynamic_undefined_weak = TRUE;
       else if (strcmp (optarg, "nodynamic-undefined-weak") == 0)
        link_info.dynamic_undefined_weak = FALSE;
 '
 
-PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_NODYNAMIC_UNDEFINED_WEAK"
-PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_NODYNAMIC_UNDEFINED_WEAK"
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_DYNAMIC_UNDEFINED_WEAK"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_DYNAMIC_UNDEFINED_WEAK"
index d00cf68d894be9cd5d5438dddd91f44014e928d7..44edbd02b57627ba8786d561e1d6cdaae10be393 100644 (file)
@@ -1,5 +1,7 @@
 # The PLT-agnostic parts of a generic 32-bit ELF PowerPC target.  Included by:
 # elf32ppc.sh elf32ppcvxworks.sh elf64ppc.sh
+. ${srcdir}/emulparams/dynamic_undefined_weak.sh
+
 TEMPLATE_NAME=elf32
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
index 909342c7d1cbc27bcc01fa17997d94d224696151..2626b5de206700032fbb99c86afdb24bec2d8585 100644 (file)
@@ -1231,11 +1231,18 @@ generated by compiler.  Updates on protected data symbols by another
 module aren't visible to the resulting shared library.  Supported for
 i386 and x86-64.
 
+@item dynamic-undefined-weak
+Make undefined weak symbols dynamic when building a dynamic object,
+if they are referenced from a regular object file and not forced local
+by symbol visibility or versioning.  Not all targets support this
+option.
+
 @item nodynamic-undefined-weak
-Don't treat undefined weak symbols as dynamic when building executable.
-This option overrides linker backend default.  It can be used to avoid
-dynamic relocations against undefined weak symbols in executable.
-Supported for i386 and x86-64.
+Do not make undefined weak symbols dynamic when building a dynamic
+object.  Not all targets support this option.  If neither
+@option{-z nodynamic-undefined-weak} nor @option{-z dynamic-undefined-weak}
+are given, a target may default to either option being in force, or
+make some other selection of undefined weak symbols dynamic.
 
 @item noreloc-overflow
 Disable relocation overflow check.  This can be used to disable
index eb28c2cb77131b151b2b8403fc55e9464e8342e6..4ae22cf40d3aaa4781794c07615a6866971473b8 100644 (file)
@@ -53,6 +53,52 @@ if { ![is_elf_format] && ![is_pecoff_format] } then {
     }
 }
 
+proc undef_weak_so { testname opts passval } {
+    global ld
+    global nm
+
+    if {![ld_link $ld tmpdir/weak-fundef.so \
+         "$opts tmpdir/weak-fundef.o"]} then {
+       fail $testname
+    } elseif {![is_remote host] && [which $nm] == 0} then {
+       unresolved $testname
+    } else {
+       set exec_output [run_host_cmd "$nm" "-D tmpdir/weak-fundef.so"]
+       set exec_output [prune_warnings $exec_output]
+
+       set output_regexp ".*w undef_weak_fun.*"
+       if {[regexp $output_regexp $exec_output] == $passval} then {
+           pass $testname
+       } else {
+           fail $testname
+       }
+       return 1
+    }
+    return 0
+}
+
+proc undef_weak_exe { testname opts passval } {
+    global ld
+    global nm
+
+    if {![ld_link $ld tmpdir/weak-fundef \
+         "$opts tmpdir/weak-fundef.o tmpdir/weak-fundef.so"]} then {
+       fail $testname
+    } elseif {![is_remote host] && [which $nm] == 0} then {
+       unresolved $testname
+    } else {
+       set exec_output [run_host_cmd "$nm" "-D tmpdir/weak-fundef"]
+       set exec_output [prune_warnings $exec_output]
+
+       set output_regexp ".*w undef_weak_fun.*"
+       if {[regexp $output_regexp $exec_output] == $passval} then {
+           pass $testname
+       } else {
+           fail $testname
+       }
+    }
+}
+
 # When linking a shared lib, weak undefined symbols should become dynamic.
 set testname "weak undefined function symbols in shared lib"
 
@@ -71,39 +117,40 @@ if { $asflags == "" || ![is_elf_format] || ![check_shared_lib_support]} then {
 } elseif {![ld_assemble $as "$asflags $srcdir/$subdir/weak-fundef.s" \
                tmpdir/weak-fundef.o]} then {
     fail $testname
-} elseif {![ld_link $ld tmpdir/weak-fundef.so \
-           "--shared tmpdir/weak-fundef.o"]} then {
-    fail $testname
-} elseif {![is_remote host] && [which $nm] == 0} then {
-    unresolved $testname
-} else {
-    set exec_output [run_host_cmd "$nm" "-D tmpdir/weak-fundef.so"]
-    set exec_output [prune_warnings $exec_output]
-    verbose -log $exec_output
+} elseif { [undef_weak_so $testname "--shared" 1] } then {
 
-    set output_regexp ".*w undef_weak_fun.*"
+    # When linking a dynamic executable, weak undefined symbols become dynamic.
+    set testname "weak undefined function symbols in dynamic exe"
+    undef_weak_exe $testname "--no-as-needed" 1
 
-    if {[regexp $output_regexp $exec_output]} then {
-       pass $testname
-    } else {
-       fail $testname
+    # Find -z options supported by the default emulation
+    set emul [get_target_emul]
+    set cmd [list "$ld --help 2>&1 | sed -e '1,/^$emul:/d;/^\[^ \]*:/,\$d'"]
+    set status [remote_exec host [concat sh -c $cmd]]
+    if { [lindex $status 0] != 0 } {
+       verbose -log "$cmd exited with status [lindex $status 0]"
     }
+    set emulopt [lindex $status 1]
 
-    # When linking a dynamic executable, weak undefined symbols become dynamic.
-    set testname "weak undefined function symbols in dynamic exe"
+    if { [string first "dynamic-undefined-weak" $emulopt] >= 0 } {
+       # -z dynamic-undefined-weak is supported.  Let's see if it works.
 
-    if {![ld_link $ld tmpdir/weak-fundef \
-         "--no-as-needed tmpdir/weak-fundef.o tmpdir/weak-fundef.so"]} then {
-       fail $testname
-    } else {
-       set exec_output [run_host_cmd "$nm" "-D tmpdir/weak-fundef"]
-       set exec_output [prune_warnings $exec_output]
-       verbose -log $exec_output
+       set testname "weak undefined functions in shared lib, no dyn undef weak"
+       undef_weak_so $testname "--shared -z nodynamic-undefined-weak" 0
 
-       if {[regexp $output_regexp $exec_output]} then {
-           pass $testname
-       } else {
-           fail $testname
-       }
+       set testname "weak undefined functions in shared lib, dyn undef weak"
+       undef_weak_so $testname "--shared -z dynamic-undefined-weak" 1
+
+       set testname "weak undefined functions in dynamic exe, no dyn undef weak"
+       undef_weak_exe $testname "-z nodynamic-undefined-weak" 0
+
+       set testname "weak undefined functions in dynamic exe, dyn undef weak"
+       undef_weak_exe $testname "-z dynamic-undefined-weak" 1
+
+       set testname "weak undefined functions in pie, no dyn undef weak"
+       undef_weak_exe $testname "-pie -z nodynamic-undefined-weak" 0
+
+       set testname "weak undefined functions in pie, dyn undef weak"
+       undef_weak_exe $testname "-pie -z dynamic-undefined-weak" 1
     }
 }