]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld: Add _bfd_elf_link_hide_sym_by_version
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 26 May 2018 11:27:09 +0000 (04:27 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Sat, 26 May 2018 11:27:24 +0000 (04:27 -0700)
bfd_hide_sym_by_version can't be used to check if a versioned symbol is
hidden.  This patch adds _bfd_elf_link_hide_sym_by_version to support
both versioned and unversioned symbols by extracting versioned symbol
check from _bfd_elf_link_assign_sym_version.

bfd/

PR ld/23194
* elf-bfd.h (_bfd_elf_link_hide_sym_by_version): New.
* elflink.c (_bfd_elf_link_hide_versioned_symbol): New function.
Extracted from _bfd_elf_link_assign_sym_version.
(_bfd_elf_link_hide_sym_by_version): New function.
(_bfd_elf_link_assign_sym_version): Use
_bfd_elf_link_hide_versioned_symbol.
* elfxx-x86.c (_bfd_x86_elf_link_symbol_references_local): Call
_bfd_elf_link_hide_sym_by_version instead of
bfd_hide_sym_by_version.  Don't check unversioned symbol.

ld/

PR ld/23194
* testsuite/ld-i386/pr23194.d: Expect only R_386_GLOB_DAT
against foobar.
* testsuite/ld-i386/pr23194.map: Add foobar.
* testsuite/ld-x86-64/pr23194.map: Likewise.
* testsuite/ld-i386/pr23194.s: Add a common foobar symbol.
* testsuite/ld-x86-64/pr23194.s: Likewise.
* testsuite/ld-x86-64/pr23194.d: Expect only R_X86_64_GLOB_DAT
against foobar.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elflink.c
bfd/elfxx-x86.c
ld/ChangeLog
ld/testsuite/ld-i386/pr23194.d
ld/testsuite/ld-i386/pr23194.map
ld/testsuite/ld-i386/pr23194.s
ld/testsuite/ld-x86-64/pr23194.d
ld/testsuite/ld-x86-64/pr23194.map
ld/testsuite/ld-x86-64/pr23194.s

index 4cccb96c03614746f6c17ecce29e1577c08f6b70..0419bec612fab193a6fa1c303a7f7d2b3a0e8bcf 100644 (file)
@@ -1,3 +1,16 @@
+2018-05-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/23194
+       * elf-bfd.h (_bfd_elf_link_hide_sym_by_version): New.
+       * elflink.c (_bfd_elf_link_hide_versioned_symbol): New function.
+       Extracted from _bfd_elf_link_assign_sym_version.
+       (_bfd_elf_link_hide_sym_by_version): New function.
+       (_bfd_elf_link_assign_sym_version): Use
+       _bfd_elf_link_hide_versioned_symbol.
+       * elfxx-x86.c (_bfd_x86_elf_link_symbol_references_local): Call
+       _bfd_elf_link_hide_sym_by_version instead of
+       bfd_hide_sym_by_version.  Don't check unversioned symbol.
+
 2018-05-25  Alan Modra  <amodra@gmail.com>
 
        * Makefile.in: Regenerate.
index e051c9c0892b84cdacacc76707aa3f1d4ad3e5bb..032e11f2e9922dd41efe0de29565b2db7c2b4d81 100644 (file)
@@ -2186,6 +2186,9 @@ extern const struct bfd_elf_special_section *_bfd_elf_get_special_section
 extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr
   (bfd *, asection *);
 
+extern bfd_boolean _bfd_elf_link_hide_sym_by_version
+  (struct bfd_link_info *, struct elf_link_hash_entry *);
+
 /* If the target doesn't have reloc handling written yet:  */
 extern bfd_boolean _bfd_elf_no_info_to_howto
   (bfd *, arelent *, Elf_Internal_Rela *);
index 0383e4e37034ee66828cfd801e064a11d2d8d067..05664b4e89bb4f546a120a26e0479ddea2dfd265 100644 (file)
@@ -2222,6 +2222,115 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
+/* Return TRUE and set *HIDE to TRUE if the versioned symbol is
+   hidden.  Set *T_P to NULL if there is no match.  */
+
+static bfd_boolean
+_bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h,
+                                    const char *version_p,
+                                    struct bfd_elf_version_tree **t_p,
+                                    bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+
+  /* Look for the version.  If we find it, it is no longer weak.  */
+  for (t = info->version_info; t != NULL; t = t->next)
+    {
+      if (strcmp (t->name, version_p) == 0)
+       {
+         size_t len;
+         char *alc;
+         struct bfd_elf_version_expr *d;
+
+         len = version_p - h->root.root.string;
+         alc = (char *) bfd_malloc (len);
+         if (alc == NULL)
+           return FALSE;
+         memcpy (alc, h->root.root.string, len - 1);
+         alc[len - 1] = '\0';
+         if (alc[len - 2] == ELF_VER_CHR)
+           alc[len - 2] = '\0';
+
+         h->verinfo.vertree = t;
+         t->used = TRUE;
+         d = NULL;
+
+         if (t->globals.list != NULL)
+           d = (*t->match) (&t->globals, NULL, alc);
+
+         /* See if there is anything to force this symbol to
+            local scope.  */
+         if (d == NULL && t->locals.list != NULL)
+           {
+             d = (*t->match) (&t->locals, NULL, alc);
+             if (d != NULL
+                 && h->dynindx != -1
+                 && ! info->export_dynamic)
+               *hide = TRUE;
+           }
+
+         free (alc);
+         break;
+       }
+    }
+
+  *t_p = t;
+
+  return TRUE;
+}
+
+/* Return TRUE if the symbol H is hidden by version script.  */
+
+bfd_boolean
+_bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
+                                  struct elf_link_hash_entry *h)
+{
+  const char *p;
+  bfd_boolean hide = FALSE;
+  const struct elf_backend_data *bed
+    = get_elf_backend_data (info->output_bfd);
+
+  /* Version script only hides symbols defined in regular objects.  */
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
+    return TRUE;
+
+  p = strchr (h->root.root.string, ELF_VER_CHR);
+  if (p != NULL && h->verinfo.vertree == NULL)
+    {
+      struct bfd_elf_version_tree *t;
+
+      ++p;
+      if (*p == ELF_VER_CHR)
+       ++p;
+
+      if (*p != '\0'
+         && _bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide)
+         && hide)
+       {
+         if (hide)
+           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  /* If we don't have a version for this symbol, see if we can find
+     something.  */
+  if (h->verinfo.vertree == NULL && info->version_info != NULL)
+    {
+      h->verinfo.vertree
+       = bfd_find_version_for_sym (info->version_info,
+                                   h->root.root.string, &hide);
+      if (h->verinfo.vertree != NULL && hide)
+       {
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
 /* Figure out appropriate versions for all the symbols.  We may not
    have the version number script until we have read all of the input
    files, so until that point we don't know which symbols should be
@@ -2235,6 +2344,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   const struct elf_backend_data *bed;
   struct elf_info_failed eif;
   char *p;
+  bfd_boolean hide;
 
   sinfo = (struct elf_info_failed *) data;
   info = sinfo->info;
@@ -2254,6 +2364,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   if (!h->def_regular)
     return TRUE;
 
+  hide = FALSE;
   bed = get_elf_backend_data (info->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -2268,50 +2379,15 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
       if (*p == '\0')
        return TRUE;
 
-      /* Look for the version.  If we find it, it is no longer weak.  */
-      for (t = sinfo->info->version_info; t != NULL; t = t->next)
+      if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide))
        {
-         if (strcmp (t->name, p) == 0)
-           {
-             size_t len;
-             char *alc;
-             struct bfd_elf_version_expr *d;
-
-             len = p - h->root.root.string;
-             alc = (char *) bfd_malloc (len);
-             if (alc == NULL)
-               {
-                 sinfo->failed = TRUE;
-                 return FALSE;
-               }
-             memcpy (alc, h->root.root.string, len - 1);
-             alc[len - 1] = '\0';
-             if (alc[len - 2] == ELF_VER_CHR)
-               alc[len - 2] = '\0';
-
-             h->verinfo.vertree = t;
-             t->used = TRUE;
-             d = NULL;
-
-             if (t->globals.list != NULL)
-               d = (*t->match) (&t->globals, NULL, alc);
-
-             /* See if there is anything to force this symbol to
-                local scope.  */
-             if (d == NULL && t->locals.list != NULL)
-               {
-                 d = (*t->match) (&t->locals, NULL, alc);
-                 if (d != NULL
-                     && h->dynindx != -1
-                     && ! info->export_dynamic)
-                   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-               }
-
-             free (alc);
-             break;
-           }
+         sinfo->failed = TRUE;
+         return FALSE;
        }
 
+      if (hide)
+       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+
       /* If we are building an application, we need to create a
         version node for this version.  */
       if (t == NULL && bfd_link_executable (info))
@@ -2367,10 +2443,10 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
   /* If we don't have a version for this symbol, see if we can find
      something.  */
-  if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL)
+  if (!hide
+      && h->verinfo.vertree == NULL
+      && sinfo->info->version_info != NULL)
     {
-      bfd_boolean hide;
-
       h->verinfo.vertree
        = bfd_find_version_for_sym (sinfo->info->version_info,
                                    h->root.root.string, &hide);
index 710417f90c0721c56952a31ef657ea4c7fcaff11..3a7573f7a2605ca53bda910a701974bc5d36c8f0 100644 (file)
@@ -2038,21 +2038,14 @@ _bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info,
                  && htab->interp == NULL)
              || info->dynamic_undefined_weak == 0))
       || ((h->def_regular || ELF_COMMON_DEF_P (h))
-         && h->versioned == unversioned
          && info->version_info != NULL
-         && bfd_hide_sym_by_version (info->version_info,
-                                     h->root.root.string)))
+         && _bfd_elf_link_hide_sym_by_version (info, h)))
     {
       eh->local_ref = 2;
       return TRUE;
     }
 
