diff --git a/src/liblzma/check/crc32_fast.c b/src/liblzma/check/crc32_fast.c index 079051f1..719d696c 100644 --- a/src/liblzma/check/crc32_fast.c +++ b/src/liblzma/check/crc32_fast.c @@ -135,15 +135,12 @@ typedef uint32_t (*crc32_func_type)( // This resolver is shared between all three dispatch methods. It serves as // the ifunc resolver if ifunc is supported, otherwise it is called as a // regular function by the constructor or first call resolution methods. -// The __no_profile_instrument_function__ attribute support is checked when -// determining if ifunc can be used, so it is safe to use here. -#ifdef CRC_USE_IFUNC -__attribute__((__no_profile_instrument_function__)) -#endif +// The funcion attributes are needed for safe IFUNC resolver usage with GCC. +lzma_resolver_attributes static crc32_func_type crc32_resolve(void) { - return is_arch_extension_supported() + return is_arch_extension_supported() ? &crc32_arch_optimized : &crc32_generic; } diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c index 5728b45e..330a5016 100644 --- a/src/liblzma/check/crc64_fast.c +++ b/src/liblzma/check/crc64_fast.c @@ -98,13 +98,12 @@ typedef uint64_t (*crc64_func_type)( # pragma GCC diagnostic ignored "-Wunused-function" #endif -#ifdef CRC_USE_IFUNC -__attribute__((__no_profile_instrument_function__)) -#endif +// The funcion attributes are needed for safe IFUNC resolver usage with GCC. +lzma_resolver_attributes static crc64_func_type crc64_resolve(void) { - return is_arch_extension_supported() + return is_arch_extension_supported() ? &crc64_arch_optimized : &crc64_generic; } diff --git a/src/liblzma/check/crc_common.h b/src/liblzma/check/crc_common.h index 856665db..5a86556f 100644 --- a/src/liblzma/check/crc_common.h +++ b/src/liblzma/check/crc_common.h @@ -128,6 +128,31 @@ # endif #endif +#ifdef CRC_USE_IFUNC +// Two function attributes are needed to make IFUNC safe with GCC. +// +// no-omit-frame-pointer prevents false Valgrind issues when combined with +// a few other compiler flags. The optimize attribute is supported on +// GCC >= 4.4 and is not supported with Clang. +# if TUKLIB_GNUC_REQ(4,4) && !defined(__clang__) +# define no_omit_frame_pointer \ + __attribute__((optimize("no-omit-frame-pointer"))) +# else +# define no_omit_frame_pointer +# endif + +// The __no_profile_instrument_function__ attribute support is checked when +// determining if ifunc can be used, so it is safe to use unconditionally. +// This attribute is needed because GCC can add profiling to the IFUNC +// resolver, which calls functions that have not yet been relocated leading +// to a crash on liblzma start up. +# define lzma_resolver_attributes \ + __attribute__((__no_profile_instrument_function__)) \ + no_omit_frame_pointer +#else +# define lzma_resolver_attributes +#endif + // For CRC32 use the generic slice-by-eight implementation if no optimized // version is available. #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)