diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2023-06-27 17:05:23 +0300 |
---|---|---|
committer | Jia Tan <jiat0218@gmail.com> | 2023-06-27 23:55:59 +0800 |
commit | ee44863ae88e377a5df10db007ba9bfadde3d314 (patch) | |
tree | c3f534ebce92e9d561c51c1aa40c2254fdc7d18b /src | |
parent | Add ifunc check to CMakeLists.txt (diff) | |
download | xz-ee44863ae88e377a5df10db007ba9bfadde3d314.tar.xz |
liblzma: Add ifunc implementation to crc64_fast.c.
The ifunc method avoids indirection via the function pointer
crc64_func. This works on GNU/Linux and probably on FreeBSD too.
The previous __attribute((__constructor__)) method is kept for
compatibility with ELF platforms which do support ifunc.
The ifunc method has some limitations, for example, building
liblzma with -fsanitize=address will result in segfaults.
The configure option --disable-ifunc must be used for such builds.
Thanks to Hans Jansen for the original patch.
Closes: https://github.com/tukaani-project/xz/pull/53
Diffstat (limited to 'src')
-rw-r--r-- | src/liblzma/check/crc64_fast.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c index e686dbd7..e2d4ec3c 100644 --- a/src/liblzma/check/crc64_fast.c +++ b/src/liblzma/check/crc64_fast.c @@ -438,26 +438,34 @@ is_clmul_supported(void) } +typedef uint64_t (*crc64_func_type)( + const uint8_t *buf, size_t size, uint64_t crc); + + +static crc64_func_type +crc64_resolve(void) +{ + return is_clmul_supported() ? &crc64_clmul : &crc64_generic; +} + + +#ifndef HAVE_FUNC_ATTRIBUTE_IFUNC + #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR -# define CRC64_FUNC_INIT # define CRC64_SET_FUNC_ATTR __attribute__((__constructor__)) +static crc64_func_type crc64_func; #else -# define CRC64_FUNC_INIT = &crc64_dispatch # define CRC64_SET_FUNC_ATTR static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc); +static crc64_func_type crc64_func = &crc64_dispatch; #endif -// Pointer to the the selected CRC64 method. -static uint64_t (*crc64_func)(const uint8_t *buf, size_t size, uint64_t crc) - CRC64_FUNC_INIT; - - CRC64_SET_FUNC_ATTR static void crc64_set_func(void) { - crc64_func = is_clmul_supported() ? &crc64_clmul : &crc64_generic; + crc64_func = crc64_resolve(); return; } @@ -466,7 +474,8 @@ crc64_set_func(void) static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc) { - // When __attribute__((__constructor__)) isn't supported, set the + // When __attribute__((__ifunc__(...))) and + // __attribute__((__constructor__)) isn't supported, set the // function pointer without any locking. If multiple threads run // the detection code in parallel, they will all end up setting // the pointer to the same value. This avoids the use of @@ -477,8 +486,15 @@ crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc) } #endif #endif +#endif +#if defined(CRC_GENERIC) && defined(CRC_CLMUL) \ + && defined(HAVE_FUNC_ATTRIBUTE_IFUNC) +extern LZMA_API(uint64_t) +lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) + __attribute__((__ifunc__("crc64_resolve"))); +#else extern LZMA_API(uint64_t) lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) { @@ -528,3 +544,4 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) return crc64_generic(buf, size, crc); #endif } +#endif |