PATCH: Fix the oldest ABI

H. J. Lu hjl@lucon.org
Sat Nov 16 20:05:00 GMT 2002


Here is a patch to fix --enable-oldest-abi=ABI. I tested it on i686
with --enable-oldest-abi=2.2.3. The resulting libraries seem compatible
with glibc built without --enable-oldest-abi=2.2.3.


H.J.
-------------- next part --------------
2002-11-16  H.J. Lu  <hjl@gnu.org>

	* scripts/abi-versions.awk: Use gsub instead of sub.

2002-08-28  H.J. Lu  <hjl@gnu.org>

	* Makeconfig ($(common-objpfx)soversions.i): Add the default
	version and the oldest version.
	($(common-objpfx)soversions.mk): Updated.

	* Makerules ($(common-objpfx)abi-versions.h): Pass soversions.i
	to scripts/abi-versions.awk. Don't pass $(oldest_abi).
	($(common-objpfx)Versions.all): Updated for new soversions.i.
	($(common-objpfx)sysd-versions): Pass soversions.i to
	scripts/versions.awk.

	* scripts/abi-versions.awk: Remove oldest_abi. Take soversions.

	* scripts/versions.awk: Take soversions. Fix the oldest ABI
	support.

2002-08-23  H.J. Lu  <hjl@gnu.org>

	* sysdeps/unix/make-syscalls.sh: Support the oldest ABI.

	* sysdeps/unix/sysv/linux/i386/syscalls.list: Add GLIBC_2.2 as
	the current ABI for getrlimit and setrlimit.

--- libc/Makeconfig.oldest	Fri Nov 15 17:47:31 2002
+++ libc/Makeconfig	Sat Nov 16 11:13:46 2002
@@ -762,11 +762,15 @@ $(common-objpfx)shlib-versions.v.i: \
 						     $(add-ons) \
 						     $(subdirs)))
 $(common-objpfx)soversions.i: $(common-objpfx)shlib-versions.v
-	default_setname='$(filter-out %_default,$(oldest-abi:%=GLIBC_%))'; \
+	oldest_setname='$(filter-out %_default,$(oldest-abi:%=GLIBC_%))'; \
+	if test "x$$oldest_setname" = x; then \
+	  oldest_setname=default; \
+	fi; \
 	while read conf version setname; do \
 	  test -n "$$version" && \
 	  test `expr '$(config-machine)-$(config-vendor)-$(config-os)' \
 		     : "$$conf"` != 0 || continue; \
+	  default_setname=none; \
 	  if test "x$$version" = xDEFAULT; then \
 	    default_setname="$$setname"; \
 	  else \
