This is the mail archive of the binutils@sources.redhat.com 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]

[PATCH] .symver x, x@foo (take 2)


On Mon, Feb 10, 2003 at 11:03:31AM +0100, Jakub Jelinek wrote:
> Hi!
> 
> The following patch changes .symver x, x@foo so that any references to x
> in the same link aren't resolved to the local x copy, but end up
> with dynamic relocation against x@foo.
> See the thread from December about glibc errno on this list.
> ATM there is no way to make dynamic relocations which are needed, so that
> references to the compat symbol in the shared library defining
> it are resolved to R_*_COPY in binaries referencing it if any.
> The closest what hjl suggested was that the shared library defines x@foo
> symbol and the relocations are against a different symbol, SHN_UNDEF
> x.  The problem then is that the binary might have legally x@bar COPY
> reloc.
> This is still a RFC, because although it works on most arches, it failed
> on alpha with an assertion. Am going to look at it.

For alpha the symbol was changed into indirect too late.
The following patch works on all arches I've tried (IA-{32,64}, Alpha,
PPC32, s390{,x}, x86-64) and builds a working glibc (unlike
binutils without the patch).

2003-02-10  Jakub Jelinek  <jakub@redhat.com>

bfd/
	* elflink.h (elf_link_add_object_symbols): Handle .symver x, x@FOO.
ld/testsuite/
	* ld-shared/shared.exp: Run on s390*-*-linux* and x86_64-*-linux* too.
	xfail tests linking non-pic code into shared libs on x86_64-*-linux*.
	* ld-elfvsb/elfvsb.exp: Likewise.
	* ld-elfvers/vers.exp: Likewise.  Add vers24a, vers24b and vers24c
	tests.
	* ld-elfvers/vers3.ver: Allow VERS_2.0 to come before GLIBC_*
	version.
	* ld-elfvers/vers19.ver: Likewise.
	* ld-elfvers/vers24a.c: New test.
	* ld-elfvers/vers24b.c: New test.
	* ld-elfvers/vers24c.c: New test.
	* ld-elfvers/vers24.map: New test.
	* ld-elfvers/vers24.rd: New test.
	* lib/ld-lib.exp (run_ld_link_tests): Add optional 7th argument
	cflags.  If source files have .c extension, compile them first.

--- bfd/elflink.h.jj	2003-02-05 18:24:42.000000000 -0500
+++ bfd/elflink.h	2003-02-10 10:42:05.000000000 -0500
@@ -1168,6 +1168,8 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *ever;
   struct elf_link_hash_entry *weaks;
+  struct elf_link_hash_entry **nondeflt_vers = NULL;
+  bfd_size_type nondeflt_vers_cnt = 0;
   Elf_Internal_Sym *isymbuf = NULL;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
@@ -1997,6 +1999,23 @@ elf_link_add_object_symbols (abfd, info)
 					  override, dt_needed))
 	      goto error_free_vers;
 
+	  if (definition && (abfd->flags & DYNAMIC) == 0)
+	    {
+	      char *p = strchr (name, ELF_VER_CHR);
+	      if (p != NULL && p[1] != ELF_VER_CHR)
+		{
+		  /* Queue non-default versions so that .symver x, x@FOO
+		     aliases can be checked.  */
+		  if (! nondeflt_vers)
+		    {
+		      amt = (isymend - isym + 1)
+			    * sizeof (struct elf_link_hash_entry *);
+		      nondeflt_vers = bfd_malloc (amt);
+		    }
+		  nondeflt_vers [nondeflt_vers_cnt++] = h;
+		}
+	    }
+
 	  if (dynsym && h->dynindx == -1)
 	    {
 	      if (! _bfd_elf_link_record_dynamic_symbol (info, h))
@@ -2071,6 +2090,56 @@ elf_link_add_object_symbols (abfd, info)
 	}
     }
 
