mirror of
https://git.tukaani.org/xz.git
synced 2024-04-04 12:36:23 +02:00
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
This commit is contained in:
parent
b72d212024
commit
ee44863ae8
1 changed files with 26 additions and 9 deletions
|
@ -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
|
#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
|
||||||
# define CRC64_FUNC_INIT
|
|
||||||
# define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))
|
# define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))
|
||||||
|
static crc64_func_type crc64_func;
|
||||||
#else
|
#else
|
||||||
# define CRC64_FUNC_INIT = &crc64_dispatch
|
|
||||||
# define CRC64_SET_FUNC_ATTR
|
# define CRC64_SET_FUNC_ATTR
|
||||||
static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);
|
static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);
|
||||||
|
static crc64_func_type crc64_func = &crc64_dispatch;
|
||||||
#endif
|
#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
|
CRC64_SET_FUNC_ATTR
|
||||||
static void
|
static void
|
||||||
crc64_set_func(void)
|
crc64_set_func(void)
|
||||||
{
|
{
|
||||||
crc64_func = is_clmul_supported() ? &crc64_clmul : &crc64_generic;
|
crc64_func = crc64_resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +474,8 @@ crc64_set_func(void)
|
||||||
static uint64_t
|
static uint64_t
|
||||||
crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc)
|
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
|
// function pointer without any locking. If multiple threads run
|
||||||
// the detection code in parallel, they will all end up setting
|
// the detection code in parallel, they will all end up setting
|
||||||
// the pointer to the same value. This avoids the use of
|
// 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
|
#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)
|
extern LZMA_API(uint64_t)
|
||||||
lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
|
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);
|
return crc64_generic(buf, size, crc);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue