[PATCH 2/4] Check -z single-global-definition and -fsingle-global-definition

H.J. Lu hjl.tools@gmail.com
Sun Jun 20 23:36:18 GMT 2021


1. Check linker support for -z single-global-definition.  If
GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION is set on any input
relocatable files:
  a. Don't generate copy relocations.
  b. Turn off extern_protected_data.
  c. Treate reference to protected symbols with single global definition
  as local.
  d. Set GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION on output.
  e. Add -z [no]single-global-definition to control single global
  definition.
2. Check compiler support for -fsingle-global-definition:
  a. Generate a single global definition marker in relocatable objects.
    i. Always use GOT to access undefined data and function symbols,
    including in PIE and non-PIE.  These will avoid copy relocations in
    executables.
    ii. This is compatible with existing executables and shared libraries.
  b. In executable and shared library, bind symbols with the STV_PROTECTED
     visibility locally:
    i. The address of data symbol is the address of data body.
    ii. For systems without function descriptor, the function pointer is
    the address of function body.
    iii. The resulting shared libraries may not be incompatible with
    executables which have copy relocations on protected symbols.

Size comparison of non-PIE builds with GCC 12 -O2:

1. On x86-64:
   text	   data	    bss	    dec	    hex	filename
 190218	   9672	    416	 200306	  30e72	ld.so (original)
 190258	   9336	    416	 200010	  30d4a ld.so (-fsingle-global-definition)
1917384	  20232	  52424	1990040	 1e5d98	libc.so (original)
1919946	  20240	  52432	1992618	 1e67aa	libc.so (-fsingle-global-definition)
 261734	  10339	    744	 272817	  429b1	localedef (original)
 233084	  41734	    648	 275466	  4340a	localedef (-fsingle-global-definition)
2. On i686:
   text	   data	    bss	    dec	    hex	filename
 199369	   6796	    212	 206377	  32629	ld.so (original)
 199381	   6796	    212	 206389	  32635 ld.so (-fsingle-global-definition)
2058080	  11136	  38856	2108072	 202aa8	libc.so (original)
2058092	  11136	  38856	2108084	 202ab4	libc.so (-fsingle-global-definition)
 276207	   9559	    552	 286318	  45e6e localedef (original)
 254249	  33734	    520	 288503	  466f7	localedef (-fsingle-global-definition)
---
 configure    | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 configure.ac | 37 ++++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 9619c10991..5844dad68f 100755
--- a/configure
+++ b/configure
@@ -732,6 +732,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -844,6 +845,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1096,6 +1098,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1233,7 +1244,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1386,6 +1397,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -5746,6 +5758,65 @@ fi
 $as_echo "$libc_cv_insert" >&6; }
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking -z single-global-definition" >&5
+$as_echo_n "checking -z single-global-definition... " >&6; }
+if ${libc_cv_z_single_global_definition+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+		__attribute__ ((visibility ("protected")))
+		void bar (void) {}
+		void *bar_p (void) { return &bar; }
+EOF
+		libc_cv_z_single_global_definition=no
+		if { ac_try='${CC-cc} -Wl,-z,single-global-definition
+			-nostdlib -nostartfiles $CFLAGS $CPPFLAGS $LDFLAGS
+			-fPIC -shared $no_ssp -o conftest.so conftest.c
+			1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+		  libc_cv_z_single_global_definition=yes
+		else
+		  libc_cv_z_single_global_definition=no
+		fi
+		rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_z_single_global_definition" >&5
+$as_echo "$libc_cv_z_single_global_definition" >&6; }
+config_vars="$config_vars
+have-z-single-global-definition = $libc_cv_z_single_global_definition"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fsingle-global-definition" >&5
+$as_echo_n "checking for -fsingle-global-definition... " >&6; }
+if ${libc_cv_fsingle_global_definition+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+int foo;
+EOF
+		if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S
+			-fsingle-global-definition
+			conftest.c 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+		  libc_cv_fsingle_global_definition=yes
+		else
+		  libc_cv_fsingle_global_definition=no
+		fi
+		rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_fsingle_global_definition" >&5
+$as_echo "$libc_cv_fsingle_global_definition" >&6; }
+config_vars="$config_vars
+have-fsingle-global-definition = $libc_cv_fsingle_global_definition"
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken __attribute__((alias()))" >&5
 $as_echo_n "checking for broken __attribute__((alias()))... " >&6; }
 if ${libc_cv_broken_alias_attribute+:} false; then :
diff --git a/configure.ac b/configure.ac
index 34ecbba540..26932812da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1222,6 +1222,43 @@ EOF
 	       ])
 AC_SUBST(libc_cv_insert)
 
+AC_CACHE_CHECK(-z single-global-definition,
+	       libc_cv_z_single_global_definition,
+	       [cat > conftest.c <<EOF
+		__attribute__ ((visibility ("protected")))
+		void bar (void) {}
+		void *bar_p (void) { return &bar; }
+EOF
+		libc_cv_z_single_global_definition=no
+		if AC_TRY_COMMAND([${CC-cc} -Wl,-z,single-global-definition
+			-nostdlib -nostartfiles $CFLAGS $CPPFLAGS $LDFLAGS
+			-fPIC -shared $no_ssp -o conftest.so conftest.c
+			1>&AS_MESSAGE_LOG_FD]); then
+		  libc_cv_z_single_global_definition=yes
+		else
+		  libc_cv_z_single_global_definition=no
+		fi
+		rm -f conftest.*
+	       ])
+LIBC_CONFIG_VAR([have-z-single-global-definition],
+		[$libc_cv_z_single_global_definition])
+
+AC_CACHE_CHECK(for -fsingle-global-definition,
+	       libc_cv_fsingle_global_definition,
+	       [cat > conftest.c <<EOF
+int foo;
+EOF
+		if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S
+			-fsingle-global-definition
+			conftest.c 1>&AS_MESSAGE_LOG_FD]); then
+		  libc_cv_fsingle_global_definition=yes
+		else
+		  libc_cv_fsingle_global_definition=no
+		fi
+		rm -f conftest*])
+LIBC_CONFIG_VAR([have-fsingle-global-definition],
+		[$libc_cv_fsingle_global_definition])
+
 AC_CACHE_CHECK(for broken __attribute__((alias())),
 	       libc_cv_broken_alias_attribute,
 	       [cat > conftest.c <<EOF
-- 
2.31.1



More information about the Libc-alpha mailing list