-  /* bfd_hide_sym_by_version can't be used to check if a versioned symbol
-     is hidden.  It has to be syncd with _bfd_elf_link_assign_sym_version
-     to get the correct answer.  */
-  if (h->versioned == unversioned)
-    eh->local_ref = 1;
-
+  eh->local_ref = 1;
   return FALSE;
 }
 
index d418b20dbf66191dbfe1cbb4b32114a7afbf6556..fa5f2224cc5c29e17a118fefd1eba67ff46d87fe 100644 (file)
@@ -1,3 +1,15 @@
+2018-05-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/23194
+       * testsuite/ld-i386/pr23194.d: Expect only R_386_GLOB_DAT
+       against foobar.
+       * testsuite/ld-i386/pr23194.map: Add foobar.
+       * testsuite/ld-x86-64/pr23194.map: Likewise.
+       * testsuite/ld-i386/pr23194.s: Add a common foobar symbol.
+       * testsuite/ld-x86-64/pr23194.s: Likewise.
+       * testsuite/ld-x86-64/pr23194.d: Expect only R_X86_64_GLOB_DAT
+       against foobar.
+
 2018-05-25  Alan Modra  <amodra@gmail.com>
 
        * po/BLD-POTFILES.in: Regenerate.
index b5e8c3330eecec9aba2928fccd936090d867517e..f6d2a03b5d134fb19aae570112f54a7e6ffe23ae 100644 (file)
@@ -4,4 +4,4 @@
 
 Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
  Offset     Info    Type                Sym. Value  Symbol's Name
