Handle symbol defined in IR and referenced in DSO
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 20 Apr 2017 14:48:24 +0000 (07:48 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 20 Apr 2017 14:48:35 +0000 (07:48 -0700)
We need to make an IR symbol visible if it is defined in an IR object
and referenced in a dynamic object.  When --as-needed is used, since
linker removes the IR symbol reference of the dynamic object if the
dynamic object isn't needed in the first pass, the IR definition isn't
visible to the dynamic object even if the dynamic object becomes needed
in the second pass.  Add dynamic_ref_after_ir_def to bfd_link_hash_entry
to track IR symbol which is defined in an IR object and later referenced
in a dynamic object.  dynamic_ref_after_ir_def is preserved when restoring
the symbol table for unneeded dynamic object.

bfd/

PR ld/21382
* elflink.c (elf_link_add_object_symbols): Preserve
dynamic_ref_after_ir_def when restoring the symbol table for
unneeded dynamic object.

include/

PR ld/21382
* bfdlink.h (bfd_link_hash_entry): Add dynamic_ref_after_ir_def.

ld/

PR ld/21382
* plugin.c (is_visible_from_outside): Symbol may be visible
from outside if dynamic_ref_after_ir_def is set.
(plugin_notice): Set dynamic_ref_after_ir_def if the symbol is
defined in an IR object and referenced in a dynamic object.
* testsuite/ld-plugin/lto.exp: Run PR ld/21382 tests.
* testsuite/ld-plugin/pr21382a.c: New file.
* testsuite/ld-plugin/pr21382b.c: Likewise.

bfd/ChangeLog
bfd/elflink.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/plugin.c
ld/testsuite/ld-plugin/lto.exp
ld/testsuite/ld-plugin/pr21382a.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr21382b.c [new file with mode: 0644]

index 11fbdab1b23a8e23f2d035a9951f40cad49f8c18..214d0a8c7302e1a7b219c38720d795700f6ee8f7 100644 (file)
@@ -1,3 +1,10 @@
+2017-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21382
+       * elflink.c (elf_link_add_object_symbols): Preserve
+       dynamic_ref_after_ir_def when restoring the symbol table for
+       unneeded dynamic object.
+
 2017-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/21401
index 0add01b5ad9fb094985fd88c5338a3a5260fa652..972b6f8eb5d61e0c9a754734a15ae66849e55e64 100644 (file)
@@ -4932,6 +4932,7 @@ error_free_dyn:
          struct elf_link_hash_entry *h;
          bfd_size_type size;
          unsigned int alignment_power;
+         unsigned int dynamic_ref_after_ir_def;
 
          for (p = htab->root.table.table[i]; p != NULL; p = p->next)
            {
@@ -4953,6 +4954,10 @@ error_free_dyn:
                  size = 0;
                  alignment_power = 0;
                }
+             /* Preserve dynamic_ref_after_ir_def so that this symbol
+                will be exported when the dynamic lib becomes needed
+                in the second pass.  */
+             dynamic_ref_after_ir_def = h->root.dynamic_ref_after_ir_def;
              memcpy (p, old_ent, htab->root.table.entsize);
              old_ent = (char *) old_ent + htab->root.table.entsize;
              h = (struct elf_link_hash_entry *) p;
@@ -4969,6 +4974,7 @@ error_free_dyn:
                  if (alignment_power > h->root.u.c.p->alignment_power)
                    h->root.u.c.p->alignment_power = alignment_power;
                }
+             h->root.dynamic_ref_after_ir_def = dynamic_ref_after_ir_def;
            }
        }
 
index 90c4c8d3044bc02545889d7e5388398164c2810b..31dc68f4ba394027563a64631f48c7ab93b03c74 100644 (file)
@@ -1,3 +1,8 @@
+2017-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21382
+       * bfdlink.h (bfd_link_hash_entry): Add dynamic_ref_after_ir_def.
+
 2017-04-19  Alan Modra  <amodra@gmail.com>
 
        * bfdlink.h (struct bfd_link_info <dynamic_undefined_weak>):
index 18dea0c7318a278de4209c270df43cbc05e2d292..cb4bad9fb5a561f9d58d72fd32831026057e1682 100644 (file)
@@ -104,6 +104,10 @@ struct bfd_link_hash_entry
      IR object file.  */
   unsigned int non_ir_ref : 1;
 
+  /* Symbol is referenced in a dynamic object after it has been defined
+     in an IR object.  */
+  unsigned int dynamic_ref_after_ir_def : 1;
+
   /* Symbol is a built-in define.  These will be overridden by PROVIDE
      in a linker script.  */
   unsigned int linker_def : 1;
