PATCH: Check undefined version

H. J. Lu hjl@lucon.org
Wed Aug 7 20:35:00 GMT 2002


On Thu, Aug 08, 2002 at 10:56:57AM +0930, Alan Modra wrote:
> On Wed, Aug 07, 2002 at 01:40:43PM -0700, H. J. Lu wrote:
> > I'd like to check in this patch to check symbols with undefine version.
> 
> The idea looks OK to me.
> 
> > +      for (t = verdefs; t != NULL; t = t->next)
> > +	if (t->globals != NULL)
> > +	  for (d = t->globals; d != NULL; d = d->next)
> 
> The "if" here is redundant.
> 
> > +		if (!newh
> 
> Style.  if (newh == NULL
> 
> > +		if (newh
> 
> Again.  if (newh != NULL
> 
> > +	  /* Check if all global versions have a definiton.  */
> > +	  all_defined = true;
> > +	  for (t = verdefs; t != NULL; t = t->next)
> > +	    if (t->globals != NULL)
> > +	      for (d = t->globals; d != NULL; d = d->next)
> 
> Redundant "if"
> 

This is the updated patch I am going to check in.


H.J.
-------------- next part --------------
bfd/
2002-08-06  H.J. Lu <hjl@gnu.org>

	* elflink.h (NAME(bfd_elf,size_dynamic_sections)): Check symbol
	with undefined version if needed.
	(elf_link_assign_sym_version): Match a default symbol with a
	version without definition. No need to hide the default
	definition separately.

include/
2002-08-06  H.J. Lu <hjl@gnu.org>

	* bfdlink.h (bfd_link_info): Add allow_undefined_version.
	(bfd_elf_version_expr): Add symver and script.

ld/
2002-08-06  H.J. Lu <hjl@gnu.org>

	* ld.texinfo: Document --no-undefined-version.

	* ldlang.c (lang_new_vers_pattern): Set the `symver' and
	`script.' fields to 0.

	* ldmain.c (main): Initialize the allow_undefined_version to
	true.

	* lexsup.c (OPTION_NO_UNDEFINED_VERSION): New.
	(ld_options): Add --no-undefined-version.
	(parse_args): Support OPTION_NO_UNDEFINED_VERSION.

ld/testsuite
2002-08-06  H.J. Lu <hjl@gnu.org>

	* ld-elfvers/vers.exp: Add --no-undefined-version.

	* ld-elfvers/vers1.map: Remove the unused foo1 and foo2.
	* ld-elfvers/vers8.map: Likewise.
	* ld-elfvers/vers18.map: Likewise.

--- binutils/bfd/elflink.h.defver	Fri Jul 26 23:41:26 2002
+++ binutils/bfd/elflink.h	Wed Aug  7 20:30:44 2002
@@ -2938,6 +2941,9 @@ NAME(bfd_elf,size_dynamic_sections) (out
       struct elf_info_failed eif;
       struct elf_link_hash_entry *h;
       asection *dynstr;
+      struct bfd_elf_version_tree *t;
+      struct bfd_elf_version_expr *d;
+      boolean all_defined;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (*sinterpptr != NULL || info->shared);
@@ -3018,6 +3024,54 @@ NAME(bfd_elf,size_dynamic_sections) (out
 	    return false;
 	}
 
+      /* Make all global versions with definiton.  */
+      for (t = verdefs; t != NULL; t = t->next)
+	for (d = t->globals; d != NULL; d = d->next)
+	  if (!d->symver && strchr (d->pattern, '*') == NULL)
+	    {
+	      const char *verstr, *name;
+	      size_t namelen, verlen, newlen;
+	      char *newname, *p;
+	      struct elf_link_hash_entry *newh;
+
+	      name = d->pattern;
+	      namelen = strlen (name);
+	      verstr = t->name;
+	      verlen = strlen (verstr);
+	      newlen = namelen + verlen + 3; 
+
+	      newname = (char *) bfd_malloc ((bfd_size_type) newlen);
+	      if (newname == NULL)
+		return false;
+	      memcpy (newname, name, namelen);
+
+	      /* Check the hidden versioned definition.  */
+	      p = newname + namelen;
+	      *p++ = ELF_VER_CHR;
+	      memcpy (p, verstr, verlen + 1);
+	      newh = elf_link_hash_lookup (elf_hash_table (info),
+					   newname, false, false,
+					   false);
+	      if (newh == NULL
+		  || (newh->root.type != bfd_link_hash_defined
+		      && newh->root.type != bfd_link_hash_defweak))
+		{
+		  /* Check the default versioned definition.  */
+		  *p++ = ELF_VER_CHR;
+		  memcpy (p, verstr, verlen + 1);
+		  newh = elf_link_hash_lookup (elf_hash_table (info),
+					       newname, false, false,
+					       false);
+		}
+	      free (newname);
+
+	      /* Mark this version if there is a definition.  */
+	      if (newh != NULL
+		  && (newh->root.type == bfd_link_hash_defined
+		      || newh->root.type == bfd_link_hash_defweak))
+		d->symver = 1;
+	    }
+
       /* Attach all the symbols to their version information.  */
       asvinfo.output_bfd = output_bfd;
       asvinfo.info = info;
@@ -3030,6 +3084,28 @@ NAME(bfd_elf,size_dynamic_sections) (out
       if (asvinfo.failed)
 	return false;
 
+      if (!info->allow_undefined_version)
+	{
+	  /* Check if all global versions have a definiton.  */
+	  all_defined = true;
+	  for (t = verdefs; t != NULL; t = t->next)
+	    for (d = t->globals; d != NULL; d = d->next)
+	      if (!d->symver && !d->script
+		  && strchr (d->pattern, '*') == NULL)
+		{
+		  (*_bfd_error_handler)
+		    (_("%s: undefined version: %s"),
+		     d->pattern, t->name);
+		  all_defined = false;
+		}
+
+	  if (!all_defined)
+	    {
+	      bfd_set_error (bfd_error_bad_value);
+	      return false;
+	    }
+	}
+
       /* Find all symbols which were defined in a dynamic object and make
 	 the backend pick a reasonable value for them.  */
       elf_link_hash_traverse (elf_hash_table (info),
@@ -4258,7 +4334,6 @@ elf_link_assign_sym_version (h, data)
 	    (_("%s: undefined versioned symbol name %s"),
 	     bfd_get_filename (sinfo->output_bfd), h->root.root.string);
 	  bfd_set_error (bfd_error_bad_value);
-	error_return:
 	  sinfo->failed = true;
 	  return false;
 	}
@@ -4283,18 +4358,34 @@ elf_link_assign_sym_version (h, data)
 	{
 	  if (t->globals != NULL)
 	    {
+	      boolean matched;
+
+	      matched = false;
 	      for (d = t->globals; d != NULL; d = d->next)
 		{
 		  if ((*d->match) (d, h->root.root.string))
 		    {
-		      h->verinfo.vertree = t;
-		      local_ver = NULL;
-		      break;
+		      if (d->symver)
+			matched = true;
+		      else
+			{
+			  /* There is a version without definition.  Make
+			     the symbol the default definition for this
+			     version.  */
+			  h->verinfo.vertree = t;
+			  local_ver = NULL;
+			  d->script = 1;
+			  break;
+			}
 		    }
 		}
 
 	      if (d != NULL)
 		break;
+	      else if (matched)
+		/* There is no undefined version for this symbol. Hide the
+		   default one.  */
+		(*bed->elf_backend_hide_symbol) (info, h, true);
 	    }
 
 	  if (t->locals != NULL)
@@ -4327,43 +4418,6 @@ elf_link_assign_sym_version (h, data)
 	      (*bed->elf_backend_hide_symbol) (info, h, true);
 	    }
 	}
-
-      /* We need to check if a hidden versioned definition should
-	 hide the default one.  */
-      if (h->dynindx != -1 && h->verinfo.vertree != NULL)
-	{
-	  const char *verstr, *name;
-	  size_t namelen, verlen, newlen;
-	  char *newname;
-	  struct elf_link_hash_entry *newh;
-
-	  name = h->root.root.string;
-	  namelen = strlen (name);
-	  verstr = h->verinfo.vertree->name;
-	  verlen = strlen (verstr);
-	  newlen = namelen + verlen + 2;
-
-	  newname = (char *) bfd_malloc ((bfd_size_type) newlen);
-	  if (newname == NULL)
-	    goto error_return;
-	  memcpy (newname, name, namelen);
-
-	  /* Check the hidden versioned definition.  */
-	  p = newname + namelen;
-	  *p++ = ELF_VER_CHR;
-	  memcpy (p, verstr, verlen + 1);
-	  newh = elf_link_hash_lookup (elf_hash_table (info), newname,
-				       false, false, false);
-
-	  if (newh
-	      && (newh->root.type == bfd_link_hash_defined
-		  || newh->root.type == bfd_link_hash_defweak))
-	    /* We found a hidden versioned definition.  Hide the
-	       default one.  */
-	    (*bed->elf_backend_hide_symbol) (info, h, true);
-
-	  free (newname);
-	}
     }
 
   return true;
--- binutils/include/bfdlink.h.defver	Wed Jul 31 08:54:09 2002
+++ binutils/include/bfdlink.h	Wed Aug  7 13:13:42 2002
@@ -262,6 +262,9 @@ struct bfd_link_info
   /* true if ok to have multiple definition.  */
   boolean allow_multiple_definition;
 
+  /* true if ok to have version with no definition.  */
+  boolean allow_undefined_version;
+
   /* Which symbols to strip.  */
   enum bfd_link_strip strip;
 
@@ -602,6 +605,10 @@ struct bfd_elf_version_expr
   const char *pattern;
   /* Matching function.  */
   int (*match) PARAMS((struct bfd_elf_version_expr *, const char *));
+  /* Defined by ".symver".  */
+  unsigned int symver: 1;
+  /* Defined by version script.  */
+  unsigned int script : 1;
 };
 
 /* Version dependencies.  */
--- binutils/ld/ld.texinfo.defver	Mon Jul 15 19:21:32 2002
+++ binutils/ld/ld.texinfo	Wed Aug  7 13:27:27 2002
@@ -1102,6 +1102,12 @@ select which function is most appropriat
 I.E. dynamically select an appropriate memset function.  Apparently it
 is also normal for HPPA shared libraries to have undefined symbols.
 
+@kindex --no-undefined-version
+@item --no-undefined-version
+Normally when a symbol has an undefined version, the linker will ignore
+it. This option disallows symbols with undefined version and a fatal error
+will be issued instead.
+
 @kindex --no-warn-mismatch
 @item --no-warn-mismatch
 Normally @command{ld} will give an error if you try to link together input
--- binutils/ld/ldlang.c.defver	Tue Jul 30 14:38:18 2002
+++ binutils/ld/ldlang.c	Tue Aug  6 08:09:44 2002
@@ -5132,6 +5132,8 @@ lang_new_vers_pattern (orig, new, lang)
   ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
   ret->next = orig;
   ret->pattern = new;
+  ret->symver = 0;
+  ret->script = 0;
 
   if (lang == NULL || strcasecmp (lang, "C") == 0)
     ret->match = lang_vers_match_lang_c;
--- binutils/ld/ldmain.c.defver	Wed Jul 31 08:54:17 2002
+++ binutils/ld/ldmain.c	Wed Aug  7 13:06:49 2002
@@ -241,6 +241,7 @@ main (argc, argv)
   link_info.no_undefined = false;
   link_info.allow_shlib_undefined = false;
   link_info.allow_multiple_definition = false;
+  link_info.allow_undefined_version = true;
   link_info.strip = strip_none;
   link_info.discard = discard_sec_merge;
   link_info.keep_memory = true;
--- binutils/ld/lexsup.c.defver	Tue May 21 22:43:13 2002
+++ binutils/ld/lexsup.c	Wed Aug  7 13:23:03 2002
@@ -128,7 +128,8 @@ int parsing_defsym = 0;
 #define OPTION_TARGET_HELP              (OPTION_UNIQUE + 1)
 #define OPTION_ALLOW_SHLIB_UNDEFINED	(OPTION_TARGET_HELP + 1)
 #define OPTION_ALLOW_MULTIPLE_DEFINITION (OPTION_ALLOW_SHLIB_UNDEFINED + 1)
-#define OPTION_DISCARD_NONE		(OPTION_ALLOW_MULTIPLE_DEFINITION + 1)
+#define OPTION_NO_UNDEFINED_VERSION	(OPTION_ALLOW_MULTIPLE_DEFINITION + 1)
+#define OPTION_DISCARD_NONE		(OPTION_NO_UNDEFINED_VERSION + 1)
 #define OPTION_SPARE_DYNAMIC_TAGS	(OPTION_DISCARD_NONE + 1)
 #define OPTION_NO_DEFINE_COMMON		(OPTION_SPARE_DYNAMIC_TAGS + 1)
 #define OPTION_NOSTDLIB			(OPTION_NO_DEFINE_COMMON + 1)
@@ -328,6 +329,8 @@ static const struct ld_option ld_options
      '\0', NULL, N_("Allow undefined symbols in shared objects"), TWO_DASHES },
   { {"allow-multiple-definition", no_argument, NULL, OPTION_ALLOW_MULTIPLE_DEFINITION},
      '\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
+  { {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
+     '\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
   { {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
       '\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
   { {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
@@ -769,6 +772,9 @@ parse_args (argc, argv)
 	case OPTION_ALLOW_MULTIPLE_DEFINITION:
 	  link_info.allow_multiple_definition = true;
 	  break;
+	case OPTION_NO_UNDEFINED_VERSION:
+	  link_info.allow_undefined_version = false;
+	  break;
 	case OPTION_NO_WARN_MISMATCH:
 	  command_line.warn_mismatch = false;
 	  break;
--- binutils/ld/testsuite/ld-elfvers/vers.exp.defver	Tue Jul 30 14:38:25 2002
+++ binutils/ld/testsuite/ld-elfvers/vers.exp	Wed Aug  7 17:20:00 2002
@@ -62,7 +62,7 @@ set tmpdir tmpdir
 set VOBJDUMP_FLAGS --private-headers
 set DOBJDUMP_FLAGS --dynamic-syms
 set SOBJDUMP_FLAGS --syms
-set shared --shared
+set shared "--shared --no-undefined-version"
 set script --version-script
 
 proc test_ar { test lib object expect } {
@@ -643,7 +643,7 @@ proc build_exec { test source execname f
     global CC
     global CFLAGS
 
-    set shared --shared
+    set shared "--shared --no-undefined-version"
     set script --version-script
     if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s]     {
 	unresolved "$test"
--- binutils/ld/testsuite/ld-elfvers/vers1.map.defver	Thu Jun  3 11:02:11 1999
+++ binutils/ld/testsuite/ld-elfvers/vers1.map	Tue Aug  6 08:50:55 2002
@@ -1,6 +1,4 @@
 VERS_1.1 {
-	 global:
-		 foo1;
 	 local:
 		 hide_old*; 
 		 hide_original*; 
@@ -8,7 +6,6 @@ VERS_1.1 {
 };
 
 VERS_1.2 {
-		 foo2;
 } VERS_1.1;
 
 VERS_2.0 {
--- binutils/ld/testsuite/ld-elfvers/vers18.map.defver	Tue Aug  6 09:06:44 2002
+++ binutils/ld/testsuite/ld-elfvers/vers18.map	Tue Aug  6 09:04:19 2002
@@ -1,6 +1,4 @@
 VERS_1.1 {
-	 global:
-		 foo1;
 	 local:
 		 hide_old*; 
 		 hide_original*; 
@@ -8,7 +6,6 @@ VERS_1.1 {
 };
 
 VERS_1.2 {
-		 foo2;
 } VERS_1.1;
 
 VERS_2.0 {
--- binutils/ld/testsuite/ld-elfvers/vers8.map.defver	Thu Jun  3 11:02:11 1999
+++ binutils/ld/testsuite/ld-elfvers/vers8.map	Tue Aug  6 09:03:59 2002
@@ -1,7 +1,5 @@
 VERSION {
 	VERS_1.1 {
-		 global:
-			 foo1;
 		 local:
 			 hide_old*; 
 			 hide_original*; 
@@ -9,7 +7,6 @@ VERSION {
 	};
 	
 	VERS_1.2 {
-			 foo2;
 	} VERS_1.1;
 	
 	VERS_2.0 {


More information about the Binutils mailing list