aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/check/crc64_fast.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2023-06-27 17:05:23 +0300
committerJia Tan <jiat0218@gmail.com>2023-06-27 23:55:59 +0800
commitee44863ae88e377a5df10db007ba9bfadde3d314 (patch)
treec3f534ebce92e9d561c51c1aa40c2254fdc7d18b /src/liblzma/check/crc64_fast.c
parentAdd ifunc check to CMakeLists.txt (diff)
downloadxz-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/liblzma/check/crc64_fast.c')
-rw-r--r--src/liblzma/check/crc64_fast.c35
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