@@ -775,13 +779,13 @@ $(common-objpfx)soversions.i: $(common-o
 	    if eval test -z "\$${versioned_$${lib}}"; then \
 	      eval versioned_$${lib}=yes; \
 	      number=`echo $$version | sed "s/^.*=//"`; \
-	      echo $$lib $$number $${setname:-$${default_setname}}; \
+	      echo $$lib $$number $${setname:-$${default_setname}} $$oldest_setname; \
 	    fi; \
 	  fi; \
 	done < $< > $@T; exit 0
 	mv -f $@T $@
 $(common-objpfx)soversions.mk: $(common-objpfx)soversions.i
-	(while read lib number setname; do \
+	(while read lib number default_setname oldest_setname; do \
 	   case $$number in \
 	     [0-9]*) echo "$$lib.so-version=.$$number"; \
 		     echo "all-sonames+=$$lib=$$lib.so\$$($$lib.so-version)";;\
--- libc/Makerules.oldest	Fri Nov 15 17:47:31 2002
+++ libc/Makerules	Sat Nov 16 11:13:46 2002
@@ -114,8 +114,10 @@ ifeq ($(versioning),yes)
 ifndef avoid-generated
 before-compile := $(common-objpfx)abi-versions.h $(before-compile)
 $(common-objpfx)abi-versions.h: $(..)scripts/abi-versions.awk \
+				$(common-objpfx)soversions.i \
 				$(common-objpfx)Versions.all
-	LC_ALL=C $(AWK) -v oldest_abi=$(oldest-abi) -f $^ > $@T
+	LC_ALL=C $(AWK) -v soversions=$(word 2,$^) \
+			-f $(word 1,$^) $(word 3,$^) > $@T
 	mv -f $@T $@
 
 $(common-objpfx)%.latest: $(common-objpfx)abi-versions.h
@@ -320,8 +322,8 @@ $(common-objpfx)Versions.def.v.i: $(..)V
 $(common-objpfx)Versions.all: $(..)scripts/firstversions.awk \
 			      $(common-objpfx)soversions.i \
 			      $(common-objpfx)Versions.def.v
-	{ while read lib version setname; do \
-	    test -z "$$setname" || echo "$$lib : $$setname"; \
+	{ while read lib version default_setname oldest_setname; do \
+	    test "$$default_setname" == none || echo "$$lib : $$default_setname"; \
 	  done < $(word 2,$^); \
 	  cat $(word 3,$^); \
 	} | LC_ALL=C $(AWK) -f $< > $@T
@@ -333,12 +335,14 @@ $(common-objpfx)Versions.v.i: $(wildcard
 			      $(sysd-versions-force)
 $(common-objpfx)sysd-versions: $(common-objpfx)Versions.all \
 			       $(common-objpfx)Versions.v \
+			       $(common-objpfx)soversions.i \
 			       $(..)scripts/versions.awk
 	( echo 'sysd-versions-subdirs = $(all-subdirs) $(config-sysdirs)' ; \
 	  cat $(word 2,$^) \
 	  | LC_ALL=C $(AWK) -v buildroot=$(common-objpfx) -v defsfile=$< \
+			    -v soversions=$(word 3,$^) \
 			    -v move_if_change='$(move-if-change)' \
-			    -f $(word 3,$^); \
+			    -f $(word 4,$^); \
 	) > $@T
 	mv -f $@T $@
 endif # avoid-generated
--- libc/scripts/abi-versions.awk.oldest	Wed Mar  7 08:57:54 2001
+++ libc/scripts/abi-versions.awk	Sat Nov 16 17:21:40 2002
@@ -2,12 +2,27 @@
 # See include/shlib-compat.h comments for explanation.
 
 # This script expects the following variables to be defined:
-# oldest_abi		the oldest ABI supported
+# soversions		name of soversions.i file.
 
 BEGIN {
   print "/* This file is automatically generated by abi-versions.awk.";
   print "   It defines symbols used by shlib-compat.h, which see.  */";
   print "\n#ifndef _ABI_VERSIONS_H\n#define _ABI_VERSIONS_H";
+  while (getline < soversions) {
+    lib=$1
+    version=$2
+    default_setname=$3
+    oldest_setname=$4
+    if (default_setname != "none") {
+      gsub(/[^A-Za-z0-9_ 	]/, "_", default_setname);
+      default_setnames [lib] = default_setname
+    }
+    if (oldest_setname != "default") { 
+      gsub(/[^A-Za-z0-9_ 	]/, "_", oldest_setname);
+      oldest_setnames [lib] = oldest_setname
+    }
+  }
+  close (soversions)
 }
 
 NF == 2 && $2 == "{" {
@@ -29,7 +44,22 @@ $2 == "=" {
   oldid = $1; newid = $3;
 
   printf "#define ABI_%s_%s\tABI_%s_%s\n", libid, oldid, libid, newid;
-  printf "#define VERSION_%s_%s\t%s\n", libid, oldid, new;
+  if (!oldest_setnames [libid]) {
+    # We don't have the oldest ABI defined. Rename it.
+    printf "#define VERSION_%s_%s\t%s\n", libid, oldid, new;
+  }
+  else {
+    # It is very tricky here. We have the oldest ABI defined. We need
+    # to figure out if we should change symbol version name or not.
+    if (default_setnames [libid] && default_setnames [libid] > oldid) {
+      # We rename the symbol version name only if the old version is
+      # older than the default.
+      printf "#define VERSION_%s_%s\t%s\n", libid, oldid, new;
+    }
+    else {
+      printf "#define VERSION_%s_%s\t%s\n", libid, oldid, old;
+    }
+  }
   next;
 }
 
@@ -40,9 +70,9 @@ $2 == "=" {
 
   printf "#define ABI_%s_%s\t%d\t/* support %s */\n", libid, versid, ++n, vers;
   printf "#define VERSION_%s_%s\t%s\n", libid, versid, vers;
-  if ("GLIBC_" oldest_abi == vers)
+  if (oldest_setnames [libid] == versid)
     start = 1;
-  if (start == 0 && oldest_abi != "default")
+  if (start == 0 && oldest_setnames [libid])
     --n;
   next;
 }
--- libc/scripts/versions.awk.oldest	Sat Apr  6 22:39:11 2002
+++ libc/scripts/versions.awk	Sat Nov 16 11:13:46 2002
@@ -4,22 +4,39 @@
 
 # This script expects the following variables to be defined:
 # defsfile		name of Versions.def file
+# soversions		name of soversions.i file.
 # buildroot		name of build directory with trailing slash
 # move_if_change	move-if-change command
 
 # Read definitions for the versions.
 BEGIN {
+  while (getline < soversions) {
+    lib=$1
+    version=$2
+    default_setname=$3
+    oldest_setname=$4
+    if (default_setname != "none") {
+      default_setnames [lib] = default_setname
+    }
+  }
+  close (soversions)
+
   nlibs=0;
   while (getline < defsfile) {
     if (/^[a-zA-Z0-9_.]+ \{/) {
       libs[$1] = 1;
       curlib = $1;
       while (getline < defsfile && ! /^}/) {
-      if ($2 == "=") {
+	if ($1 ~ /^GLIBC_[0-9]/)
+	  allglibcversions[$1] = 1
+	if ($2 == "=") {
 	  renamed[curlib "::" $1] = $3;
-      }
-	else
+	}
+	else {
 	  versions[$1] = 1;
+	  if ($1 ~ /^GLIBC_[0-9]/)
+	    supprtedglibcversions[$1] = 1
+	}
       }
     }
   }
@@ -27,6 +44,38 @@ BEGIN {
 
   tmpfile = buildroot "Versions.tmp";
   sort = "sort -n > " tmpfile;
+
+  # Sort all glibc versions.
+  numallglibcversions = 0;
+  for (v in allglibcversions) {
+    sortedallglibcversions[numallglibcversions] = v
+    numallglibcversions++;
+  }
+  for (i = 0; i < numallglibcversions; i++) {
+    for (j = i + 1; j < numallglibcversions; j++) {
+      if (sortedallglibcversions[i] > sortedallglibcversions[j]) {
+        t = sortedallglibcversions[j]
+	sortedallglibcversions[j] = sortedallglibcversions[i]
+	sortedallglibcversions[i] = t
+      }
+    }
+  }
+
+  # Sort supprted glibc versions.
+  numsupprtedglibcversions = 0;
+  for (v in supprtedglibcversions) {
+    sortedsupprtedglibcversions[numsupprtedglibcversions] = v
+    numsupprtedglibcversions++;
+  }
+  for (i = 0; i < numsupprtedglibcversions; i++) {
+    for (j = i + 1; j < numsupprtedglibcversions; j++) {
+      if (sortedsupprtedglibcversions[i] > sortedsupprtedglibcversions[j]) {
+        t = sortedsupprtedglibcversions[j]
+	sortedsupprtedglibcversions[j] = sortedsupprtedglibcversions[i]
+	sortedsupprtedglibcversions[i] = t
+      }
+    }
+  }
 }
 
 # Remove comment lines.
@@ -46,8 +95,17 @@ BEGIN {
 
 # This matches the beginning of a new version for the current library.
 /^  [A-Za-z_]/ {
-  if (renamed[actlib "::" $1])
-    actver = renamed[actlib "::" $1];
+  renamedver = renamed[actlib "::" $1];
+  if (renamedver) {
+    # We do rename only for the default version.
+    if (default_setnames [actlib] == renamedver) {
+      actver = renamedver
+    }
+    else {
+      firstver = renamedver
+      actver = $1;
+    }
+  }
   else if (!versions[$1]) {
     printf("version %s not defined for %s\n", $1, actlib) > "/dev/stderr";
     exit 1;
@@ -90,6 +148,74 @@ function close_and_move(name, real_name)
 # Now print the accumulated information.
 END {
   close(sort);
+
+  # First collect all the symbol information.
+  while (getline < tmpfile) {
+    lib = $1;
+    version = $2;
+    for (n = 3; n <= NF; ++n) {
+      symbol = $n;
+      sub (/;/, "", symbol);
+      symbols[lib, symbol, version] = 1;
+    }
+  }
+  close(tmpfile)
+
+  if (firstver) {
+    # Check versions in all libraries.
+    for (l in libs) {
+      last = ""
+      # For each symbol in all libraries.
+      for (combined in symbols) {
+	split(combined, separate, SUBSEP);
+	lib = separate[1]
+	# Check the current library.
+	if (lib != l)
+	  continue
+	# All symbols from the same library are consecutive.
+	if (last != "" && lib != l)
+	  break
+	# The first symbol in the library.
+	if (last == "")
+	  last = l
+	version = separate[3]
+	# Ignore none glibc versions and versions newer then the first
+	# version.
+	if (version !~ /^GLIBC_[0-9]/ || version >= firstver)
+	  continue;
+	symbol = separate[2]
+	# We check if there is any definition after the first version.
+	for (i = 0; i < numsupprtedglibcversions; i++) {
+	  v = sortedsupprtedglibcversions[i];
+	  if (symbols[lib, symbol, v]) {
+	    # Found one. Delete the previous version.
+	    delete symbols[lib, symbol, version]
+	    first = 1
+	    break
+	  }
+	}
+	if (i == numsupprtedglibcversions) {
+	  # We didn't found any definition after the first version. We
+	  # check if there are multiple definitions. We only keep the
+	  # latest one.
+	  last = numallglibcversions
+	  for (i = numallglibcversions - 1; i >= 0 ; i--) {
+	    v = sortedallglibcversions[i];
+	    if (symbols[lib, symbol, v]) {
+	      if (last != numallglibcversions) {
+		# Found an older version. Delete it.
+		delete symbols[lib, symbol, v]
+	      }
+	      else {
+		# Found the latest one before the first version.
+		last = i
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
   oldlib = "";
   oldver = "";
   printf("version-maps =");
@@ -116,8 +242,15 @@ END {
       oldver = $2;
     }
     printf("   ") > outfile;
+    lib = $1;
+    version = $2;
     for (n = 3; n <= NF; ++n) {
-      printf(" %s", $n) > outfile;
+      symbol = $n;
+      sub (/;/, "", symbol);
+      if (symbols[lib, symbol, version]) {
+	delete symbols[lib, symbol, version]
+	printf(" %s", $n) > outfile;
+      }
     }
     printf("\n") > outfile;
   }
--- libc/sysdeps/unix/make-syscalls.sh.oldest	Fri Nov 15 17:47:59 2002
+++ libc/sysdeps/unix/make-syscalls.sh	Sat Nov 16 11:13:46 2002
@@ -118,6 +118,23 @@ while read file srcfile caller syscall a
   echo "unix-syscalls += $file"
   test x$caller = x- || echo "unix-extra-syscalls += $file"
 
+  # Find the first verion and the version which obsoletes it. 
+  introduced=
+  obsoleted=
+  for name in $weak; do
+    name=`echo $name | sed 's/\./_/g'`
+    case $name in
+    *@@*)
+      ;;
+    *@*)
+      introduced=`echo $name | sed 's/.*@//'`
+      ;;
+    GLIBC_*)
+      obsoleted=$name
+      ;;
+    esac
+  done
+
   # Emit a compilation rule for this syscall.
   case $weak in
   *@*)
@@ -143,10 +160,17 @@ shared-only-routines += $file
   echo "\
 	\$(make-target-directory)
 	(echo '#include <sysdep.h>'; \\
+	 if test x != x"$introduced" && test x != x"$obsoleted"; then \\
+	   echo '#include <shlib-compat.h>'; \\
+	   echo '#if SHLIB_COMPAT (libc, $introduced, $obsoleted)'; \\
+	 fi; \\
 	 echo 'PSEUDO ($strong, $syscall, $nargs)'; \\
 	 echo '	ret'; \\
 	 echo 'PSEUDO_END($strong)'; \\
-	 echo 'libc_hidden_def ($strong)'; \\"
+	 echo 'libc_hidden_def ($strong)'; \\
+	 if test x != x"$introduced" && test x != x"$obsoleted"; then \\
+	   echo '#endif'; \\
+	 fi; \\"
   ;;
   esac
 
@@ -158,6 +182,8 @@ shared-only-routines += $file
 
   for name in $weak; do
     case $name in
+      GLIBC_*)
+	;;
       *@@*)
 	base=`echo $name | sed 's/@@.*//'`
 	ver=`echo $name | sed 's/.*@@//'`
--- libc/sysdeps/unix/sysv/linux/i386/syscalls.list.oldest	Tue Jul  4 10:44:33 2000
+++ libc/sysdeps/unix/sysv/linux/i386/syscalls.list	Sat Nov 16 11:13:46 2002
@@ -2,5 +2,5 @@
 
 modify_ldt	EXTRA	modify_ldt	i:ipi	__modify_ldt	modify_ldt
 vm86		-	vm86		i:p	__vm86		vm86
-oldgetrlimit	EXTRA	getrlimit	i:ip	__old_getrlimit	getrlimit@GLIBC_2.0
-oldsetrlimit	EXTRA	setrlimit	i:ip	__old_setrlimit	setrlimit@GLIBC_2.0
+oldgetrlimit	EXTRA	getrlimit	i:ip	__old_getrlimit	getrlimit@GLIBC_2.0 GLIBC_2.2
+oldsetrlimit	EXTRA	setrlimit	i:ip	__old_setrlimit setrlimit@GLIBC_2.0 GLIBC_2.2


More information about the Libc-alpha mailing list