mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-01 10:06:57 +03:00
x86: Update _dl_tlsdesc_dynamic to preserve caller-saved registers
Compiler generates the following instruction sequence for GNU2 dynamic TLS access: leaq tls_var@TLSDESC(%rip), %rax call *tls_var@TLSCALL(%rax) or leal tls_var@TLSDESC(%ebx), %eax call *tls_var@TLSCALL(%eax) CALL instruction is transparent to compiler which assumes all registers, except for EFLAGS and RAX/EAX, are unchanged after CALL. When _dl_tlsdesc_dynamic is called, it calls __tls_get_addr on the slow path. __tls_get_addr is a normal function which doesn't preserve any caller-saved registers. _dl_tlsdesc_dynamic saved and restored integer caller-saved registers, but didn't preserve any other caller-saved registers. Add _dl_tlsdesc_dynamic IFUNC functions for FNSAVE, FXSAVE, XSAVE and XSAVEC to save and restore all caller-saved registers. This fixes BZ #31372. Add GLRO(dl_x86_64_runtime_resolve) with GLRO(dl_x86_tlsdesc_dynamic) to optimize elf_machine_runtime_setup. Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
This commit is contained in:
@ -27,8 +27,13 @@
|
||||
extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
|
||||
attribute_hidden;
|
||||
|
||||
#if defined SHARED && defined __x86_64__
|
||||
# include <dl-plt-rewrite.h>
|
||||
#if defined SHARED
|
||||
extern void _dl_tlsdesc_dynamic_fxsave (void) attribute_hidden;
|
||||
extern void _dl_tlsdesc_dynamic_xsave (void) attribute_hidden;
|
||||
extern void _dl_tlsdesc_dynamic_xsavec (void) attribute_hidden;
|
||||
|
||||
# ifdef __x86_64__
|
||||
# include <dl-plt-rewrite.h>
|
||||
|
||||
static void
|
||||
TUNABLE_CALLBACK (set_plt_rewrite) (tunable_val_t *valp)
|
||||
@ -47,6 +52,15 @@ TUNABLE_CALLBACK (set_plt_rewrite) (tunable_val_t *valp)
|
||||
: plt_rewrite_jmp);
|
||||
}
|
||||
}
|
||||
# else
|
||||
extern void _dl_tlsdesc_dynamic_fnsave (void) attribute_hidden;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
extern void _dl_runtime_resolve_fxsave (void) attribute_hidden;
|
||||
extern void _dl_runtime_resolve_xsave (void) attribute_hidden;
|
||||
extern void _dl_runtime_resolve_xsavec (void) attribute_hidden;
|
||||
#endif
|
||||
|
||||
#ifdef __LP64__
|
||||
@ -1130,6 +1144,44 @@ no_cpuid:
|
||||
TUNABLE_CALLBACK (set_x86_shstk));
|
||||
#endif
|
||||
|
||||
if (GLRO(dl_x86_cpu_features).xsave_state_size != 0)
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, XSAVEC))
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_xsavec;
|
||||
#endif
|
||||
#ifdef SHARED
|
||||
GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_xsavec;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_xsave;
|
||||
#endif
|
||||
#ifdef SHARED
|
||||
GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_xsave;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
GLRO(dl_x86_64_runtime_resolve) = _dl_runtime_resolve_fxsave;
|
||||
# ifdef SHARED
|
||||
GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fxsave;
|
||||
# endif
|
||||
#else
|
||||
# ifdef SHARED
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, FXSR))
|
||||
GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fxsave;
|
||||
else
|
||||
GLRO(dl_x86_tlsdesc_dynamic) = _dl_tlsdesc_dynamic_fnsave;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
||||
# ifdef __x86_64__
|
||||
TUNABLE_GET (plt_rewrite, tunable_val_t *,
|
||||
|
Reference in New Issue
Block a user