|
|
0304b1 |
Note: the context of this patch differs from upstream slightly,
|
|
|
0304b1 |
to accomodate the lack of ILP32 in RHEL.
|
|
|
0304b1 |
|
|
|
0304b1 |
commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67
|
|
|
0304b1 |
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
|
|
0304b1 |
Date: Wed Sep 27 16:55:14 2017 +0100
|
|
|
0304b1 |
|
|
|
0304b1 |
aarch64: Disable lazy symbol binding of TLSDESC
|
|
|
0304b1 |
|
|
|
0304b1 |
Always do TLS descriptor initialization at load time during relocation
|
|
|
0304b1 |
processing to avoid barriers at every TLS access. In non-dlopened shared
|
|
|
0304b1 |
libraries the overhead of tls access vs static global access is > 3x
|
|
|
0304b1 |
bigger when lazy initialization is used (_dl_tlsdesc_return_lazy)
|
|
|
0304b1 |
compared to bind-now (_dl_tlsdesc_return) so the barriers dominate tls
|
|
|
0304b1 |
access performance.
|
|
|
0304b1 |
|
|
|
0304b1 |
TLSDESC relocs are in DT_JMPREL which are processed at load time using
|
|
|
0304b1 |
elf_machine_lazy_rel which is only supposed to do lightweight
|
|
|
0304b1 |
initialization using the DT_TLSDESC_PLT trampoline (the trampoline code
|
|
|
0304b1 |
jumps to the entry point in DT_TLSDESC_GOT which does the lazy tlsdesc
|
|
|
0304b1 |
initialization at runtime). This patch changes elf_machine_lazy_rel
|
|
|
0304b1 |
in aarch64 to do the symbol binding and initialization as if DF_BIND_NOW
|
|
|
0304b1 |
was set, so the non-lazy code path of elf/do-rel.h was replicated.
|
|
|
0304b1 |
|
|
|
0304b1 |
The static linker could be changed to emit TLSDESC relocs in DT_REL*,
|
|
|
0304b1 |
which are processed non-lazily, but the goal of this patch is to always
|
|
|
0304b1 |
guarantee bind-now semantics, even if the binary was produced with an
|
|
|
0304b1 |
old linker, so the barriers can be dropped in tls descriptor functions.
|
|
|
0304b1 |
|
|
|
0304b1 |
After this change the synchronizing ldar instructions can be dropped
|
|
|
0304b1 |
as well as the lazy initialization machinery including the DT_TLSDESC_GOT
|
|
|
0304b1 |
setup.
|
|
|
0304b1 |
|
|
|
0304b1 |
I believe this should be done on all targets, including ones where no
|
|
|
0304b1 |
barrier is needed for lazy initialization. There is very little gain in
|
|
|
0304b1 |
optimizing for large number of symbolic tlsdesc relocations which is an
|
|
|
0304b1 |
extremely uncommon case. And currently the tlsdesc entries are only
|
|
|
0304b1 |
readonly protected with -z now and some hardennings against writable
|
|
|
0304b1 |
JUMPSLOT relocs don't work for TLSDESC so they are a security hazard.
|
|
|
0304b1 |
(But to fix that the static linker has to be changed.)
|
|
|
0304b1 |
|
|
|
0304b1 |
* sysdeps/aarch64/dl-machine.h (elf_machine_lazy_rel): Do symbol
|
|
|
0304b1 |
binding and initialization non-lazily for R_AARCH64_TLSDESC.
|
|
|
0304b1 |
|
|
|
978e96 |
diff -rup a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
|
|
|
978e96 |
--- a/sysdeps/aarch64/dl-machine.h 2018-10-16 12:07:31.588149003 -0400
|
|
|
978e96 |
+++ b/sysdeps/aarch64/dl-machine.h 2018-10-16 12:18:46.214078837 -0400
|
|
|
978e96 |
@@ -376,12 +376,21 @@ elf_machine_lazy_rel (struct link_map *m
|
|
|
0304b1 |
}
|
|
|
0304b1 |
else if (__builtin_expect (r_type == R_AARCH64_TLSDESC, 1))
|
|
|
0304b1 |
{
|
|
|
0304b1 |
- struct tlsdesc volatile *td =
|
|
|
0304b1 |
- (struct tlsdesc volatile *)reloc_addr;
|
|
|
0304b1 |
+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
|
|
|
0304b1 |
+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
|
|
|
0304b1 |
+ const ElfW (Sym) *sym = &symtab[symndx];
|
|
|
0304b1 |
+ const struct r_found_version *version = NULL;
|
|
|
0304b1 |
|
|
|
0304b1 |
- td->arg = (void*)reloc;
|
|
|
0304b1 |
- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
|
|
|
0304b1 |
- + map->l_addr);
|
|
|
0304b1 |
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
|
|
0304b1 |
+ {
|
|
|
0304b1 |
+ const ElfW (Half) *vernum =
|
|
|
0304b1 |
+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
|
|
0304b1 |
+ version = &map->l_versions[vernum[symndx] & 0x7fff];
|
|
|
0304b1 |
+ }
|
|
|
0304b1 |
+
|
|
|
0304b1 |
+ /* Always initialize TLS descriptors completely, because lazy
|
|
|
0304b1 |
+ initialization requires synchronization at every TLS access. */
|
|
|
0304b1 |
+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
|
|
|
0304b1 |
}
|
|
|
0304b1 |
else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE))
|
|
|
0304b1 |
{
|