-[0-9a-f]+ +[0-9a-f]+ +R_386_RELATIVE +
+[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +[0-9a-f]+ +foobar@@FOO
index 353c194af573d9bf689ee6e6fe6518b0f5db6193..196dac96399d973ee0c366905040f2f4ff5c5271 100644 (file)
@@ -1,6 +1,7 @@
 FOO {
   global:
     bar;
+    foobar;
   local:
     *;
 };
index 32693feb7f9eaca1f60cd78619f3c4c9baff65f6..a64bae16fed95d7789eb08a37c780181590db631 100644 (file)
@@ -3,10 +3,11 @@
        .globl  foo
        .type   foo, @function
 foo:
-       ret
+       movl foobar@GOT(%ebx), %eax
        .size   foo, .-foo
        .globl  bar
        .type   bar, @function
 bar:
        jmp     *foo@GOT(%eax)
        .size   bar, .-bar
+       .comm foobar,30,4
index 6b12060822769ff5be445530809b24d69fe17cdc..b907afbcebdd81942b99e7de69dcbd5f4b5747a7 100644 (file)
@@ -4,4 +4,4 @@
 
 Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
     Offset             Info             Type               Symbol's Value  Symbol's Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_GLOB_DAT +[0-9a-f]+ +foobar@@FOO \+ 0
index 353c194af573d9bf689ee6e6fe6518b0f5db6193..196dac96399d973ee0c366905040f2f4ff5c5271 100644 (file)
@@ -1,6 +1,7 @@
 FOO {
   global:
     bar;
+    foobar;
   local:
     *;
 };
index 277c19d6dc6ca45adcf8d3268240b5bd7f8b0feb..34517bc7e221e3ba37406cfe0f24aa106b8d884b 100644 (file)
@@ -3,10 +3,11 @@
        .globl  foo
        .type   foo, @function
 foo:
-       ret
+       movq foobar@GOTPCREL(%rip), %rax
        .size   foo, .-foo
        .globl  bar
        .type   bar, @function
 bar:
        jmp     *foo@GOTPCREL(%rip)
        .size   bar, .-bar
+       .comm foobar,30,4