]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
Build: Change --enable-ifunc handling.
authorJia Tan <jiat0218@gmail.com>
Tue, 21 Nov 2023 12:56:55 +0000 (20:56 +0800)
committerJia Tan <jiat0218@gmail.com>
Thu, 30 Nov 2023 12:04:42 +0000 (20:04 +0800)
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.

configure.ac

index 1fe6101675b2b67cac8fc091463da6dfc8cb81ff..cdd72a9ffd1cfc6b39af91b5509022c9a505a27b 100644 (file)
@@ -869,15 +869,37 @@ fi
 # implementations of the same function at runtime. This is slightly more
 # efficient than using __attribute__((__constructor__)) and setting
 # a function pointer.
-AC_ARG_ENABLE([ifunc], [AS_HELP_STRING([--disable-ifunc],
-               [do not use __attribute__((__ifunc__()))])],
-       [], [enable_ifunc=yes])
-
-if test "x$enable_ifunc" = xyes ; then
+AC_ARG_ENABLE([ifunc], [AS_HELP_STRING([--enable-ifunc],
+               [Use __attribute__((__ifunc__())). Enabled by default on
+               GNU/Linux (glibc) and FreeBSD.])],
+       [], [enable_ifunc=auto])
+
+# 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"
        CFLAGS="$CFLAGS -Werror"
        AC_MSG_CHECKING([if __attribute__((__ifunc__())) can be used])
        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 (*resolve_func (void)) (void) { return func; }
                void func_ifunc (void)
@@ -891,23 +913,28 @@ if test "x$enable_ifunc" = xyes ; then
                void make_clang_quiet(void);
                void make_clang_quiet(void) { resolve_func()(); }
        ]])], [
-               AC_DEFINE([HAVE_FUNC_ATTRIBUTE_IFUNC], [1],
+               enable_ifunc=yes
+       ], [
+               enable_ifunc=no
+       ])
+
+       AC_MSG_RESULT([$enable_ifunc])
+
+       CFLAGS="$OLD_CFLAGS"
+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.])
-               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([
+       # 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])
-       ])
-
-       CFLAGS="$OLD_CFLAGS"
 fi