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
     {