ld: Set non_ir_ref_regular on symbols referenced in regular objects
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 28 Nov 2017 11:48:25 +0000 (03:48 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 28 Nov 2017 11:48:44 +0000 (03:48 -0800)
If linker plugin is enabled, set non_ir_ref_regular on symbols referenced
in regular objects so that linker plugin will get the correct symbol
resolution.

bfd/

PR ld/22502
* elflink.c (_bfd_elf_merge_symbol): Also skip definition from
an IR object.
(elf_link_add_object_symbols): If linker plugin is enabled, set
non_ir_ref_regular on symbols referenced in regular objects so
that linker plugin will get the correct symbol resolution.

ld/

PR ld/22502
* testsuite/ld-plugin/lto.exp: Run PR ld/22502 test.
* testsuite/ld-plugin/pr22502a.c: New file.
* testsuite/ld-plugin/pr22502b.c: Likewise.

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

index 3903b1d..abd7c96 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/22502
+       * elflink.c (_bfd_elf_merge_symbol): Also skip definition from
+       an IR object.
+       (elf_link_add_object_symbols): If linker plugin is enabled, set
+       non_ir_ref_regular on symbols referenced in regular objects so
+       that linker plugin will get the correct symbol resolution.
+
 2017-11-27  Szabolcs Nagy  <szabolcs.nagy@arm.com>
 
        PR ld/22263
index 99f867d..ddd088c 100644 (file)
@@ -1555,10 +1555,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
       sec = *psec;
     }
 
-  /* There are multiple definitions of a normal symbol.
-     Skip the default symbol as well.  */
+  /* There are multiple definitions of a normal symbol.  Skip the
+     default symbol as well as definition from an IR object.  */
   if (olddef && !olddyn && !oldweak && newdef && !newdyn && !newweak
-      && !default_sym && h->def_regular)
+      && !default_sym && h->def_regular
+      && !(oldbfd != NULL
+          && (oldbfd->flags & BFD_PLUGIN) != 0
+          && (abfd->flags & BFD_PLUGIN) == 0))
     {
       /* Handle a multiple definition.  */
       (*info->callbacks->multiple_definition) (info, &h->root,
@@ -4931,6 +4934,65 @@ error_free_dyn:
        }
     }
 
+  if (info->lto_plugin_active
+      && !bfd_link_relocatable (info)
+      && (abfd->flags & BFD_PLUGIN) == 0
+      && !just_syms
+      && extsymcount)
+    {
+      int r_sym_shift;
+
+      if (bed->s->arch_size == 32)
+       r_sym_shift = 8;
+      else
+       r_sym_shift = 32;
+
+      /* If linker plugin is enabled, set non_ir_ref_regular on symbols
+        referenced in regular objects so that linker plugin will get
+        the correct symbol resolution.  */
+
+      sym_hash = elf_sym_hashes (abfd);
+      for (s = abfd->sections; s != NULL; s = s->next)
+       {
+         Elf_Internal_Rela *internal_relocs;
+         Elf_Internal_Rela *rel, *relend;
+
+         /* Don't check relocations in excluded sections.  */
+         if ((s->flags & SEC_RELOC) == 0
+             || s->reloc_count == 0
+             || (s->flags & SEC_EXCLUDE) != 0
+             || ((info->strip == strip_all
+                  || info->strip == strip_debugger)
+                 && (s->flags & SEC_DEBUGGING) != 0))
+           continue;
+
+         internal_relocs = _bfd_elf_link_read_relocs (abfd, s, NULL,
+                                                      NULL,
+                                                      info->keep_memory);
+         if (internal_relocs == NULL)
+           goto error_free_vers;
+
+         rel = internal_relocs;
+         relend = rel + s->reloc_count;
+         for ( ; rel < relend; rel++)
+           {
+             unsigned long r_symndx = rel->r_info >> r_sym_shift;
+             struct elf_link_hash_entry *h;
+
+             /* Skip local symbols.  */
+             if (r_symndx < extsymoff)
+               continue;
+
+             h = sym_hash[r_symndx - extsymoff];
+             if (h != NULL)
+               h->root.non_ir_ref_regular = 1;
+           }
+
+         if (elf_section_data (s)->relocs != internal_relocs)
+           free (internal_relocs);
+       }
+    }
+
   if (extversym != NULL)
     {
       free (extversym);
index 9c10c7e..ed63236 100644 (file)
@@ -1,3 +1,10 @@
+2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/22502
+       * testsuite/ld-plugin/lto.exp: Run PR ld/22502 test.
+       * testsuite/ld-plugin/pr22502a.c: New file.
+       * testsuite/ld-plugin/pr22502b.c: Likewise.
+
 2017-11-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        * testsuite/ld-elf/pr21562c.t: Also provide ___start_scnfoo and
index d34479f..56c852d 100644 (file)
@@ -208,6 +208,12 @@ set lto_link_tests [list \
    "-flto -Wl,-plugin,$plug_so" "-flto" \
    {pr20321.c} {{warning ".*: duplicated plugin"}} \
    "pr20321" "c"] \
+  [list "Build pr22502a.o" \
+   "" "" \
+   {pr22502a.c}] \
+  [list "Build pr22502b.o" \
+   "$plug_opt" "-flto $lto_no_fat" \
+   {pr22502b.c}] \
 ]
 
 if { [at_least_gcc_version 4 7] } {
@@ -391,6 +397,9 @@ set lto_run_tests [list \
   [list "Run pr20267b" \
    "-O2 -flto tmpdir/pr20267a.o tmpdir/libpr20267b.a" "" \
    {dummy.c} "pr20267b" "pass.out" "-flto -O2" "c"] \
+  [list "Run pr22502" \
+   "-O2 -flto tmpdir/pr22502a.o tmpdir/pr22502b.o" "" \
+   {dummy.c} "pr20267" "pass.out" "-flto -O2" "c"] \
 ]
 
 if { [at_least_gcc_version 4 7] } {
diff --git a/ld/testsuite/ld-plugin/pr22502a.c b/ld/testsuite/ld-plugin/pr22502a.c
new file mode 100644 (file)
index 0000000..0eaa1af
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+volatile int x;
+extern void abort ();
+
+__attribute__((weak))
+void foobar (void) { x++; }
+
+int main (void)
+{
+  foobar ();
+  if (x != -1)
+    abort ();
+  printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr22502b.c b/ld/testsuite/ld-plugin/pr22502b.c
new file mode 100644 (file)
index 0000000..87389b9
--- /dev/null
@@ -0,0 +1,3 @@
+extern volatile int x;
+
+void foobar (void) { x--; }