[v2,2/4] Check -z indirect-extern-access and -fno-direct-extern-access

Message ID 20210624134938.2025098-3-hjl.tools@gmail.com
State Superseded
Headers
Series Implement indirect external access 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 24, 2021, 1:49 p.m. UTC
  1. Check linker support for -z indirect-extern-access.  If
GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS is set on any input
relocatable files:
  a. Don't generate copy relocations.
  b. Turn off extern_protected_data since it implies
     GNU_PROPERTY_NO_COPY_ON_PROTECTED.
  c. Treate reference to protected symbols with indirect external access
     as local.
  d. Set GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS on output.
  e. When generating executable, clear this bit when there are non-GOT
     or non-PLT relocations in input relocatable files without the bit set.
  f. Add -z [no]indirect-extern-access to control indirect external access.
2. Check compiler support for -fno-direct-extern-access:
  a. Generate an indirect external access 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
 189958	   9304	    416	 199678	  30bfe	ld.so (original)
 189974	   9304	    416	 199694	  30c0e ld.so (-fno-direct-extern-access)
1922458	  20240	  52432	1995130	 1e717a	libc.so (original)
1922474	  20240	  52432	1995146	 1e718a	libc.so (-fno-direct-extern-access)
  49321	   1363	    192	  50876	   c6bc iconv_prog (original)
  47053	   3638	    120	  50811	   c67b	iconv_prog (-fno-direct-extern-access)
 261978	  10339	    744	 273061	  42aa5	localedef (original)
 233344	  41734	    648	 275726	  4350e	localedef (-fno-direct-extern-access)

The size difference in localedef mainly comes from .data.rel.ro
 .data.rel.ro  0x000005	 (original)
 .data.rel.ro  0x007a88  (-fno-direct-extern-access)

For example, with -fno-direct-extern-access, localedef.o has 172
relocation entries against section '.rela.data.rel.ro.local' vs none
without -fno-direct-extern-access.
---
 configure    | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac | 37 ++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)
  

Patch

diff --git a/configure b/configure
index 9619c10991..093c59e25e 100755
--- a/configure
+++ b/configure
@@ -5746,6 +5746,65 @@  fi
 $as_echo "$libc_cv_insert" >&6; }
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking -z indirect-extern-access" >&5
+$as_echo_n "checking -z indirect-extern-access... " >&6; }
+if ${libc_cv_z_indirect_extern_access+:} 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_indirect_extern_access=no
+		if { ac_try='${CC-cc} -Wl,-z,indirect-extern-access
+			-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_indirect_extern_access=yes
+		else
+		  libc_cv_z_indirect_extern_access=no
+		fi
+		rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_z_indirect_extern_access" >&5
+$as_echo "$libc_cv_z_indirect_extern_access" >&6; }
+config_vars="$config_vars
+have-z-indirect-extern-access = $libc_cv_z_indirect_extern_access"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fno-direct-extern-access" >&5
+$as_echo_n "checking for -fno-direct-extern-access... " >&6; }
+if ${libc_cv_fno_direct_extern_access+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+int foo;
+EOF
+		if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S
+			-fno-direct-extern-access
+			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_fno_direct_extern_access=yes
+		else
+		  libc_cv_fno_direct_extern_access=no
+		fi
+		rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_fno_direct_extern_access" >&5
+$as_echo "$libc_cv_fno_direct_extern_access" >&6; }
+config_vars="$config_vars
+have-fno-direct-extern-access = $libc_cv_fno_direct_extern_access"
+
 { $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..195abe0827 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1222,6 +1222,43 @@  EOF
 	       ])
 AC_SUBST(libc_cv_insert)
 
+AC_CACHE_CHECK(-z indirect-extern-access,
+	       libc_cv_z_indirect_extern_access,
+	       [cat > conftest.c <<EOF
+		__attribute__ ((visibility ("protected")))
+		void bar (void) {}
+		void *bar_p (void) { return &bar; }
+EOF
+		libc_cv_z_indirect_extern_access=no
+		if AC_TRY_COMMAND([${CC-cc} -Wl,-z,indirect-extern-access
+			-nostdlib -nostartfiles $CFLAGS $CPPFLAGS $LDFLAGS
+			-fPIC -shared $no_ssp -o conftest.so conftest.c
+			1>&AS_MESSAGE_LOG_FD]); then
+		  libc_cv_z_indirect_extern_access=yes
+		else
+		  libc_cv_z_indirect_extern_access=no
+		fi
+		rm -f conftest.*
+	       ])
+LIBC_CONFIG_VAR([have-z-indirect-extern-access],
+		[$libc_cv_z_indirect_extern_access])
+
+AC_CACHE_CHECK(for -fno-direct-extern-access,
+	       libc_cv_fno_direct_extern_access,
+	       [cat > conftest.c <<EOF
+int foo;
+EOF
+		if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S
+			-fno-direct-extern-access
+			conftest.c 1>&AS_MESSAGE_LOG_FD]); then
+		  libc_cv_fno_direct_extern_access=yes
+		else
+		  libc_cv_fno_direct_extern_access=no
+		fi
+		rm -f conftest*])
+LIBC_CONFIG_VAR([have-fno-direct-extern-access],
+		[$libc_cv_fno_direct_extern_access])
+
 AC_CACHE_CHECK(for broken __attribute__((alias())),
 	       libc_cv_broken_alias_attribute,
 	       [cat > conftest.c <<EOF