[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patches] Make --disable-versioning work in EGLIBC



Joseph S. Myers wrote:
On Thu, 7 May 2009, Maxim Kuvyrkov wrote:

The patch was tested on ARM, MIPS and PowerPC with no regressions and on x86
with 2 regressions (I'm looking into these).

A key piece of testing would be to build for a few platforms in the default (versioning enabled) case and make sure that exactly the same symbols are exported, at the same versions, before and after the patch, and that the test results in the default case are also unchanged by the patch.

Hi Joseph,

Below is updated patch to make --disable-versioning work. I've spent quite some time on verifying and fixing various discrepancies in symbols between EGLIBC built without symbol versions and compatibility code and the default configuration. The attached patch was tested on ARM, IA32, MIPS and PowerPC without any unexpected differences in symbols or symbol attributes.

OK for trunk?  In normal configuration all changes evaluate to no-op.

To compare exported API of the libraries I used the attached AWK script (to compare two files) and shell script (to compare 2 build or install directories) to automate the process.

The remaining differences in API are the following ('Missing' means that the default configuration provides the symbol, but --disable-versioning configuration does not):

In libc.so:

1. Missing GCC_3.* and GLIBC_2.* symbols. These symbols are missing for obvious reasons of not using symbol versioning (*).

(*) There is suggestion to include in --disable-versioning configuration a singly GLIBC_2.X symbol to provide applications version of the GLIBC API the library provides.

2. Missing
_IO_stderr_
_IO_stdin_
_IO_stdout_

These symbols defined under SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1).

3. Missing on several architectures
__deregister_frame_info_bases
__deregister_frame_info
__deregister_frame
__register_frame_info_bases
__register_frame_info
__register_frame_info_table_bases
__register_frame_info_table
__register_frame
__register_frame_table
_Unwind_Find_FDE

These symbols are defined under SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2_5).

4. Missing re_max_failures. This symbol is defined under SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3).

5. Missing on PowerPC only
__novmx__libc_siglongjmp
__novmx__libc_longjmp

These symbols defined under SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4).


In libresolv.so:

6. Missing
dn_expand
res_query
res_mkquery
res_querydomain
res_search

These symbols are defined under SHLIB_COMPAT (GLIBC_2_0, GLIBC_2_2).

6. Different attributes on symbols
_res
__divdi3
__moddi3
__udivdi3
__umoddi3

These symbols are provided only at GLIBC_2.0, without default version. It seems to me that the closest thing in non-versioning case is to make their visibility hidden. This is what invisible_compat_symbol() macro does.

--
Maxim K.
CodeSourcery
2009-05-07  Maxim Kuvyrkov  <maxim@xxxxxxxxxxxxxxxx>

	Make --disable-versioning work.

	* scripts/versions.awk (versioning): New parameter, don't output
	version information if it is defined to 'no'.
	* include/shlib-compat.h (IS_IN_libc, versioned_symbol),
	(versioned_symbol_1): Define when !DO_VERSIONING.
	(invisible_compat_symbol): Define, instead of compat_symbol when
	appropriate.
	* include/libc-symbols.h (default_symbol_version): Define when
	!DO_VERSIONING.
	(versioned_weak): Define.
	* Makerules: Generate version maps when !DO_VERSIONING to properly
	set symbol binding.
	(abi_versions_file): Define, use instead of abi-versions.h.
	(libc_gcclibs): Define, link against libgcc_eh when !DO_VERSIONING.
	* extra-lib.mk, elf/Makefile: Update, handle --disable-versioning.
	* elf/do-rel.h: Handle !DO_VERSIONING.

	* sysdeps/powerpc/powerpc32/dl-machine.c: Don't error when
	!DO_VERSIONING.
	* sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h: Define stuff when
	!DO_VERSIONING.
	* nptl/pthread_kill_other_threads.c (compat_symbol): Surround with
	ifdef DO_VERSIONING.
	* sysdeps/wordsize-32/divdi3.c: Use invisible_compat_symbol.
	* nptl/Makefile (tst-_res1): Disable test when !DO_VERSIONING.
	
	* sysdeps/powerpc/longjmp.c (_longjmp, longjmp, siglongjmp): Update.
	* sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h (ldbl_weak_alias): Update.
	* sysdeps/ieee754/ldbl-128ibm/s_isinfl.c (__isinfl): Update.
	* sysdeps/ieee754/ldbl-128ibm/s_finitel.c (finitel): Update.
	* sysdeps/ieee754/ldbl-128ibm/s_isnanl.c (__isnanl): Update.
	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (wcstold_l, strtold_l):
	Update.
	
Index: scripts/versions.awk
===================================================================
--- scripts/versions.awk	(revision 8445)
+++ scripts/versions.awk	(working copy)
@@ -6,6 +6,7 @@
 # defsfile		name of Versions.def file
 # buildroot		name of build directory with trailing slash
 # move_if_change	move-if-change command
+# versioning            "yes", if symbol versioning is being used
 
 # Read definitions for the versions.
 BEGIN {
@@ -67,7 +68,10 @@ BEGIN {
   sortver=actver
   # Ensure GLIBC_ versions come always first
   sub(/^GLIBC_/," GLIBC_",sortver)
-  printf("%s %s %s\n", actlib, sortver, $0) | sort;
+  if (versioning == "yes") printf("%s %s %s\n", actlib, sortver, $0) | sort;
+  # When not using symbol versioning, assign all symbols non-existent GLIBC
+  # version 1.1; this will allow us to make all necessary symbols global.
+  else printf("%s GLIBC_1.1 %s\n", actlib, $0) | sort;
 }
 
 
@@ -81,7 +85,7 @@ function closeversion(name, oldname) {
   # or FOO_x and FOO_y but not GLIBC_x and FOO_y.
   pfx = oldname;
   sub(/[0-9.]+/,".+",pfx);
-  if (oldname == "" || name !~ pfx) print "};" > outfile;
+  if (oldname == "" || name !~ pfx || versioning != "yes") print "};" > outfile;
   else printf("} %s;\n", oldname) > outfile;
 }
 
@@ -121,7 +125,10 @@ END {
 	closeversion(oldver, veryoldver);
 	veryoldver = oldver;
       }
-      printf("%s {\n  global:\n", $2) > outfile;
+      if (versioning == "yes") printf("%s {\n  global:\n", $2) > outfile;
+      # When not using symbol versioning, just output which symbols should be
+      # made global.
+      else print "{\n  global:\n" > outfile;
       oldver = $2;
     }
     printf("   ") > outfile;
Index: include/shlib-compat.h
===================================================================
--- include/shlib-compat.h	(revision 8445)
+++ include/shlib-compat.h	(working copy)
@@ -26,6 +26,36 @@
 #include <abi-versions.h>	/* header generated by abi-versions.awk */
 #endif
 
