From 8973fb50f5b17296ae3bc8a06326dc7596565439 Mon Sep 17 00:00:00 2001
From: Michael Haubenwallner <michael.haubenwallner@salomon.at>
Date: Fri, 16 Mar 2012 14:49:20 +0100
Subject: [PATCH] AIX: Filename-based shlib versioning for libgcc_s

2012-10-30  Michael Haubenwallner  <michael.haubenwallner@salomon.at>

	(libgcc_s) Optional filename-based shared library versioning on AIX.
	* Makefile.in (enable_aix_soname): Define.
	* config/rs6000/t-slibgcc-aix: Implement filename-based versioning.
	* configure.in: Accept --enable-aix-soname argument.
	* configure: Recreate.
---
 libgcc/Makefile.in                 |    1 +
 libgcc/config/rs6000/t-slibgcc-aix |   79 +++++++++++++++++++++++++++++++-----
 libgcc/configure                   |   26 ++++++++++++
 libgcc/configure.ac                |   17 ++++++++
 4 files changed, 112 insertions(+), 11 deletions(-)

diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 43b14a0..b22e82b 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -41,6 +41,7 @@ long_double_type_size = @long_double_type_size@
 decimal_float = @decimal_float@
 enable_decimal_float = @enable_decimal_float@
 fixed_point = @fixed_point@
+enable_aix_soname = @enable_aix_soname@
 
 host_noncanonical = @host_noncanonical@
 target_noncanonical = @target_noncanonical@
diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix
index a0fdd13..79a6f1f 100644
--- a/libgcc/config/rs6000/t-slibgcc-aix
+++ b/libgcc/config/rs6000/t-slibgcc-aix
@@ -17,24 +17,81 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-# Build a shared libgcc library.
+# Build a shared libgcc library, with optional filename-based versioning:
+#
+# To get a different *filename* used at runtime than at linktime, instead of
+# the Shared Object we need to give an Import File to the linker, which allows
+# to define a different filename for runtime.
+#
+# Packing both the Import File and the Shared Object into one archive file
+# allows for a file layout similar to what is known on SVR4/Linux platforms -
+# having the unversioned library name as symlink to the versioned one, while
+# still keeping the AIX specific multilib variant of having both 32bit and
+# 64bit Shared Objects within one archive file possible, even if we do not
+# create such libraries (yet?).
+#
+# However, static linking of Shared Objects via an Import File does not work.
+# So as long as a library needs to be statically linkable, we want to use .so
+# as extension for the unversioned symlink, even if that will be used with
+# runtime-linking enabled (-brtl or -G linker flag) only.
+#
+# But as libgcc_s never is statically linked anyway, we can create libgcc_s.a
+# as symlink to libgcc_s.so.1 too (rendering the use of the .so extension as
+# best-practice template here).
+#
+# Use these configure arguments to control the filename-based versioning:
+#
+#   --disable-aix-soname
+#       Do not provide filename-based versioning for shared libgcc (default).
+#
+#   --enable-aix-soname
+#       Create shared libgcc with filename-based versioning, for both linking
+#       with and without AIX runtime-linking enabled.
+#
+# For the symbols listed in the Import File:
+# It would be important to specify their 'weak' attribute, but it turns out
+# that libgcc_s doesn't have weak symbols at all. So there is no need for
+# extra effort to identify weak symbols here.
 SHLIB_EXT = .a
-SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-	-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
+SHLIB_SOVERSION = 1
+SHLIB_SONAME = `test no != $(enable_aix_soname) && echo '@shlib_base_name@.so.$(SHLIB_SOVERSION)' || echo '@shlib_base_name@$(SHLIB_EXT)'`
+SHLIB_MEMBER = `case $(enable_aix_soname):@multilib_dir@ in no:*) echo 'shr' ;; *64*) echo 'shr_64' ;; *) echo 'shr' ;; esac`
+SHLIB_BITS   = `case @multilib_dir@ in *64*) echo '64' ;; *) echo '32' ;; esac`
+SHLIB_LINK = soname=$(SHLIB_SONAME) ; shr=$(SHLIB_MEMBER) ; imp= ; \
+	$(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+	-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/$$shr.o \
 	@multilib_flags@ @shlib_objs@ -lc \
 	`case @multilib_dir@ in \
 	*pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
 	*) echo -lc ;; esac` ; \
-	rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
-	$(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
-	@multilib_dir@/shr.o ; \
-	mv @multilib_dir@/tmp-@shlib_base_name@.a \
-	   @multilib_dir@/@shlib_base_name@.a ; \
-	rm -f @multilib_dir@/shr.o
+	if test no != $(enable_aix_soname); then \
+	  imp=@multilib_dir@/$$shr.imp ; \
+	  $(STRIP_FOR_TARGET) -X32_64 -e @multilib_dir@/$$shr.o ; \
+	  { echo "\#! $$soname($$shr.o)" ; \
+	    echo "\# $(SHLIB_BITS)" ; \
+	    cat @shlib_map_file@ ; \
+	  } > $$imp ; \
+	fi ; \
+	rm -f @multilib_dir@/tmp-$$soname ; \
+	$(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-$$soname \
+	  $$imp @multilib_dir@/$$shr.o ; \
+	mv @multilib_dir@/tmp-$$soname \
+	   @multilib_dir@/$$soname ; \
+	rm -f $$imp @multilib_dir@/$$shr.o ; \
+	if test no != $(enable_aix_soname); then \
+	  rm -f @multilib_dir@/@shlib_base_name@$(SHLIB_EXT) ; \
+	  $(LN_S) $$soname @multilib_dir@/@shlib_base_name@$(SHLIB_EXT) ; \
+	fi
 SHLIB_INSTALL = \
 	$(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
-	$(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
-		$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/
+	soname=$(SHLIB_SONAME) ; \
+	$(INSTALL_DATA) @multilib_dir@/$$soname \
+		$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \
+	if test no != $(enable_aix_soname) ; then \
+	  rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@$(SHLIB_EXT) ; \
+	  $(LN_S) $$soname \
+		  $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@$(SHLIB_EXT) ; \
+	fi
 SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
 SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
 SHLIB_MAPFILES = libgcc-std.ver
diff --git a/libgcc/configure b/libgcc/configure
index ed6eabf..361d772 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -608,6 +608,7 @@ build_os
 build_vendor
 build_cpu
 build
+enable_aix_soname
 enable_shared
 libgcc_topdir
 target_alias
@@ -655,6 +656,7 @@ with_target_subdir
 with_cross_host
 with_ld
 enable_shared
+enable_aix_soname
 enable_version_specific_runtime_libs
 with_slibdir
 enable_maintainer_mode
@@ -1288,6 +1290,7 @@ Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-shared        don't provide a shared libgcc
+  --enable-aix-soname     on AIX, do filename-based versioning for the shared libgcc
   --enable-version-specific-runtime-libs    Specify that runtime libraries should be installed in a compiler-specific directory
   --enable-maintainer-mode
                           enable make rules and dependencies not useful (and
@@ -2140,6 +2143,29 @@ fi
 
 
 
+# Check whether --enable-aix-soname was given.
+if test "${enable_aix_soname+set}" = set; then :
+  enableval=$enable_aix_soname;
+  case "${host}:${enable_shared}" in
+  powerpc*-*-aix[5-9]*:yes)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to do filename-based versioning for shared libgcc" >&5
+$as_echo_n "checking whether to do filename-based versioning for shared libgcc... " >&6; }
+    case ${enable_aix_soname} in
+    no) ;;
+    *) enable_aix_soname=yes ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_aix_soname" >&5
+$as_echo "$enable_aix_soname" >&6; }
+    ;;
+  *) enable_aix_soname=no ;;
+  esac
+
+else
+  enable_aix_soname=no
+fi
+
+
+
 # Make sure we can run config.sub.
 $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
   as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 8b7aba5..32b3e70 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -66,6 +66,23 @@ AC_ARG_ENABLE(shared,
 ], [enable_shared=yes])
 AC_SUBST(enable_shared)
 
+AC_ARG_ENABLE(aix-soname,
+[  --enable-aix-soname     on AIX, do filename-based versioning for the shared libgcc],
+[
+  case "${host}:${enable_shared}" in
+  powerpc*-*-aix[[5-9]]*:yes)
+    AC_MSG_CHECKING([whether to do filename-based versioning for shared libgcc])
+    case ${enable_aix_soname} in
+    no) ;;
+    *) enable_aix_soname=yes ;;
+    esac
+    AC_MSG_RESULT($enable_aix_soname)
+    ;;
+  *) enable_aix_soname=no ;;
+  esac
+], [enable_aix_soname=no])
+AC_SUBST(enable_aix_soname)
+
 GCC_PICFLAG
 AC_SUBST(PICFLAG)
 
-- 
1.7.3.4

