x86: Set have-protected-data to no if unsupported

If the building compiler enables no direct external data access by
default, access to protected data in shared libraries from executables
must be compiled with no direct external data access.  If the testing
compiler doesn't support it, set have-protected-data to no to disable
the tests which requires no direct external data access.

Add LIBC_TRY_CC_COMMAND to test a building compiler option or options
with an input file.

This fixes BZ #33286.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
This commit is contained in:
H.J. Lu 2025-08-22 15:56:41 -07:00
parent aa4dbb2eeb
commit dd4394b249
4 changed files with 224 additions and 0 deletions

17
aclocal.m4 vendored
View File

@ -326,6 +326,23 @@ case "$prefix" in
;;
esac])
dnl Test a CC compiler option or options with an input file.
dnl LIBC_TRY_CC_COMMAND([message], [code], [options],
dnl [CC-cache-id], [CC-action-if-true], [CC-action-if-false])
AC_DEFUN([LIBC_TRY_CC_COMMAND],
[
cat > conftest.c <<EOF
$2
EOF
AC_CACHE_CHECK([$1], $4, [dnl
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $3 conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
then
[$5]
else
[$6]
fi])
rm -f conftest*])
dnl Run a test with TEST_CC.
dnl LIBC_CHECK_TEST_CC([commands])
AC_DEFUN([LIBC_CHECK_TEST_CC],

View File

@ -144,6 +144,12 @@ $(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so
| grep GLIBC_ABI_GNU2_TLS > $@; \
$(evaluate-test)
generated += check-gnu2-tls.out
ifneq (,$(test-cc-cflags-no-direct-extern-access))
CFLAGS-tst-protected1a.c += $(test-cc-cflags-no-direct-extern-access)
CFLAGS-tst-protected1b.c += $(test-cc-cflags-no-direct-extern-access)
CFLAGS-vismain.c += $(test-cc-cflags-no-direct-extern-access)
endif
endif
ifeq ($(subdir),gmon)

131
sysdeps/x86/configure vendored
View File

@ -213,6 +213,137 @@ CC="$saved_CC"
config_vars="$config_vars
have-test-cc-cflags-mfpmath-387 = $libc_cv_have_test_cc_cflags_mfpmath_387"
conftest_code="
extern int foo;
int *
foo_p (void)
{
return &foo;
}
"
cat > conftest.c <<EOF
$conftest_code
EOF
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if no direct extern access is enabled by default" >&5
printf %s "checking if no direct extern access is enabled by default... " >&6; }
if test ${libc_cv_cc_no_direct_extern_access+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -O2 -fno-pic conftest.c -o conftest 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
libc_cv_cc_cflags_no_direct_extern_access=no
if test "$base_machine" = x86_64; then
if grep -E -q "mov[lq][ ]+foo@GOTPCREL\(%rip\)," conftest; then
libc_cv_cc_no_direct_extern_access=yes
fi
elif test "$base_machine" = i386; then
if grep -E -q "movl[ ]+foo@GOT," conftest; then
libc_cv_cc_no_direct_extern_access=yes
fi
else
echo unsupported machine: $base_machine
rm -f conftest*
exit 1
fi
else
echo failed to check no direct external data access
rm -f conftest*
exit 1
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_no_direct_extern_access" >&5
printf "%s\n" "$libc_cv_cc_no_direct_extern_access" >&6; }
rm -f conftest*
saved_CC="$CC"
CC="$TEST_CC"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -mno-direct-extern-access works in testing" >&5
printf %s "checking if -mno-direct-extern-access works in testing... " >&6; }
if test ${libc_cv_test_cc_cflags_mno_direct_extern_access+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -mno-direct-extern-access -xc /dev/null -S -o /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then :
libc_cv_test_cc_cflags_mno_direct_extern_access=yes
else case e in #(
e) libc_cv_test_cc_cflags_mno_direct_extern_access=no
;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_cflags_mno_direct_extern_access" >&5
printf "%s\n" "$libc_cv_test_cc_cflags_mno_direct_extern_access" >&6; }
CC="$saved_CC"
saved_CC="$CC"
CC="$TEST_CC"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -fno-direct-access-external-data works in testing" >&5
printf %s "checking if -fno-direct-access-external-data works in testing... " >&6; }
if test ${libc_cv_test_cc_cflags_fno_direct_access_external_data+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -fno-direct-access-external-data -xc /dev/null -S -o /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then :
libc_cv_test_cc_cflags_fno_direct_access_external_data=yes
else case e in #(
e) libc_cv_test_cc_cflags_fno_direct_access_external_data=no
;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_cflags_fno_direct_access_external_data" >&5
printf "%s\n" "$libc_cv_test_cc_cflags_fno_direct_access_external_data" >&6; }
CC="$saved_CC"
if test $libc_cv_test_cc_cflags_mno_direct_extern_access = yes; then
libc_cv_test_cc_cflags_no_direct_extern_access="-mno-direct-extern-access"
elif test $libc_cv_test_cc_cflags_fno_direct_access_external_data = yes; then
libc_cv_test_cc_cflags_no_direct_extern_access="-fno-direct-access-external-data"
fi
config_vars="$config_vars
test-cc-cflags-no-direct-extern-access = $libc_cv_test_cc_cflags_no_direct_extern_access"
if test "${libc_cv_cc_no_direct_extern_access}${libc_cv_test_cc_cflags_no_direct_extern_access}" = yes; then
libc_cv_protected_data=no
fi
printf "%s\n" "#define SUPPORT_STATIC_PIE 1" >>confdefs.h

View File

@ -132,5 +132,75 @@ LIBC_TRY_TEST_CC_OPTION([if -mfpmath=387 works],
LIBC_CONFIG_VAR(have-test-cc-cflags-mfpmath-387,
$libc_cv_have_test_cc_cflags_mfpmath_387)
conftest_code="
extern int foo;
int *
foo_p (void)
{
return &foo;
}
"
dnl Check if CC enables no direct extern access by default.
LIBC_TRY_CC_COMMAND([if no direct extern access is enabled by default],
[$conftest_code],
[-S -O2 -fno-pic],
libc_cv_cc_no_direct_extern_access,
[
libc_cv_cc_cflags_no_direct_extern_access=no
if test "$base_machine" = x86_64; then
if grep -E -q "mov[lq][ ]+foo@GOTPCREL\(%rip\)," conftest; then
libc_cv_cc_no_direct_extern_access=yes
fi
elif test "$base_machine" = i386; then
if grep -E -q "movl[ ]+foo@GOT," conftest; then
libc_cv_cc_no_direct_extern_access=yes
fi
else
echo unsupported machine: $base_machine
rm -f conftest*
exit 1
fi
],
[
echo failed to check no direct external data access
rm -f conftest*
exit 1
])
dnl Check if TEST_CC supports -mno-direct-extern-access.
LIBC_TRY_TEST_CC_OPTION([if -mno-direct-extern-access works],
[-Werror -mno-direct-extern-access],
libc_cv_test_cc_cflags_mno_direct_extern_access,
[libc_cv_test_cc_cflags_mno_direct_extern_access=yes],
[libc_cv_test_cc_cflags_mno_direct_extern_access=no]
)
dnl Check if TEST_CC supports -fno-direct-access-external-data.
LIBC_TRY_TEST_CC_OPTION([if -fno-direct-access-external-data works],
[-Werror -fno-direct-access-external-data],
libc_cv_test_cc_cflags_fno_direct_access_external_data,
[libc_cv_test_cc_cflags_fno_direct_access_external_data=yes],
[libc_cv_test_cc_cflags_fno_direct_access_external_data=no]
)
if test $libc_cv_test_cc_cflags_mno_direct_extern_access = yes; then
libc_cv_test_cc_cflags_no_direct_extern_access="-mno-direct-extern-access"
elif test $libc_cv_test_cc_cflags_fno_direct_access_external_data = yes; then
libc_cv_test_cc_cflags_no_direct_extern_access="-fno-direct-access-external-data"
fi
LIBC_CONFIG_VAR(test-cc-cflags-no-direct-extern-access,
$libc_cv_test_cc_cflags_no_direct_extern_access)
dnl If the building compiler enables no direct external data access by
dnl default, access to protected data in shared libraries from executables
dnl must be compiled with no direct external data access. If the testing
dnl compiler doesn't support it, set have-protected-data to no to disable
dnl the tests which requires no direct external data access.
dnl
if test "${libc_cv_cc_no_direct_extern_access}${libc_cv_test_cc_cflags_no_direct_extern_access}" = yes; then
libc_cv_protected_data=no
fi
dnl Static PIE is supported.
AC_DEFINE(SUPPORT_STATIC_PIE)