+  /* Now that all the symbols from this input file are created, handle
+     .symver foo, foo@BAR such that any relocs against foo become foo@BAR.  */
+  if (nondeflt_vers != NULL)
+    {
+      bfd_size_type cnt, symidx;
+
+      for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt)
+	{
+	  struct elf_link_hash_entry *h = nondeflt_vers[cnt], *hi;
+	  char *shortname, *p;
+
+	  p = strchr (h->root.root.string, ELF_VER_CHR);
+	  if (p == NULL
+	      || (h->root.type != bfd_link_hash_defined
+		  && h->root.type != bfd_link_hash_defweak))
+	    continue;
+
+	  amt = p - h->root.root.string;
+	  shortname = bfd_malloc (amt + 1);
+	  memcpy (shortname, h->root.root.string, amt);
+	  shortname[amt] = '\0';
+
+	  hi = (struct elf_link_hash_entry *)
+	       bfd_link_hash_lookup (info->hash, shortname,
+				     FALSE, FALSE, FALSE);
+	  if (hi != NULL
+	      && hi->root.type == h->root.type
+	      && hi->root.u.def.value == h->root.u.def.value
+	      && hi->root.u.def.section == h->root.u.def.section)
+	    {
+	      (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+	      hi->root.type = bfd_link_hash_indirect;
+	      hi->root.u.i.link = (struct bfd_link_hash_entry *) h;
+	      (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
+	      hi->elf_link_hash_flags = 0;
+	      sym_hash = elf_sym_hashes (abfd);
+	      if (sym_hash)
+		for (symidx = 0; symidx < extsymcount; ++symidx)
+		  if (sym_hash[symidx] == hi)
+		    {
+		      sym_hash[symidx] = h;
+		      break;
+		    }
+	    }
+	  free (shortname);
+	}
+      free (nondeflt_vers);
+      nondeflt_vers = NULL;
+    }
+
   if (extversym != NULL)
     {
       free (extversym);
@@ -2277,6 +2346,8 @@ elf_link_add_object_symbols (abfd, info)
   return TRUE;
 
  error_free_vers:
+  if (nondeflt_vers != NULL)
+    free (nondeflt_vers);
   if (extversym != NULL)
     free (extversym);
  error_free_sym:
--- ld/testsuite/ld-elfvers/vers.exp.jj	2002-09-10 08:51:14.000000000 -0400
+++ ld/testsuite/ld-elfvers/vers.exp	2003-02-09 17:59:11.000000000 -0500
@@ -43,7 +43,9 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget sparc*-*-linux*] \
      && ![istarget arm*-*-linux*] \
      && ![istarget mips*-*-linux*] \
-     && ![istarget alpha*-*-linux*] } {
+     && ![istarget alpha*-*-linux*] \
+     && ![istarget s390*-*-linux*] \
+     && ![istarget x86_64-*-linux*] } {
     return
 }
 
@@ -719,7 +721,12 @@ build_vers_lib "vers1" vers1.c vers1 "" 
 # Test #2 - build a library, and link it against the library we built in step
 # 1.
 #
-build_vers_lib "vers2" vers2.c vers2 vers1.so vers2.map vers2.ver vers2.dsym ""
+if [istarget x86_64-*-linux*] {
+    # x86_64 doesn't like non-pic shared libraries
+    xfail "vers2"
+} else {
+    build_vers_lib "vers2" vers2.c vers2 vers1.so vers2.map vers2.ver vers2.dsym ""
+}
 
 #
 # Test #3 - build an executable, and link it against vers1.so.
@@ -838,3 +845,21 @@ build_vers_lib "vers23b" vers23b.c vers2
 build_vers_lib "vers23c" vers23b.c vers23c "vers23a.so" vers23b.map vers23c.ver vers23b.dsym ""
 build_exec "vers23d" vers23.c vers23d "tmpdir/vers23a.so tmpdir/vers23c.so" "" vers23.ver vers23d.dsym ""
 build_exec "vers23" vers23.c vers23 "tmpdir/vers23a.so tmpdir/vers23b.o tmpdir/vers23b.so" "" vers23.ver vers23.dsym ""
+
+# Test .symver x,x@VERS.0
+set as_pic_flags ""
+if [istarget sparc*-*-*] {
+  set as_pic_flags "-K PIC"
+}
+run_ld_link_tests [list "\"vers24a\"
+			 \"-shared --version-script $srcdir/$subdir/vers24.map\"
+			 \"$as_pic_flags\" {vers24a.c vers24b.c} { { readelf -Wrs vers24.rd } }
+			 \"libvers24a.so\" \"-fpic\""]
+run_ld_link_tests [list "\"vers24b\"
+			 \"-shared --version-script $srcdir/$subdir/vers24.map\"
+			 \"$as_pic_flags\" {vers24b.c vers24a.c} { { readelf -Wrs vers24.rd } }
+			 \"libvers24b.so\" \"-fpic\""]
+run_ld_link_tests [list "\"vers24c\"
+			 \"-shared --version-script $srcdir/$subdir/vers24.map\"
+			 \"$as_pic_flags\" {vers24c.c} { { readelf -Wrs vers24.rd } }
+			 \"libvers24c.so\" \"-fpic\""]
--- ld/testsuite/ld-elfvers/vers24a.c.jj	2003-02-08 16:00:04.000000000 -0500
+++ ld/testsuite/ld-elfvers/vers24a.c	2003-02-08 17:27:53.000000000 -0500
@@ -0,0 +1,5 @@
+/* Test whether .symver x, x@foo
+   causes relocations against x within the same shared library
+   to become dynamic relocations against x@foo.  */
+int x = 12;
+__asm__ (".symver x, x@VERS.0");
--- ld/testsuite/ld-elfvers/vers24b.c.jj	2003-02-08 16:00:15.000000000 -0500
+++ ld/testsuite/ld-elfvers/vers24b.c	2003-02-07 17:43:02.000000000 -0500
@@ -0,0 +1,5 @@
+extern int x;
+void foo (void)
+{
+  x = 24;
+}
--- ld/testsuite/ld-elfvers/vers24.map.jj	2003-02-08 16:00:32.000000000 -0500
+++ ld/testsuite/ld-elfvers/vers24.map	2003-02-08 16:01:23.000000000 -0500
@@ -0,0 +1,4 @@
+VERS.0 {
+  global: x; foo;
+  local: *;
+};
--- ld/testsuite/ld-elfvers/vers3.ver.jj	2001-07-11 09:48:54.000000000 -0400
+++ ld/testsuite/ld-elfvers/vers3.ver	2003-02-09 17:57:40.000000000 -0500
@@ -1,4 +1,4 @@
 Version References:
   required from tmpdir/vers1.so:
-    0x0a7922b0 0x00 02 VERS_2.0
+    0x0a7922b0 0x00 0[23] VERS_2.0
 
--- ld/testsuite/ld-elfvers/vers24.rd.jj	2003-02-08 17:18:25.000000000 -0500
+++ ld/testsuite/ld-elfvers/vers24.rd	2003-02-09 18:22:41.000000000 -0500
@@ -0,0 +1,15 @@
+Relocation section .*
+# Ensure there is a dynamic relocation against x
+#...
+[0-9a-f]+ +[0-9a-f]+ R_.* +x(| \+ 0)
+#...
+Symbol table '.dynsym' contains [0-9]+ entries:
+# And ensure the dynamic symbol table contains at least x@VERS.0
+# and foo@@VERS.0 symbols
+#...
+ +[0-9]+: [0-9a-f]+ +(4 OBJECT +GLOBAL DEFAULT +[0-9]+ x|[0-9]+ FUNC +GLOBAL DEFAULT +[0-9]+ foo@)@VERS\.0
+#...
+ +[0-9]+: [0-9a-f]+ +(4 OBJECT +GLOBAL DEFAULT +[0-9]+ x|[0-9]+ FUNC +GLOBAL DEFAULT +[0-9]+ foo@)@VERS\.0
+#...
+Symbol table '.symtab' contains [0-9]+ entries:
+#pass
--- ld/testsuite/ld-elfvers/vers24c.c.jj	2003-02-08 17:29:10.000000000 -0500
+++ ld/testsuite/ld-elfvers/vers24c.c	2003-02-08 17:29:04.000000000 -0500
@@ -0,0 +1,9 @@
+/* Test whether .symver x, x@foo
+   causes relocations against x within the same shared library
+   to become dynamic relocations against x@foo.  */
+int x = 12;
+__asm__ (".symver x, x@VERS.0");
+void foo (void)
+{
+  x = 24;
+}
--- ld/testsuite/ld-elfvers/vers19.ver.jj	2001-05-11 06:26:01.000000000 -0400
+++ ld/testsuite/ld-elfvers/vers19.ver	2003-02-09 17:57:53.000000000 -0500
@@ -1,3 +1,3 @@
 Version References:
   required from vers17.so:
