PR26806, Suspected linker bug with LTO
authorAlan Modra <amodra@gmail.com>
Fri, 30 Oct 2020 04:26:35 +0000 (14:56 +1030)
committerAlan Modra <amodra@gmail.com>
Sun, 1 Nov 2020 23:09:53 +0000 (09:39 +1030)
This patch reverts most of git commit 1e3b96fd6cf, so IR symbols are
again not marked def_regular or ref_regular.  That should be enough to
stop IR symbols from becoming dynamic.  To mark as-needed shared
libraries referenced by IR symbols, use the referencing BFD rather
than the ref flags.

bfd/
PR 15146
PR 26314
PR 26530
PR 26806
* elflink.c (elf_link_add_object_symbols): Don't set def/ref flags
for plugin syms.  Do allow plugin syms to mark as-needed libs.
ld/
PR 26806
* testsuite/ld-plugin/lto-19.h,
* testsuite/ld-plugin/lto-19a.c,
* testsuite/ld-plugin/lto-19b.c,
* testsuite/ld-plugin/lto-19c.c: New test.
* testsuite/ld-plugin/pr26806.c,
* testsuite/ld-plugin/pr26806.d: New test.
* testsuite/ld-plugin/lto.exp: Run them.

bfd/ChangeLog
bfd/elflink.c
ld/ChangeLog
ld/testsuite/ld-plugin/lto-19.h [new file with mode: 0644]
ld/testsuite/ld-plugin/lto-19a.c [new file with mode: 0644]
ld/testsuite/ld-plugin/lto-19b.c [new file with mode: 0644]
ld/testsuite/ld-plugin/lto-19c.c [new file with mode: 0644]
ld/testsuite/ld-plugin/lto.exp
ld/testsuite/ld-plugin/pr26806.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr26806.d [new file with mode: 0644]

index a12ba7de337437a16d1c2769c4712e9376641303..e632282a71cf14ba0d87a0890f2286323b7d3420 100644 (file)
@@ -1,3 +1,12 @@
+2020-11-02  Alan Modra  <amodra@gmail.com>
+
+       PR 15146
+       PR 26314
+       PR 26530
+       PR 26806
+       * elflink.c (elf_link_add_object_symbols): Don't set def/ref flags
+       for plugin syms.  Do allow plugin syms to mark as-needed libs.
+
 2020-10-30  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/26703
index e23d189b9835047c90f84a37970f6cc534727597..4b035a2cd56fdbf2dcb793b2dc0ffb807265272f 100644 (file)
@@ -4989,7 +4989,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
             object and a shared object.  */
          bfd_boolean dynsym = FALSE;
 
-         if (! dynamic)
+         /* Plugin symbols aren't normal.  Don't set def/ref flags.  */
+         if ((abfd->flags & BFD_PLUGIN) != 0)
+           ;
+         else if (!dynamic)
            {
              if (! definition)
                {
@@ -5006,14 +5009,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                      h->ref_dynamic = 1;
                    }
                }
-
-             /* If the indirect symbol has been forced local, don't
-                make the real symbol dynamic.  */
-             if ((h == hi || !hi->forced_local)
-                 && (bfd_link_dll (info)
-                     || h->def_dynamic
-                     || h->ref_dynamic))
-               dynsym = TRUE;
            }
          else
            {
@@ -5027,14 +5022,25 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                  h->def_dynamic = 1;
                  hi->def_dynamic = 1;
                }
+           }
 
-             /* If the indirect symbol has been forced local, don't
-                make the real symbol dynamic.  */
-             if ((h == hi || !hi->forced_local)
-                 && (h->def_regular
-                     || h->ref_regular
-                     || (h->is_weakalias
-                         && weakdef (h)->dynindx != -1)))
+         /* If an indirect symbol has been forced local, don't
+            make the real symbol dynamic.  */
+         if (h != hi && hi->forced_local)
+           ;
+         else if (!dynamic)
+           {
+             if (bfd_link_dll (info)
+                 || h->def_dynamic
+                 || h->ref_dynamic)
+               dynsym = TRUE;
+           }
+         else
+           {
+             if (h->def_regular
+                 || h->ref_regular
+                 || (h->is_weakalias
+                     && weakdef (h)->dynindx != -1))
                dynsym = TRUE;
            }
 
@@ -5170,6 +5176,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              && !bfd_link_relocatable (info))
            dynsym = FALSE;
 
+         /* Nor should we make plugin symbols dynamic.  */
+         if ((abfd->flags & BFD_PLUGIN) != 0)
+           dynsym = FALSE;
+
          if (definition)
            {
              h->target_internal = isym->st_target_internal;
@@ -5196,7 +5206,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                }
            }
 
-         if (dynsym && (abfd->flags & BFD_PLUGIN) == 0 && h->dynindx == -1)
+         if (dynsym && h->dynindx == -1)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
                goto error_free_vers;
@@ -5225,6 +5235,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              && definition
              && ((dynsym
                   && h->ref_regular_nonweak)
+                 || (old_bfd != NULL
+                     && (old_bfd->flags & BFD_PLUGIN) != 0
+                     && bind != STB_WEAK)
                  || (h->ref_dynamic_nonweak
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
                      && !on_needed_list (elf_dt_name (abfd),
index 3f39eb462e7e3783b61e24f0ff0017e4e4b6a740..f980e6239440b19aa09c8df13b8ccc0f667ae0df 100644 (file)
@@ -1,3 +1,14 @@
+2020-11-02  Alan Modra  <amodra@gmail.com>
+
+       PR 26806
+       * testsuite/ld-plugin/lto-19.h,
+       * testsuite/ld-plugin/lto-19a.c,
+       * testsuite/ld-plugin/lto-19b.c,
+       * testsuite/ld-plugin/lto-19c.c: New test.
+       * testsuite/ld-plugin/pr26806.c,
+       * testsuite/ld-plugin/pr26806.d: New test.
+       * testsuite/ld-plugin/lto.exp: Run them.
+
 2020-10-30  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/26703
diff --git a/ld/testsuite/ld-plugin/lto-19.h b/ld/testsuite/ld-plugin/lto-19.h
new file mode 100644 (file)
index 0000000..0ca48d1
--- /dev/null
@@ -0,0 +1,6 @@
+struct re_dfa_t {
+  const int *sb_char;
+};
+struct re_dfa_t *xregcomp (void);
+struct re_dfa_t *rpl_regcomp (void);
+void rpl_regfree (struct re_dfa_t *);
diff --git a/ld/testsuite/ld-plugin/lto-19a.c b/ld/testsuite/ld-plugin/lto-19a.c
new file mode 100644 (file)
index 0000000..6213f79
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "lto-19.h"
+
+static const int utf8_sb_map[4] = { 0x12, 0x34, 0x56, 0x78 };
+
+struct re_dfa_t *
+rpl_regcomp ()
+{
+  struct re_dfa_t *dfa = malloc (sizeof (struct re_dfa_t));
+  dfa->sb_char = utf8_sb_map;
+  return dfa;
+}
+
+void
+rpl_regfree (struct re_dfa_t *dfa)
+{
+  puts (dfa->sb_char == utf8_sb_map ? "PASS" : "FAIL");
+}
diff --git a/ld/testsuite/ld-plugin/lto-19b.c b/ld/testsuite/ld-plugin/lto-19b.c
new file mode 100644 (file)
index 0000000..b784f84
--- /dev/null
@@ -0,0 +1,7 @@
+#include "lto-19.h"
+
+struct re_dfa_t *
+xregcomp (void)
+{
+  return rpl_regcomp ();
+}
diff --git a/ld/testsuite/ld-plugin/lto-19c.c b/ld/testsuite/ld-plugin/lto-19c.c
new file mode 100644 (file)
index 0000000..0d231ba
--- /dev/null
@@ -0,0 +1,9 @@
+#include "lto-19.h"
+
+int
+main ()
+{
+  struct re_dfa_t *dfa = xregcomp ();
+  rpl_regfree (dfa);
+  return 0;
+}
index 9f9f2d13ced3d7f93b21eeab041a59f273d354be..23c948cc64324c1ac4e80f8d20c3be7406f0a106 100644 (file)
@@ -403,6 +403,18 @@ set lto_link_elf_tests [list \
   [list {lto-18d.o} \
    {} {-flto -O2} \
    {lto-18d.c} {} {}] \
+  [list {liblto-19.a} \
+   "$plug_opt" {-flto -O2 -fPIC} \
+   {lto-19a.c} {} {liblto-19.a}] \
+  [list {compile lto-19b.c} \
+   "$plug_opt" {-flto -O2 -fPIC} \
+   {lto-19b.c} {} {} {c}] \
+  [list {liblto-19.so} \
+   {-shared tmpdir/lto-19b.o tmpdir/liblto-19.a} {-O2 -fPIC} \
+   {dummy.c} {} {liblto-19.so}] \
+  [list {pr26806.so} \
+   {-shared} {-fpic -O2 -flto} \
+   {pr26806.c} {{nm {-D} pr26806.d}} {pr26806.so}] \
 ]
 
 # PR 14918 checks that libgcc is not spuriously included in a shared link of
@@ -584,6 +596,10 @@ set lto_run_elf_shared_tests [list \
    {-static -flto -fuse-linker-plugin} {} \
    {lto-18a.c} {lto-18-4.exe} {lto-18.out} {-flto -O2} {c} {} \
    { -Ltmpdir -llto-18b -llto-18c tmpdir/lto-18d.o}] \
+  [list {lto-19} \
+   {-Wl,--as-needed,-R,tmpdir} {} \
+   {lto-19c.c} {lto-19.exe} {pass.out} {-flto -O2} {c} {} \
+   {tmpdir/liblto-19.so tmpdir/liblto-19.a}] \
 ]
 
 # LTO run-time tests for ELF
diff --git a/ld/testsuite/ld-plugin/pr26806.c b/ld/testsuite/ld-plugin/pr26806.c
new file mode 100644 (file)
index 0000000..8bb2931
--- /dev/null
@@ -0,0 +1,2 @@
+#include <unistd.h>
+int foo (int x) { if (__builtin_constant_p (x)) return getpid (); return 0; }
diff --git a/ld/testsuite/ld-plugin/pr26806.d b/ld/testsuite/ld-plugin/pr26806.d
new file mode 100644 (file)
index 0000000..16fa828
--- /dev/null
@@ -0,0 +1,4 @@
+#failif
+#...
+.* _*getpid[@ ].*
+#...