This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR 6022, local wildcard version vs. -rdynamic


This cures PR6022, a variation on PR7047 but for --export-dynamic, by
using the same logic when exporting all symbols as we now use for
matching symbols against version scripts.  Besides fixing the "local: *"
complaint in the PR, this also makes --export-dynamic actually heed all
local directives in a version script.  Previously, if a symbol would
be global except for matching a local directive in a version script,
linking with --export-dynamic kept it as global.

	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.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.326
diff -u -p -r1.326 elflink.c
--- bfd/elflink.c	23 Jan 2009 12:15:27 -0000	1.326
+++ bfd/elflink.c	24 Jan 2009 01:29:51 -0000
@@ -1798,6 +1798,80 @@ nondefault:
   return TRUE;
 }
 
+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_
       && (h->def_regular
 	  || h->ref_regular))
     {
-      struct bfd_elf_version_tree *t;
-      struct bfd_elf_version_expr *d;
-
-      for (t = eif->verdefs; t != NULL; t = t->next)
-	{
-	  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;
-	    }
-	}
+      bfd_boolean hide;
 
-      if (!eif->verdefs)
+      if (eif->verdefs == NULL
+	  || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+	      && !hide))
 	{
-	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
      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;
-	    }
-
-	  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;
-	    }
-	}
+      bfd_boolean hide;
 
-      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;

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]