Version script help needed

H. J. Lu hjl@lucon.org
Mon Aug 5 10:18:00 GMT 2002


On Mon, Aug 05, 2002 at 04:11:56PM +0200, Franz Sirl wrote:
> At 22:00 03.08.2002, H. J. Lu wrote:
> >On Sat, Aug 03, 2002 at 07:04:18PM +0200, Franz Sirl wrote:
> > > On Samstag, 3. August 2002 18:33, H. J. Lu wrote:
> > > > On Sat, Aug 03, 2002 at 05:57:37PM +0200, Franz Sirl wrote:
> > > > > One thing makes me wonder though, if I use .symver and a version 
> > script,
> > > > > why are versioned symbols matched? E. if I use .symver and the 
> > following
> > > > > version script
> > > > >
> > > > > VEROLD {
> > > > >      local:
> > > > >      *;
> > > > > };
> > > > >
> > > > > VERNEW {
> > > > >      local:
> > > > >      *;
> > > > > } VEROLD;
> > > > >
> > > > > divdi3@VEROLD and divdi3@@VERNEW will be changed from GLOBAL scope to
> > > > > LOCAL scope. On the other side version scripts prevent me from from 
> > using
> > > > > versioned symbols in there? Is this the right behaviour?
> > > >
> > > > I don't see there is a problem.
> > >
> > > Hmm, I seem to miss the logic then. If you don't strip mylibgcc2.so, 
> > you'll
> > > see:
> > >
> > > [fsirl@enzo:~/test-versioning]$ readelf -a mylibgcc2.so|grep divdi3
> > >     31: 00000708    36 FUNC    GLOBAL DEFAULT    9 divdi3@@VERNEW
> > >     69: 00000000     0 FILE    LOCAL  DEFAULT  ABS divdi3-old.c
> > >     70: 00000000     0 FILE    LOCAL  DEFAULT  ABS divdi3-new.c
> > >     78: 000006e4    36 FUNC    LOCAL  DEFAULT    9 divdi3@VEROLD
> > >    190: 000006e4    36 FUNC    LOCAL  DEFAULT    9 divdi3_old
> > >    200: 00000708    36 FUNC    GLOBAL DEFAULT    9 divdi3
> > >
> > > So divdi3 got versioned as VEROLD, but it wasn't globalized. On the 
> > other hand
> > > if I mention divdi3 under VEROLD too in the script (and you can't directly
> > > list divdi3@VEROLD in there), I don't get divdi3 at VERNEW, even though 
> > it is
> > > mentioned there.
> > >
> > > I guess what I'm trying to say, why isn't the symbol matching in version
> > > scripts limited to unversioned symbols and symbols matching the current
> > > version node for a particular version node?
> >
> >I can't guess what you really want. Why not tell us what you want in
> >the resulting DSO?
> 
> I still want the same as in my first mail in the DSO:
> 
>      31: 00000708    36 FUNC    GLOBAL DEFAULT    9 divdi3@@VERNEW
>      78: 000006e4    36 FUNC    GLOBAL DEFAULT    9 divdi3@VEROLD
> 
> And I wanted to accomplish that without having an explicit .symver for the 
> VERNEW symbol version.
> 
> I think I just don't understand how the symbol matching in a version script 
> works. With this script:
> 
> VEROLD {
>          global:
>            divdi3;
> };
> 
> VERNEW {
>          global:
>            divdi3;
>          local:
>            *;
> } VEROLD;
> 

Here is a patch to do that. However, I am sure if it is %100 correct.
Any comments with testcases?


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

	* elflink.h (elf_link_assign_sym_version): Don't match a
	default version if there is a hidden versioned definition.

--- bfd/elflink.h.defver	Fri Jul 26 23:41:26 2002
+++ bfd/elflink.h	Mon Aug  5 10:12:56 2002
@@ -4274,6 +4274,10 @@ elf_link_assign_sym_version (h, data)
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_tree *local_ver;
       struct bfd_elf_version_expr *d;
+      const char *verstr, *name;
+      size_t namelen, verlen, newlen;
+      char *newname;
+      struct elf_link_hash_entry *newh;
 
       /* See if can find what version this symbol is in.  If the
 	 symbol is supposed to be local, then don't actually register
@@ -4287,9 +4291,38 @@ elf_link_assign_sym_version (h, data)
 		{
 		  if ((*d->match) (d, h->root.root.string))
 		    {
-		      h->verinfo.vertree = t;
-		      local_ver = NULL;
-		      break;
+		      name = h->root.root.string;
+		      namelen = strlen (name);
+		      verstr = t->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 didn't find the hidden versioned
+			     definition.  Use it.  */
+			  h->verinfo.vertree = t;
+			  local_ver = NULL;
+			  break;
+			}
 		    }
 		}
 
@@ -4332,11 +4365,6 @@ elf_link_assign_sym_version (h, data)
 	 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;


More information about the Binutils mailing list