index bccd2becc63e5a822a54ba0a98c535168752105c..208c1197f1859861a26a9580a0d054b2249cd811 100644 (file)
@@ -1,3 +1,14 @@
+2017-04-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/21382
+       * plugin.c (is_visible_from_outside): Symbol may be visible
+       from outside if dynamic_ref_after_ir_def is set.
+       (plugin_notice): Set dynamic_ref_after_ir_def if the symbol is
+       defined in an IR object and referenced in a dynamic object.
+       * testsuite/ld-plugin/lto.exp: Run PR ld/21382 tests.
+       * testsuite/ld-plugin/pr21382a.c: New file.
+       * testsuite/ld-plugin/pr21382b.c: Likewise.
+
 2017-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/21401
index 03e2e69a639151285e9a06c41a722cdf87a03ca9..164b5db5d6d23a3daa527a49a88510796a75e78f 100644 (file)
@@ -629,7 +629,9 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym,
 
   if (bfd_link_relocatable (&link_info))
     return TRUE;
-  if (link_info.export_dynamic || bfd_link_dll (&link_info))
+  if (blhe->dynamic_ref_after_ir_def
+      || link_info.export_dynamic
+      || bfd_link_dll (&link_info))
     {
       /* Check if symbol is hidden by version script.  */
       if (bfd_hide_sym_by_version (link_info.version_info,
@@ -1316,12 +1318,21 @@ plugin_notice (struct bfd_link_info *info,
       /* If this is a ref, set non_ir_ref.  */
       else if (bfd_is_und_section (section))
        {
+          if (h->type == bfd_link_hash_defweak
+              || h->type == bfd_link_hash_defined)
+            {
+              /* Check if the symbol is referenced in a dynamic object
+                 after it has been defined in an IR object.  */
+              if ((abfd->flags & DYNAMIC) != 0
+                  && is_ir_dummy_bfd (h->u.def.section->owner))
+                h->dynamic_ref_after_ir_def = TRUE;
+            }
          /* Replace the undefined dummy bfd with the real one.  */
-         if ((h->type == bfd_link_hash_undefined
-              || h->type == bfd_link_hash_undefweak)
-             && (h->u.undef.abfd == NULL
-                 || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
-           h->u.undef.abfd = abfd;
+          else if ((h->type == bfd_link_hash_undefined
+                    || h->type == bfd_link_hash_undefweak)
+                   && (h->u.undef.abfd == NULL
+                       || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
+            h->u.undef.abfd = abfd;
          h->non_ir_ref = TRUE;
        }
 
index 80c084bda119c8fed8452d1e612dea06341cc383..f0bc345f2c76b3fb1ed44b4354089932e1a45253 100644 (file)
@@ -289,6 +289,12 @@ set lto_link_elf_tests [list \
   [list "PR ld/14918" \
    "-flto" "-flto" \
    {pr14918.c} {{"readelf" {-d --wide} "pr14918.d"}} "pr14918.exe" "c"] \
+  [list "Build pr21382a.o" \
+   "" "-O2 -flto" \
+   {pr21382a.c} {} "" "c"] \
+  [list "Build pr21382.so" \
+   "-shared" "-O2 -fpic" \
+   {pr21382b.c} {} "pr21382.so" "c"] \
 ]
 
 # Check final symbols in executables.
@@ -387,6 +393,9 @@ set lto_run_elf_shared_tests [list \
   [list "LTO 7" \
    "-O2 -flto -fuse-linker-plugin tmpdir/lto-7b.o tmpdir/lto-7c.o tmpdir/lto-7a.o -Wl,--no-as-needed tmpdir/liblto-7.so" "" \
    {dummy.c} "lto-7.exe" "lto-7.out" "" "c"] \
+  [list "Run pr21382" \
+   "-O2 -flto -fuse-linker-plugin -Wl,--as-needed tmpdir/pr21382a.o tmpdir/pr21382.so" "" \
+   {dummy.c} "pr21382.exe" "pass.out" "" "c"] \
 ]
 
 # LTO run-time tests for ELF
diff --git a/ld/testsuite/ld-plugin/pr21382a.c b/ld/testsuite/ld-plugin/pr21382a.c
new file mode 100644 (file)
index 0000000..09b9d75
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+extern void y (void);
+
+void
+x (void)
+{
+  printf ("PASS\n");
+}
+
+
+int
+main (void)
+{
+  y ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr21382b.c b/ld/testsuite/ld-plugin/pr21382b.c
new file mode 100644 (file)
index 0000000..c5b74a9
--- /dev/null
@@ -0,0 +1,7 @@
+extern void x (void);
+
+void
+y (void)
+{
+  x ();
+}