Build: Change --enable-ifunc handling.
Some compilers support __attribute__((__ifunc__())) even though the dynamic linker does not. The compiler is able to create the binary but it will fail on startup. So it is not enough to just test if the attribute is supported. The default value for enable_ifunc is now auto, which will attempt to compile a program using __attribute__((__ifunc__())). There are additional checks in this program if glibc is being used or if it is running on FreeBSD. Setting --enable-ifunc will skip this test and always enable __attribute__((__ifunc__())), even if is not supported.
This commit is contained in:
parent
12b89bcc99
commit
ffb456593d
61
configure.ac
61
configure.ac
|
@ -869,15 +869,37 @@ fi
|
||||||
# implementations of the same function at runtime. This is slightly more
|
# implementations of the same function at runtime. This is slightly more
|
||||||
# efficient than using __attribute__((__constructor__)) and setting
|
# efficient than using __attribute__((__constructor__)) and setting
|
||||||
# a function pointer.
|
# a function pointer.
|
||||||
AC_ARG_ENABLE([ifunc], [AS_HELP_STRING([--disable-ifunc],
|
AC_ARG_ENABLE([ifunc], [AS_HELP_STRING([--enable-ifunc],
|
||||||
[do not use __attribute__((__ifunc__()))])],
|
[Use __attribute__((__ifunc__())). Enabled by default on
|
||||||
[], [enable_ifunc=yes])
|
GNU/Linux (glibc) and FreeBSD.])],
|
||||||
|
[], [enable_ifunc=auto])
|
||||||
|
|
||||||
if test "x$enable_ifunc" = xyes ; then
|
# When enable_ifunc is 'auto', allow the use of __attribute__((__ifunc__()))
|
||||||
|
# if compiler support is detected and we are building for GNU/Linux (glibc)
|
||||||
|
# or FreeBSD. uClibc and musl don't support ifunc in their dynamic linkers
|
||||||
|
# but some compilers still accept the attribute when compiling for these
|
||||||
|
# C libraries, which results in broken binaries. That's why we need to
|
||||||
|
# check which libc is being used.
|
||||||
|
if test "x$enable_ifunc" = xauto ; then
|
||||||
OLD_CFLAGS="$CFLAGS"
|
OLD_CFLAGS="$CFLAGS"
|
||||||
CFLAGS="$CFLAGS -Werror"
|
CFLAGS="$CFLAGS -Werror"
|
||||||
AC_MSG_CHECKING([if __attribute__((__ifunc__())) can be used])
|
AC_MSG_CHECKING([if __attribute__((__ifunc__())) can be used])
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||||
|
/*
|
||||||
|
* Force a compilation error when not using glibc on Linux
|
||||||
|
* or if we are not using FreeBSD. uClibc will define
|
||||||
|
* __GLIBC__ but does not support ifunc, so we must have
|
||||||
|
* an extra check to disable with uClibc.
|
||||||
|
*/
|
||||||
|
#if defined(__linux__)
|
||||||
|
# include <features.h>
|
||||||
|
# if !defined(__GLIBC__) || defined(__UCLIBC__)
|
||||||
|
compile error
|
||||||
|
# endif
|
||||||
|
#elif !defined(__FreeBSD__)
|
||||||
|
compile error
|
||||||
|
#endif
|
||||||
|
|
||||||
static void func(void) { return; }
|
static void func(void) { return; }
|
||||||
static void (*resolve_func (void)) (void) { return func; }
|
static void (*resolve_func (void)) (void) { return func; }
|
||||||
void func_ifunc (void)
|
void func_ifunc (void)
|
||||||
|
@ -891,25 +913,30 @@ if test "x$enable_ifunc" = xyes ; then
|
||||||
void make_clang_quiet(void);
|
void make_clang_quiet(void);
|
||||||
void make_clang_quiet(void) { resolve_func()(); }
|
void make_clang_quiet(void) { resolve_func()(); }
|
||||||
]])], [
|
]])], [
|
||||||
AC_DEFINE([HAVE_FUNC_ATTRIBUTE_IFUNC], [1],
|
enable_ifunc=yes
|
||||||
[Define to 1 if __attribute__((__ifunc__()))
|
|
||||||
is supported for functions.])
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
|
|
||||||
# ifunc explicitly does not work with -fsanitize=address.
|
|
||||||
# If configured, it will result in a liblzma build that
|
|
||||||
# will fail when liblzma is loaded at runtime (when the
|
|
||||||
# ifunc resolver executes).
|
|
||||||
AS_CASE([$CFLAGS], [*-fsanitize=*], [AC_MSG_ERROR([
|
|
||||||
CFLAGS contains '-fsanitize=' which is incompatible with ifunc.
|
|
||||||
Use --disable-ifunc when using '-fsanitize'.])])
|
|
||||||
], [
|
], [
|
||||||
AC_MSG_RESULT([no])
|
enable_ifunc=no
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_MSG_RESULT([$enable_ifunc])
|
||||||
|
|
||||||
CFLAGS="$OLD_CFLAGS"
|
CFLAGS="$OLD_CFLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$enable_ifunc" = xyes ; then
|
||||||
|
AC_DEFINE([HAVE_FUNC_ATTRIBUTE_IFUNC], [1],
|
||||||
|
[Define to 1 if __attribute__((__ifunc__()))
|
||||||
|
is supported for functions.])
|
||||||
|
|
||||||
|
# ifunc explicitly does not work with -fsanitize=address.
|
||||||
|
# If configured, it will result in a liblzma build that will fail
|
||||||
|
# when liblzma is loaded at runtime (when the ifunc resolver
|
||||||
|
# executes).
|
||||||
|
AS_CASE([$CFLAGS], [*-fsanitize=*], [AC_MSG_ERROR([
|
||||||
|
CFLAGS contains '-fsanitize=' which is incompatible with ifunc.
|
||||||
|
Use --disable-ifunc when using '-fsanitize'.])])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
|
|
Loading…
Reference in New Issue