-    0x0a7922b0 0x00 02 VERS_2.0
+    0x0a7922b0 0x00 0[23] VERS_2.0
--- ld/testsuite/ld-elfvsb/elfvsb.exp.jj	2002-07-30 10:20:17.000000000 -0400
+++ ld/testsuite/ld-elfvsb/elfvsb.exp	2003-02-09 18:23:44.000000000 -0500
@@ -1,5 +1,5 @@
 # Expect script for ld-visibility tests
-#   Copyright 2000, 2001 Free Software Foundation, Inc.
+#   Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -35,7 +35,9 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget powerpc-*-linux*] \
      && ![istarget arm*-*-linux*] \
      && ![istarget alpha*-*-linux*] \
-     && ![istarget sparc*-*-linux*] } {
+     && ![istarget sparc*-*-linux*] \
+     && ![istarget s390*-*-linux*] \
+     && ![istarget x86_64-*-linux*] } {
     return
 }
 
@@ -255,6 +257,7 @@ proc visibility_run {visibility} {
 		setup_xfail "ia64-*-linux*"
 		setup_xfail "alpha*-*-linux*"
 	    }
+	    setup_xfail "x86_64-*-linux*"
 
 	    visibility_test $visibility vnp "visibility ($visibility) (non PIC)" mainnp.o sh1np.o sh2np.o elfvsb
 
@@ -285,6 +288,7 @@ proc visibility_run {visibility} {
 		setup_xfail "alpha*-*-linux*"
 		setup_xfail "mips*-*-linux*"
 	    }
+	    setup_xfail "x86_64-*-linux*"
 	    visibility_test $visibility vnp "visibility ($visibility) (non PIC, load offset)" \
 		mainnp.o sh1np.o sh2np.o elfvsb \
 		"-T $srcdir/$subdir/elf-offset.ld"
@@ -341,6 +345,7 @@ proc visibility_run {visibility} {
 		    setup_xfail "ia64-*-linux*"
 		    setup_xfail "alpha*-*-linux*"
 		}
