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

Message ID 20210620233620.391576-3-hjl.tools@gmail.com
State Superseded
Headers
Series Implement single global definition marker |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

H.J. Lu June 20, 2021, 11:36 p.m. UTC
  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(-)
  

Comments

Andreas Schwab June 21, 2021, 7:31 a.m. UTC | #1
On Jun 20 2021, H.J. Lu via Libc-alpha wrote:

> 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

Please use a vanilla autoconf version.

Andreas.
  
Florian Weimer June 21, 2021, 7:43 a.m. UTC | #2
* H. J. Lu via Libc-alpha:

> 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)

I must say these numbers do not make sense to me.  Why do libc.so and
localedef data sizes increase with -fsingle-global-definition?  Fewer
copy relocations should *reduce* data size on both sides.  localedef
would have to have nearly 4,000 data relocations to account for the size
increase.  And shouldn't the GOT overlap with BSS anyway (so not even
show up in the data column)?

And I don't think we can build glibc with -fsingle-global-definition
anyway because it would be an ABI break.

> ---
>  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

Please regenerate with an unpatched autoconf.

Thanks,
Florian
  
H.J. Lu June 21, 2021, 12:49 p.m. UTC | #3
On Mon, Jun 21, 2021 at 12:43 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > 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)
>
> I must say these numbers do not make sense to me.  Why do libc.so and
> localedef data sizes increase with -fsingle-global-definition?  Fewer

I haven't investigated them in detail yet.  My main purposes were to
check if anything breaks.

> copy relocations should *reduce* data size on both sides.  localedef
> would have to have nearly 4,000 data relocations to account for the size
> increase.  And shouldn't the GOT overlap with BSS anyway (so not even
> show up in the data column)?

I will take a closer look.

> And I don't think we can build glibc with -fsingle-global-definition
> anyway because it would be an ABI break.

Correct.

> > ---
> >  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
>
> Please regenerate with an unpatched autoconf.
>

Will do.

Thanks.
  

Patch

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