summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--sysdeps/arm/dl-machine.h24
2 files changed, 21 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 778e41fd45..e1dc25c62e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2017-11-03  Szabolcs Nagy  <szabolcs.nagy@arm.com>
 
+	[BZ #18572]
+	* sysdeps/arm/dl-machine.h (elf_machine_lazy_rel): Do symbol binding
+	non-lazily for R_ARM_TLS_DESC.
+
+2017-11-03  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
 	[BZ #17078]
 	* sysdeps/arm/dl-machine.h (elf_machine_rela): Remove the
 	R_ARM_TLS_DESC case.
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index bf5f5d205c..c59386f515 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -669,15 +669,21 @@ elf_machine_lazy_rel (struct link_map *map,
     }
   else if (__builtin_expect (r_type == R_ARM_TLS_DESC, 1))
     {
-      struct tlsdesc volatile *td =
-	(struct tlsdesc volatile *)reloc_addr;
-
-      /* The linker must have given us the parameter we need in the
-	 first GOT entry, and left the second one empty.  We fill the
-	 latter with the resolver address.  */
-      assert (td->entry == 0);
-      td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
-			  + map->l_addr);
+      const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
+      const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
+      const ElfW (Sym) *sym = &symtab[symndx];
+      const struct r_found_version *version = NULL;
+
+      if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+	{
+	  const ElfW (Half) *vernum =
+	    (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+	  version = &map->l_versions[vernum[symndx] & 0x7fff];
+	}
+
+      /* Always initialize TLS descriptors completely, because lazy
+	 initialization requires synchronization at every TLS access.  */
+      elf_machine_rel (map, reloc, sym, version, reloc_addr, skip_ifunc);
     }
   else
     _dl_reloc_bad_type (map, r_type, 1);