Mark the plugin symbol undefined
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 3 Feb 2015 17:03:23 +0000 (09:03 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 3 Feb 2015 17:03:23 +0000 (09:03 -0800)
LTO may optimize out a plugin symbol, which is also referenced by a
non-IR file.  When that happens, we should mark the plugin symbol
undefined.  It isn't the problem since LTO already determined the
symbols in the non-IR file aren't used.

bfd/

PR ld/12365
PR ld/14272
* elflink.c (_bfd_elf_fix_symbol_flags): Mark the plugin symbol
undefined if it is referenced from a non-IR file.

ld/testsuite/

PR ld/12365
* ld-plugin/pr12365a.c: New file.
* ld-plugin/pr12365b.c: Likewise.
* ld-plugin/pr12365c.c: Likewise.

* ld-plugin/lto.exp (lto_link_tests): Prepare for the PR ld/12365
test.
Run the PR ld/12365 test.

bfd/ChangeLog
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-plugin/lto.exp
ld/testsuite/ld-plugin/pr12365a.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr12365b.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr12365c.c [new file with mode: 0644]

index 4924f03ff3b38230a4fa4f1516743e5f920edc98..a7fe73ccb5c1eb69e39f113f838ce8ce0f499c66 100644 (file)
@@ -1,3 +1,10 @@
+2015-02-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/12365
+       PR ld/14272
+       * elflink.c (_bfd_elf_fix_symbol_flags): Mark the plugin symbol
+       undefined if it is referenced from a non-IR file.
+
 2015-02-03  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/17512
index 26af87085d2ebfcf3398d50acdee59c7d630961c..604cfb6d8ff5dfcb9d95f32881bd872e95c5fb4d 100644 (file)
@@ -2423,6 +2423,20 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
     }
   else
     {
+      /* If a plugin symbol is referenced from a non-IR file, mark
+         the symbol as undefined, except for symbol for linker
+        created section.  */
+      if (h->root.non_ir_ref
+         && (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
+         && (h->root.u.def.section->flags & SEC_LINKER_CREATED) == 0
+         && h->root.u.def.section->owner != NULL
+         && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)
+       {
+         h->root.type = bfd_link_hash_undefined;
+         h->root.u.undef.abfd = h->root.u.def.section->owner;
+       }
+
       /* Unfortunately, NON_ELF is only correct if the symbol
         was first seen in a non-ELF file.  Fortunately, if the symbol
         was first seen in an ELF file, we're probably OK unless the
index 8351d6fbdb29bb148291374121e4a572307a7a27..876bafa84fe3eb688f2692fc9e2a3b2746dc0d9a 100644 (file)
@@ -1,3 +1,14 @@
+2015-02-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/12365
+       * ld-plugin/pr12365a.c: New file.
+       * ld-plugin/pr12365b.c: Likewise.
+       * ld-plugin/pr12365c.c: Likewise.
+
+       * ld-plugin/lto.exp (lto_link_tests): Prepare for the PR ld/12365
+       test.
+       Run the PR ld/12365 test.
+
 2015-02-03  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/14918
index f0643cc5453c2983adbc2765350b58c272e00b17..400e683ec725f6d99e6815dfca12fa05b8984c25 100644 (file)
@@ -88,6 +88,9 @@ set lto_link_tests [list \
   [list "LTO 6" \
    "-O2 -flto -fuse-linker-plugin" "" \
    {lto-6.c} {} "lto-6.exe" "c"] \
+  [list "Compile PR ld/12365" \
+   "" "-flto -O2 $lto_fat" \
+   {pr12365a.c pr12365b.c pr12365c.c} {} ""] \
   [list "Compile 9" \
    "" "-O2 -finline -flto" \
    {lto-9.cc} {} "" "c++"] \
@@ -380,6 +383,13 @@ if {![string match "" $catch_output]} {
 
 if { [at_least_gcc_version 4 7] } {
     # Check expected LTO linker errors.
+    set testname "PR ld/12365"
+    set exec_output [run_host_cmd "$CC" "-O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"]
+    if { [ regexp "undefined reference to `my_bcopy'" $exec_output ] } {
+       pass $testname
+    } {
+       fail $testname
+    }
     set testname "PR ld/12942 (3)"
     set exec_output [run_host_cmd "$CXX" "-O2 -flto -fuse-linker-plugin tmpdir/pr12942b.o tmpdir/pr12942a.o"]
     if { [ regexp "undefined reference to `link_error\\(\\)'" $exec_output ] } {
diff --git a/ld/testsuite/ld-plugin/pr12365a.c b/ld/testsuite/ld-plugin/pr12365a.c
new file mode 100644 (file)
index 0000000..a9bb6c6
--- /dev/null
@@ -0,0 +1,25 @@
+extern void abort(void);
+extern void main_test (void);
+extern void abort (void);
+int inside_main;
+
+int
+main ()
+{
+  inside_main = 1;
+  main_test ();
+  inside_main = 0;
+  return 0;
+}
+
+/* When optimizing, all the constant cases should have been
+   constant folded, so no calls to link_error should remain.
+   In any case, link_error should not be called.  */
+
+#ifndef __OPTIMIZE__
+void
+link_error (void)
+{
+  abort ();
+}
+#endif
diff --git a/ld/testsuite/ld-plugin/pr12365b.c b/ld/testsuite/ld-plugin/pr12365b.c
new file mode 100644 (file)
index 0000000..a5a80e0
--- /dev/null
@@ -0,0 +1,47 @@
+#define ASMNAME(cname)  ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x)    #x
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void *memcpy (void *, const void *, size_t)
+  __asm (ASMNAME ("my_memcpy"));
+extern void bcopy (const void *, void *, size_t)
+  __asm (ASMNAME ("my_bcopy"));
+extern void *memset (void *, int, size_t)
+  __asm (ASMNAME ("my_memset"));
+extern void bzero (void *, size_t)
+  __asm (ASMNAME ("my_bzero"));
+extern int memcmp (const void *, const void *, size_t);
+
+struct A { char c[32]; } a = { "foobar" };
+char x[64] = "foobar", y[64];
+int i = 39, j = 6, k = 4;
+
+extern int inside_main;
+
+void
+main_test (void)
+{
+  struct A b = a;
+  struct A c = { { 'x' } };
+
+  inside_main = 1;
+
+  if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31))
+    abort ();
+  if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64))
+    abort ();
+  if (memcpy (y + 6, x, j) != y + 6
+      || memcmp (x, y, 6) || memcmp (x, y + 6, 58))
+    abort ();
+  if (__builtin_memset (y + 2, 'X', k) != y + 2
+      || memcmp (y, "foXXXXfoobar", 13))
+    abort ();
+  bcopy (y + 1, y + 2, 6);
+  if (memcmp (y, "fooXXXXfobar", 13))
+    abort ();
+  __builtin_bzero (y + 4, 2);
+  if (memcmp (y, "fooX\0\0Xfobar", 13))
+    abort ();
+}
diff --git a/ld/testsuite/ld-plugin/pr12365c.c b/ld/testsuite/ld-plugin/pr12365c.c
new file mode 100644 (file)
index 0000000..2edd0ff
--- /dev/null
@@ -0,0 +1,79 @@
+extern void abort (void);
+extern int inside_main;
+typedef __SIZE_TYPE__ size_t;
+
+#define TEST_ABORT if (inside_main) abort()
+
+void *
+my_memcpy (void *d, const void *s, size_t n)
+{
+  char *dst = (char *) d;
+  const char *src = (const char *) s;
+  while (n--)
+    *dst++ = *src++;
+  return (char *) d;
+}
+
+void
+my_bcopy (const void *s, void *d, size_t n)
+{
+  char *dst = (char *) d;
+  const char *src = (const char *) s;
+  if (src >= dst)
+    while (n--)
+      *dst++ = *src++;
+  else
+    {
+      dst += n;
+      src += n;
+      while (n--)
+        *--dst = *--src;
+    }
+}
+
+void *
+my_memset (void *d, int c, size_t n)
+{
+  char *dst = (char *) d;
+  while (n--)
+    *dst++ = c;
+  return (char *) d;
+}
+
+void
+my_bzero (void *d, size_t n)
+{
+  char *dst = (char *) d;
+  while (n--)
+    *dst++ = '\0';
+}
+
+void *
+memcpy (void *d, const void *s, size_t n)
+{
+  void *result = my_memcpy (d, s, n);
+  TEST_ABORT;
+  return result;
+}
+
+void
+bcopy (const void *s, void *d, size_t n)
+{
+  my_bcopy (s, d, n);
+  TEST_ABORT;
+}
+
+void *
+memset (void *d, int c, size_t n)
+{
+  void *result = my_memset (d, c, n);
+  TEST_ABORT;
+  return result;
+}
+
+void
+bzero (void *d, size_t n)
+{
+  my_bzero (d, n);
+  TEST_ABORT;
+}
This page took 0.043042 seconds and 4 git commands to generate.