PR 6022
authorAlan Modra <amodra@gmail.com>
Sat, 24 Jan 2009 03:10:43 +0000 (03:10 +0000)
committerAlan Modra <amodra@gmail.com>
Sat, 24 Jan 2009 03:10:43 +0000 (03:10 +0000)
* elflink.c (find_version_for_sym): New function split out from,
but without export_dynamic test, ..
(_bfd_elf_link_assign_sym_version): ..here.
(_bfd_elf_export_symbol): Use it.

bfd/ChangeLog
bfd/elflink.c

index 3efcb9434437c372db8fffeb275348f71efc9077..7fe0dce4f52b05023a6f0a58142d8a962fb502db 100644 (file)
@@ -1,3 +1,11 @@
+2009-01-24  Alan Modra  <amodra@bigpond.net.au>
+
+       PR 6022
+       * elflink.c (find_version_for_sym): New function split out from,
+       but without export_dynamic test, ..
+       (_bfd_elf_link_assign_sym_version): ..here.
+       (_bfd_elf_export_symbol): Use it.
+
 2009-01-23  Alan Modra  <amodra@bigpond.net.au>
 
        * elf-bfd.h (struct elf_assign_sym_version_info): Delete.
index 5bbe820e1a258ec449340c8c9dab94ce3c6ea7a4..badbe9e27a24e7764a516dbf6110b5910941efb5 100644 (file)
@@ -1798,6 +1798,80 @@ nondefault:
   return TRUE;
 }
 \f
+static struct bfd_elf_version_tree *
+find_version_for_sym (struct bfd_elf_version_tree *verdefs,
+                     const char *sym_name,
+                     bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
+
+  local_ver = NULL;
+  global_ver = NULL;
+  exist_ver = NULL;
+  for (t = verdefs; t != NULL; t = t->next)
+    {
+      if (t->globals.list != NULL)
+       {
+         struct bfd_elf_version_expr *d = NULL;
+
+         while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
+           {
+             global_ver = t;
+             if (d->symver)
+               exist_ver = t;
+             d->script = 1;
+             /* If the match is a wildcard pattern, keep looking for
+                a more explicit, perhaps even local, match.  */
+             if (d->literal)
+               break;
+           }
+
+         if (d != NULL)
+           break;
+       }
+
+      if (t->locals.list != NULL)
+       {
+         struct bfd_elf_version_expr *d = NULL;
+
+         while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
+           {
+             local_ver = t;
+             /* If the match is a wildcard pattern, keep looking for
+                a more explicit, perhaps even global, match.  */
+             if (d->literal)
+               {
+                 /* An exact match overrides a global wildcard.  */
+                 global_ver = NULL;
+                 break;
+               }
+           }
+
+         if (d != NULL)
+           break;
+       }
+    }
+
+  if (global_ver != NULL)
+    {
+      /* If we already have a versioned symbol that matches the
+        node for this symbol, then we don't want to create a
+        duplicate from the unversioned symbol.  Instead hide the
+        unversioned symbol.  */
+      *hide = exist_ver == global_ver;
+      return global_ver;
+    }
+
+  if (local_ver != NULL)
+    {
+      *hide = TRUE;
+      return local_ver;
+    }
+
+  return NULL;
+}
+
 /* This routine is used to export all defined symbols into the dynamic
    symbol table.  It is called via elf_link_hash_traverse.  */
 
@@ -1821,29 +1895,12 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
       && (h->def_regular
          || h->ref_regular))
     {
-      struct bfd_elf_version_tree *t;
-      struct bfd_elf_version_expr *d;
+      bfd_boolean hide;
 
-      for (t = eif->verdefs; t != NULL; t = t->next)
+      if (eif->verdefs == NULL
+         || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+             && !hide))
        {
-         if (t->globals.list != NULL)
-           {
-             d = (*t->match) (&t->globals, NULL, h->root.root.string);
-             if (d != NULL)
-               goto doit;
-           }
-
-         if (t->locals.list != NULL)
-           {
-             d = (*t->match) (&t->locals, NULL, h->root.root.string);
-             if (d != NULL)
-               return TRUE;
-           }
-       }
-
-      if (!eif->verdefs)
-       {
-       doit:
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
              eif->failed = TRUE;
@@ -2101,78 +2158,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
      something.  */
   if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL)
     {
-      struct bfd_elf_version_tree *t;
-      struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
-      struct bfd_elf_version_expr *d;
-
-      /* See if can find what version this symbol is in.  If the
-        symbol is supposed to be local, then don't actually register
-        it.  */
-      local_ver = NULL;
-      global_ver = NULL;
-      exist_ver = NULL;
-      for (t = sinfo->verdefs; t != NULL; t = t->next)
-       {
-         if (t->globals.list != NULL)
-           {
-             d = NULL;
-             while ((d = (*t->match) (&t->globals, d,
-                                      h->root.root.string)) != NULL)
-               {
-                 global_ver = t;
-                 local_ver = NULL;
-                 if (d->symver)
-                   exist_ver = t;
-                 d->script = 1;
-                 /* If the match is a wildcard pattern, keep looking for
-                    a more explicit, perhaps even local, match.  */
-                 if (d->literal)
-                   break;
-               }
-
-             if (d != NULL)
-               break;
-           }
+      bfd_boolean hide;
 
-         if (t->locals.list != NULL)
-           {
-             d = NULL;
-             while ((d = (*t->match) (&t->locals, d,
-                                      h->root.root.string)) != NULL)
-               {
-                 local_ver = t;
-                 /* If the match is a wildcard pattern, keep looking for
-                    a more explicit, perhaps even global, match.  */
-                 if (d->literal)
-                   {
-                     /* An exact match overrides a global wildcard.  */
-                     global_ver = NULL;
-                     break;
-                   }
-               }
-
-             if (d != NULL)
-               break;
-           }
-       }
-
-      if (global_ver != NULL)
-       {
-         h->verinfo.vertree = global_ver;
-         /* If we already have a versioned symbol that matches the
-            node for this symbol, then we don't want to create a
-            duplicate from the unversioned symbol.  Instead hide the
-            unversioned symbol.  */
-         if (exist_ver == global_ver)
-           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-       }
-      else if (local_ver != NULL)
-       {
-         h->verinfo.vertree = local_ver;
-         if (!info->export_dynamic
-             || exist_ver == local_ver)
-           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-       }
+      h->verinfo.vertree = find_version_for_sym (sinfo->verdefs,
+                                                h->root.root.string, &hide);
+      if (h->verinfo.vertree != NULL && hide)
+       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
     }
 
   return TRUE;