+		setup_xfail "x86_64-*-linux*"
 		visibility_test $visibility vmpnp "visibility ($visibility) (PIC main, non PIC so)" mainp.o sh1np.o sh2np.o elfvsb
 	    }
 	} else {
--- ld/testsuite/lib/ld-lib.exp.jj	2002-12-28 17:19:23.000000000 -0500
+++ ld/testsuite/lib/ld-lib.exp	2003-02-08 16:15:19.000000000 -0500
@@ -1,5 +1,5 @@
 # Support routines for LD testsuite.
-#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 #   Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify
@@ -978,9 +978,11 @@ proc file_contents { filename } {
     return $contents
 }
 
-# List contains test-items with 3 items followed by 2 lists:
+# List contains test-items with 3 items followed by 2 lists, one item and
+# one optional item:
 # 0:name 1:ld options 2:assembler options
 # 3:filenames of assembler files 4: action and options. 5: name of output file
+# 6:compiler flags (optional)
 
 # Actions:
 # objdump: Apply objdump options on result.  Compare with regex (last arg).
@@ -996,14 +998,17 @@ proc run_ld_link_tests { ldtests } {
     global srcdir
     global subdir
     global env
+    global CC
+    global CFLAGS
 
     foreach testitem $ldtests {
 	set testname [lindex $testitem 0]
 	set ld_options [lindex $testitem 1]
 	set as_options [lindex $testitem 2]
-	set as_files  [lindex $testitem 3]
+	set src_files  [lindex $testitem 3]
 	set actions [lindex $testitem 4]
 	set binfile tmpdir/[lindex $testitem 5]
+	set cflags [lindex $testitem 6]
 	set objfiles {}
 	set is_unresolved 0
 	set failed 0
@@ -1011,16 +1016,25 @@ proc run_ld_link_tests { ldtests } {
 #	verbose -log "Testname is $testname"
 #	verbose -log "ld_options is $ld_options"
 #	verbose -log "as_options is $as_options"
-#	verbose -log "as_files is $as_files"
+#	verbose -log "src_files is $src_files"
 #	verbose -log "actions is $actions"
 #	verbose -log "binfile is $binfile"
 
 	# Assemble each file in the test.
-	foreach as_file $as_files {
-	    set objfile "tmpdir/[file rootname $as_file].o"
+	foreach src_file $src_files {
+	    set objfile "tmpdir/[file rootname $src_file].o"
 	    lappend objfiles $objfile
 
-	    if ![ld_assemble $as "$as_options $srcdir/$subdir/$as_file" $objfile] {
+	    if { [file extension $src_file] == ".c" } {
+		set as_file "tmpdir/[file rootname $src_file].s"
+		if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
+		    set is_unresolved 1
+		    break
+		}
+	    } else {
+		set as_file "$srcdir/$subdir/$src_file"
+	    }
+	    if ![ld_assemble $as "$as_options $as_file" $objfile] {
 		set is_unresolved 1
 		break
 	    }
--- ld/testsuite/ld-shared/shared.exp.jj	2002-07-30 10:20:20.000000000 -0400
+++ ld/testsuite/ld-shared/shared.exp	2003-02-09 18:00:00.000000000 -0500
@@ -1,5 +1,5 @@
 # Expect script for ld-shared tests
-#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
 #   Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify
@@ -49,7 +49,9 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget arm*-*-linux*] \
      && ![istarget alpha*-*-linux*] \
      && ![istarget rs6000*-*-aix*] \
-     && ![istarget powerpc*-*-aix*] } {
+     && ![istarget powerpc*-*-aix*] \
+     && ![istarget s390*-*-linux*] \
+     && ![istarget x86_64-*-linux*] } {
     return
 }
 
@@ -198,6 +200,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG" $
 	setup_xfail "*-*-sunos4*"
 	setup_xfail "ia64-*-linux*"
 	setup_xfail "alpha*-*-linux*"
+	setup_xfail "x86_64-*-linux*"
 	shared_test shnp "shared (non PIC)" mainnp.o sh1np.o sh2np.o shared
 
 	# Test ELF shared library relocations with a non-zero load
@@ -210,6 +213,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG" $
 	setup_xfail "ia64-*-linux*"
 	setup_xfail "alpha*-*-linux*"
 	setup_xfail "mips*-*-linux*"
+	setup_xfail "x86_64-*-linux*"
 	shared_test shnp "shared (non PIC, load offset)" \
 		mainnp.o sh1np.o sh2np.o shared \
 		"-T $srcdir/$subdir/elf-offset.ld"
@@ -251,6 +255,7 @@ if ![ld_compile "$CC $CFLAGS $SHCFLAG $p
 	    setup_xfail "*-*-sunos4*"
 	    setup_xfail "ia64-*-linux*"
 	    setup_xfail "alpha*-*-linux*"
+	    setup_xfail "x86_64-*-linux*"
 	    shared_test shmpnp "shared (PIC main, non PIC so)" mainp.o sh1np.o sh2np.o shared
 	}
     } else {


	Jakub


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