+#if defined HAVE_ELF && defined SHARED
+
+# ifndef NOT_IN_libc
+#  define IS_IN_libc 1
+# endif
+
+/* That header also defines symbols like `VERSION_libm_GLIBC_2_1' to
+   the version set name to use for e.g. symbols first introduced into
+   libm in the GLIBC_2.1 version.  Definitions of symbols with explicit
+   versions should look like:
+   	versioned_symbol (libm, new_foo, foo, GLIBC_2_1);
+   This will define the symbol `foo' with the appropriate default version,
+   i.e. either GLIBC_2.1 or the "earliest version" specified in
+   shlib-versions if that is newer.  */
+
+# define versioned_symbol(lib, local, symbol, version) \
+  versioned_symbol_1 (lib, local, symbol, version)
+# define versioned_symbol_1(lib, local, symbol, version) \
+  versioned_symbol_2 (local, symbol, VERSION_##lib##_##version)
+# define versioned_symbol_2(local, symbol, name) \
+  default_symbol_version (local, symbol, name)
+
+#else
+
+/* No versions to worry about, just make this the global definition.  */
+# define versioned_symbol(lib, local, symbol, version) \
+  weak_alias (local, symbol)
+
+#endif
+
 #if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
 
 /* The file abi-versions.h (generated by scripts/abi-versions.awk) defines
@@ -50,26 +80,6 @@
    && (!(ABI_##lib##_##obsoleted - 0)					      \
        || ((ABI_##lib##_##introduced - 0) < (ABI_##lib##_##obsoleted - 0))))
 
-# ifndef NOT_IN_libc
-#  define IS_IN_libc 1
-# endif
-
-/* That header also defines symbols like `VERSION_libm_GLIBC_2_1' to
-   the version set name to use for e.g. symbols first introduced into
-   libm in the GLIBC_2.1 version.  Definitions of symbols with explicit
-   versions should look like:
-   	versioned_symbol (libm, new_foo, foo, GLIBC_2_1);
-   This will define the symbol `foo' with the appropriate default version,
-   i.e. either GLIBC_2.1 or the "earliest version" specified in
-   shlib-versions if that is newer.  */
-
-# define versioned_symbol(lib, local, symbol, version) \
-  versioned_symbol_1 (lib, local, symbol, version)
-# define versioned_symbol_1(lib, local, symbol, version) \
-  versioned_symbol_2 (local, symbol, VERSION_##lib##_##version)
-# define versioned_symbol_2(local, symbol, name) \
-  default_symbol_version (local, symbol, name)
-
 # define compat_symbol(lib, local, symbol, version) \
   compat_symbol_1 (lib, local, symbol, version)
 # define compat_symbol_1(lib, local, symbol, version) \
@@ -77,18 +87,24 @@
 # define compat_symbol_2(local, symbol, name) \
   symbol_version (local, symbol, name)
 
+/* This macro is used to provide a versioned-only only symbol
+   which is otherwise invisible at link time.  */
+# define invisible_compat_symbol(lib, symbol, version) \
+  compat_symbol (lib, symbol, symbol, version)
+
 #else
 
 /* Not compiling ELF shared libraries at all, so never any old versions.  */
 # define SHLIB_COMPAT(lib, introduced, obsoleted)	0
 
-/* No versions to worry about, just make this the global definition.  */
-# define versioned_symbol(lib, local, symbol, version) \
-  weak_alias (local, symbol)
-
 /* This should not appear outside `#if SHLIB_COMPAT (...)'.  */
 # define compat_symbol(lib, local, symbol, version) ...
 
+# if defined HAVE_ELF && defined SHARED
+#  define invisible_compat_symbol(lib, symbol, version)	\
+  extern __typeof (symbol) symbol attribute_hidden;
+# endif
+
 #endif
 
 
Index: include/libc-symbols.h
===================================================================
--- include/libc-symbols.h	(revision 8445)
+++ include/libc-symbols.h	(working copy)
@@ -447,10 +447,31 @@ for linking")
      __asm__ (".symver " #real "," #name "@@" #version)
 #  endif
 # endif
-#else
+# define versioned_weak /* nothing */
+#else /* !DO_VERSIONING */
+
 # define symbol_version(real, name, version)
-# define default_symbol_version(real, name, version) \
-  strong_alias(real, name)
+# ifdef __ASSEMBLER__
+#  define default_symbol_version(real, name, version) \
+  strong_alias (real, name)
+# else
+/* We can't use simple strong_alias in C here due to
+   symbols defined with hidden_def and company.
+   As you see above, symbol versions are output in plain assembly,
+   so, to archieve the same effect, we use __asm__ (#name).
+
+   Define an alias to REAL with C name __FI_##NAME and
+   asm name NAME.  We use __FI_* namespace to fill a gap
+   between __EI_* and __GI_* namespaces.  */
+#  define default_symbol_version(real, name, version) \
+  extern __typeof (real) __FI_##name __asm__ (#name); \
+  extern __typeof (real) __FI_##name __attribute__((alias (#real)))
+# endif
+/* When not using symbol versioning we use an equivalent of
+   strong_alias to define a symbol; hence add __attribute__((weak))
+   to make it weak instead.  When using .symver, this is not necessary
+   as .symver handles weakness properly.  */
+# define versioned_weak __attribute__((weak))
 #endif
 
 #if defined SHARED || defined LIBC_NONSHARED
@@ -561,7 +582,7 @@ for linking")
    versioned_symbol (libc, __real_foo, foo, GLIBC_2_1);
    libc_hidden_ver (__real_foo, foo)  */
 
-#if defined SHARED && defined DO_VERSIONING && !defined NO_HIDDEN
+#if defined SHARED && !defined NO_HIDDEN
 # ifndef __ASSEMBLER__
 #  define __hidden_proto_hiddenattr(attrs...) \
   __attribute__ ((visibility ("hidden"), ##attrs))
Index: sysdeps/powerpc/powerpc32/dl-machine.c
===================================================================
--- sysdeps/powerpc/powerpc32/dl-machine.c	(revision 8445)
+++ sysdeps/powerpc/powerpc32/dl-machine.c	(working copy)
@@ -33,9 +33,10 @@ extern int __cache_line_size attribute_h
 /* Because ld.so is now versioned, these functions can be in their own file;
    no relocations need to be done to call them.
    Of course, if ld.so is not versioned...  */
+/* eglibc: This does work without symbol versioning.
 #if defined SHARED && !(DO_VERSIONING - 0)
 #error This will not work with versioning turned off, sorry.
-#endif
+#endif */
 
 
 /* Stuff for the PLT.  */
Index: sysdeps/powerpc/longjmp.c
===================================================================
--- sysdeps/powerpc/longjmp.c	(revision 8445)
+++ sysdeps/powerpc/longjmp.c	(working copy)
@@ -57,6 +57,6 @@ weak_alias (__vmx__libc_siglongjmp, __vm
 
 default_symbol_version (__vmx__libc_longjmp, __libc_longjmp, GLIBC_PRIVATE);
 default_symbol_version (__vmx__libc_siglongjmp, __libc_siglongjmp, GLIBC_PRIVATE);
-default_symbol_version (__vmx_longjmp, _longjmp, GLIBC_2.3.4);
-default_symbol_version (__vmxlongjmp, longjmp, GLIBC_2.3.4);
-default_symbol_version (__vmxsiglongjmp, siglongjmp, GLIBC_2.3.4);
+default_symbol_version (__vmx_longjmp, _longjmp, GLIBC_2.3.4) versioned_weak;
+default_symbol_version (__vmxlongjmp, longjmp, GLIBC_2.3.4) versioned_weak;
+default_symbol_version (__vmxsiglongjmp, siglongjmp, GLIBC_2.3.4) versioned_weak;
Index: sysdeps/wordsize-32/divdi3.c
===================================================================
--- sysdeps/wordsize-32/divdi3.c	(revision 8445)
+++ sysdeps/wordsize-32/divdi3.c	(working copy)
@@ -335,10 +335,10 @@ strong_alias (__umoddi3, __umoddi3_inter
 
 /* We declare these with compat_symbol so that they are not visible at
    link time.  Programs must use the functions from libgcc.  */
-#if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
+#if defined HAVE_ELF && defined SHARED
 # include <shlib-compat.h>
-compat_symbol (libc, __divdi3, __divdi3, GLIBC_2_0);
-compat_symbol (libc, __moddi3, __moddi3, GLIBC_2_0);
-compat_symbol (libc, __udivdi3, __udivdi3, GLIBC_2_0);
-compat_symbol (libc, __umoddi3, __umoddi3, GLIBC_2_0);
+invisible_compat_symbol (libc, __divdi3, GLIBC_2_0);
+invisible_compat_symbol (libc, __moddi3, GLIBC_2_0);
+invisible_compat_symbol (libc, __udivdi3, GLIBC_2_0);
+invisible_compat_symbol (libc, __umoddi3, GLIBC_2_0);
 #endif
Index: sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h
===================================================================
--- sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h	(revision 8445)
+++ sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h	(working copy)
@@ -10,14 +10,15 @@
   SHLIB_COMPAT(lib, introduced, LONG_DOUBLE_COMPAT_VERSION)
 #define long_double_symbol(lib, local, symbol) \
   long_double_symbol_1 (lib, local, symbol, LONG_DOUBLE_COMPAT_VERSION)
-#if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
+#if defined HAVE_ELF && defined SHARED
 # define ldbl_hidden_def(local, name) libc_hidden_ver (local, name)
 # define ldbl_strong_alias(name, aliasname) \
   strong_alias (name, __GL_##name##_##aliasname) \
   long_double_symbol (libc, __GL_##name##_##aliasname, aliasname);
 # define ldbl_weak_alias(name, aliasname) \
-  weak_alias (name, __GL_##name##_##aliasname) \
-  long_double_symbol (libc, __GL_##name##_##aliasname, aliasname);
+  weak_alias (name, __GL_##name##_##aliasname)				\
+  long_double_symbol (libc, __GL_##name##_##aliasname, aliasname)	\
+  versioned_weak;
 # define long_double_symbol_1(lib, local, symbol, version) \
   versioned_symbol (lib, local, symbol, version)
 #elif defined HAVE_WEAK_SYMBOLS
Index: sysdeps/ieee754/ldbl-128ibm/s_isinfl.c
===================================================================
--- sysdeps/ieee754/ldbl-128ibm/s_isinfl.c	(revision 8445)
+++ sysdeps/ieee754/ldbl-128ibm/s_isinfl.c	(working copy)
@@ -31,5 +31,5 @@ hidden_ver (___isinfl, __isinfl)
 #ifndef IS_IN_libm
 weak_alias (___isinfl, ____isinfl)
 long_double_symbol (libc, ___isinfl, isinfl);
-long_double_symbol (libc, ____isinfl, __isinfl);
+long_double_symbol (libc, ____isinfl, __isinfl) versioned_weak;
 #endif
Index: sysdeps/ieee754/ldbl-128ibm/s_finitel.c
===================================================================
--- sysdeps/ieee754/ldbl-128ibm/s_finitel.c	(revision 8445)
+++ sysdeps/ieee754/ldbl-128ibm/s_finitel.c	(working copy)
@@ -37,9 +37,9 @@ ___finitel (long double x)
 hidden_ver (___finitel, __finitel)
 weak_alias (___finitel, ____finitel)
 #ifdef IS_IN_libm
-long_double_symbol (libm, ____finitel, finitel);
+long_double_symbol (libm, ____finitel, finitel) versioned_weak;
 long_double_symbol (libm, ___finitel, __finitel);
 #else
-long_double_symbol (libc, ____finitel, finitel);
+long_double_symbol (libc, ____finitel, finitel) versioned_weak;
 long_double_symbol (libc, ___finitel, __finitel);
 #endif
Index: sysdeps/ieee754/ldbl-128ibm/s_isnanl.c
===================================================================
--- sysdeps/ieee754/ldbl-128ibm/s_isnanl.c	(revision 8445)
+++ sysdeps/ieee754/ldbl-128ibm/s_isnanl.c	(working copy)
@@ -39,5 +39,5 @@ hidden_ver (___isnanl, __isnanl)
 #ifndef IS_IN_libm
 weak_alias (___isnanl, ____isnanl)
 long_double_symbol (libc, ___isnanl, isnanl);
-long_double_symbol (libc, ____isnanl, __isnanl);
+long_double_symbol (libc, ____isnanl, __isnanl) versioned_weak;
 #endif
Index: sysdeps/ieee754/ldbl-128ibm/strtold_l.c
===================================================================
--- sysdeps/ieee754/ldbl-128ibm/strtold_l.c	(revision 8445)
+++ sysdeps/ieee754/ldbl-128ibm/strtold_l.c	(working copy)
@@ -58,11 +58,11 @@ libc_hidden_proto (STRTOF)
 # include <math_ldbl_opt.h>
 # ifdef USE_WIDE_CHAR
 weak_alias (____new_wcstold_l, ___new_wcstold_l);
-long_double_symbol (libc, ___new_wcstold_l, wcstold_l);
+long_double_symbol (libc, ___new_wcstold_l, wcstold_l) versioned_weak;
 long_double_symbol (libc, ____new_wcstold_l, __wcstold_l);
 # else
 weak_alias (____new_strtold_l, ___new_strtold_l);
-long_double_symbol (libc, ___new_strtold_l, strtold_l);
+long_double_symbol (libc, ___new_strtold_l, strtold_l) versioned_weak;
 long_double_symbol (libc, ____new_strtold_l, __strtold_l);
 # endif
 #endif
Index: Makerules
===================================================================
--- Makerules	(revision 8445)
+++ Makerules	(working copy)
@@ -106,6 +106,7 @@ $(common-objpfx)%.latest: $(common-objpf
 	sed -n '/ VERSION_$*_/{s/^.*_\([A-Z0-9_]*\).*$$/\1/;h;};$${g;p;}' \
 	    $(common-objpfx)abi-versions.h > $@T
 	mv -f $@T $@
+abi_versions_file := $(common-objpfx)abi-versions.h
 endif # avoid-generated
 endif # $(versioning) = yes
 
@@ -304,7 +305,9 @@ endif
 
 # Generate version maps, but wait until sysdep-subdirs is known
 ifeq ($(sysd-sorted-done),t)
-ifeq ($(versioning),yes)
+# eglibc: Even when not using symbol versioning we still need to generate
+# eglibc: version maps to make all the necessary symbols global.
+# eglibc: ifeq ($(versioning),yes)
 -include $(common-objpfx)sysd-versions
 $(addprefix $(common-objpfx),$(version-maps)): $(common-objpfx)sysd-versions
 common-generated += $(version-maps)
@@ -332,7 +335,7 @@ $(common-objpfx)Versions.all: $(..)scrip
 # See %.v/%.v.i implicit rules in Makeconfig.
 $(common-objpfx)Versions.v.i: $(wildcard $(subdirs:%=$(..)%/Versions)) \
 			      $(wildcard $(sysdirs:%=%/Versions)) \
-			      $(common-objpfx)abi-versions.h \
+			      $(abi_versions_file) \
 			      $(sysd-versions-force)
 $(common-objpfx)sysd-versions: $(common-objpfx)Versions.all \
 			       $(common-objpfx)Versions.v \
@@ -341,11 +344,12 @@ $(common-objpfx)sysd-versions: $(common-
 	  cat $(word 2,$^) \
 	  | LC_ALL=C $(AWK) -v buildroot=$(common-objpfx) -v defsfile=$< \
 			    -v move_if_change='$(move-if-change)' \
+			    -v versioning=$(versioning) \
 			    -f $(word 3,$^); \
 	) > $@T
 	mv -f $@T $@
 endif # avoid-generated
-endif # $(versioning) = yes
+# eglibc: endif # $(versioning) = yes
 endif # sysd-sorted-done
 
 # Generate .dT files as we compile.
@@ -439,12 +443,12 @@ ifeq (yes,$(build-shared))
 
 # Reference map file only when versioning is selected and a map file name
 # is given.
-ifeq ($(versioning),yes)
+# eglibc: ifeq ($(versioning),yes)
 map-file = $(firstword $($(@F:.so=-map)) \
 		       $(addprefix $(common-objpfx), \
 				   $(filter $(@F:.so=.map),$(version-maps))))
 load-map-file = $(map-file:%=-Wl,--version-script=%)
-endif
+# eglibc: endif
 
 # Pattern rule to build a shared object from an archive of PIC objects.
 # This must come after the installation rules so Make doesn't try to
@@ -615,16 +619,22 @@ ifeq ($(elf),yes)
 $(common-objpfx)libc_pic.os: $(common-objpfx)libc_pic.a
 	$(LINK.o) -nostdlib -nostartfiles -r -o $@ \
 	$(LDFLAGS-c_pic.os) -Wl,-d -Wl,--whole-archive $^
+ifneq ($(versioning),yes)
+# When EGLIBC is built without symbol versioning, local copy of
+# unwind-dw2-fde-glibc.c is not compiled, so we need to link against
+# libgcc_eh to get _Unwind_Find_FDE.
+libc_gcclibs := -lgcc_eh
+endif
 # Use our own special initializer and finalizer files for libc.so.
 $(common-objpfx)libc.so: $(elfobjdir)/soinit.os \
 			 $(common-objpfx)libc_pic.os \
 			 $(elfobjdir)/sofini.os \
 			 $(elfobjdir)/interp.os $(elfobjdir)/ld.so \
 			 $(common-objpfx)shlib.lds
-	$(build-shlib)
-ifeq ($(versioning),yes)
+	$(build-shlib) $(libc_gcclibs)
+# eglibc: ifeq ($(versioning),yes)
 $(common-objpfx)libc.so: $(common-objpfx)libc.map
-endif
+# eglibc: endif
 common-generated += libc.so libc_pic.os
 ifndef subdir
 install-extras := soinit.o sofini.o
Index: extra-lib.mk
===================================================================
--- extra-lib.mk	(revision 8445)
+++ extra-lib.mk	(working copy)
@@ -87,13 +87,13 @@ $(objpfx)$(patsubst %,$(libtype.oS),$(li
 	$(build-extra-lib)
 endif
 
-ifeq ($(versioning),yes)
+# eglibc: ifeq ($(versioning),yes)
 # Add the version script to the dependencies of the shared library.
 $(objpfx)$(lib).so: $(firstword $($(lib)-map) \
 				$(addprefix $(common-objpfx), \
 					    $(filter $(lib).map, \
 						     $(version-maps))))
-endif
+# eglibc: endif
 
 endif
 
Index: nptl/Makefile
===================================================================
--- nptl/Makefile	(revision 8445)
+++ nptl/Makefile	(working copy)
@@ -298,8 +298,13 @@ tests += tst-cancelx2 tst-cancelx3 tst-c
 	 tst-oncex3 tst-oncex4
 endif
 ifeq ($(build-shared),yes)
-tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
+tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-fini1 \
 	 tst-stackguard1
+ifeq ($(versioning),yes)
+# struct __res_state _res is only available with
+# symbol versioning after GLIBC_2.2.
+tests += tst-_res1
+endif
 tests-nolibpthread += tst-fini1
 ifeq ($(have-z-execstack),yes)
 tests += tst-execstack
Index: nptl/pthread_kill_other_threads.c
===================================================================
--- nptl/pthread_kill_other_threads.c	(revision 8445)
+++ nptl/pthread_kill_other_threads.c	(working copy)
@@ -32,6 +32,8 @@ void
 __pthread_kill_other_threads_np (void)
 {
 }
+# ifdef DO_VERSIONING
 compat_symbol (libpthread, __pthread_kill_other_threads_np,
 	       pthread_kill_other_threads_np, GLIBC_2_0);
+# endif
 #endif
Index: resolv/res_libc.c
===================================================================
--- resolv/res_libc.c	(revision 8445)
+++ resolv/res_libc.c	(working copy)
@@ -135,9 +135,9 @@ extern __thread struct __res_state *__li
 
 /* We declare this with compat_symbol so that it's not
    visible at link time.  Programs must use the accessor functions.  */
-#if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING
+#if defined HAVE_ELF && defined SHARED
 # include <shlib-compat.h>
-compat_symbol (libc, _res, _res, GLIBC_2_0);
+invisible_compat_symbol (libc, _res, GLIBC_2_0);
 #endif
 
 #include <shlib-compat.h>
Index: elf/Makefile
===================================================================
--- elf/Makefile	(revision 8445)
+++ elf/Makefile	(working copy)
@@ -110,9 +110,9 @@ before-compile  = $(objpfx)trusted-dirs.
 generated	:= trusted-dirs.h trusted-dirs.st for-renamed/renamed.so
 generated-dirs	:= for-renamed
 
-ifeq ($(versioning),yes)
+# eglibc: ifeq ($(versioning),yes)
 ld-map		= $(common-objpfx)ld.map
-endif
+# eglibc: endif
 
 ifeq (yes,$(build-shared))
 extra-objs	= $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os
Index: elf/do-rel.h
===================================================================
--- elf/do-rel.h	(revision 8445)
+++ elf/do-rel.h	(working copy)
@@ -104,7 +104,7 @@ elf_dynamic_do_rel (struct link_map *map
 	  for (; relative < r; ++relative)
 	    DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
 
-#ifdef RTLD_BOOTSTRAP
+#if defined RTLD_BOOTSTRAP && defined DO_VERSIONING
       /* The dynamic linker always uses versioning.  */
       assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
 #else
@@ -122,7 +122,7 @@ elf_dynamic_do_rel (struct link_map *map
 			       (void *) (l_addr + r->r_offset));
 	    }
 	}
-#ifndef RTLD_BOOTSTRAP
+#if !defined RTLD_BOOTSTRAP || !defined DO_VERSIONING
       else
 	for (; r < end; ++r)
 	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
# Expected input:
# (readelf -sW lib1 | cut -b 24- | sort -u; echo second file; \
#  readelf -sW lib2 | cut -b 24- | sort -u) | gawk -f this-script.awk

BEGIN {
    nfile = 1;
}

/^second file/ {
    nfile = 2;
}

/^(FUNC|OBJECT)/ {
    type = $1;
    bind = $2;
    vis = $3;
    value = $4;
    name = $5;

    if (bind == "LOCAL" || value == "UND")
	next;

    if (match (name, "@@")) {
	sub (/@@.+/, "", name);

	see = "ver";
    } else if (match (name, "@")) {
	next;
    } else
	see = "sym";

    if (nfile == 1) {
	if (seen[name] == see) {
	    printf ("%s\t%s\tduplicated symbol\n", name, see);
	    printf ("%s\t%s\t%s\t%s\n", name, types[name], binds[name],
		    viss[name]);
	    printf ("%s\t%s\t%s\t%s\n", name, type, bind, vis);
	    next;
	} else if (seen[name] != "" && (types[name] != type || binds[name] != bind || viss[name] != vis)) {
	    printf ("%s\tdefault version and symbol doesn't match\n", name);
	    printf ("%s\t%s\t%s\t%s\n", name, types[name], binds[name],
		    viss[name]);
	    printf ("%s\t%s\t%s\t%s\n", name, type, bind, vis);
	}
	
	if (seen[name] != "sym") {
	    seen[name] = see;
	    types[name] = type;
	    binds[name] = bind;
	    viss[name] = vis;
	}
    } else {
	if (seen[name] == "sym" || seen[name] == "ver") {
	    if (types[name] != type || binds[name] != bind || viss[name] != vis) {
		printf ("%s\tdis-ver mismatch\n", name);
		printf ("%s\t%s\t%s\t%s\n", name, types[name], binds[name],
			viss[name]);
		printf ("%s\t%s\t%s\t%s\n", name, type, bind, vis);
	    }
	} else
	    printf ("%s\textra symbol\n", name);

	seen2[name] = see;
    }
}

END {
    for (name in seen)
	if (seen2[name] != "sym" && seen2[name] != "ver")
	    printf ("%s\tmissing symbol\n", name);
}
#!/bin/sh

compare_syms () {
    (
	$readelf -sW $1 | cut -b 24- | sort -u
	echo second file
	$readelf -sW $2 | cut -b 24- | sort -u
	) | gawk -f ~/patch/eglibc-compare-api-dis-ver.awk
}

readelf=$1readelf
ar=$1ar
install1=$2
install2=$3

for i in `find $install1/ -name *.so -o \( -name *.a -a ! -name *_pic.a \)`; do
    lib=${i#$install1/}

    echo $lib: NEWLIBRARY

    lib1=$install1/$lib
    lib2=$install2/$lib

    case $lib1 in
	(*.a)
	if [ -h $lib1 ]; then
	    compare_syms $lib1 $lib2
	else
	    for j in `$ar t $lib1`; do
		echo $j: NEWFILE
		$ar p $lib1 $j > /tmp/maxim-testfoobar1
		$ar p $lib2 $j > /tmp/maxim-testfoobar2
		compare_syms /tmp/maxim-testfoobar1 /tmp/maxim-testfoobar2
	    done
	fi
	;;
	(*) compare_syms $lib1 $lib2 ;;
    esac
done