This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix TLS relocations against local symbols on powerpc32, sparc32 and sparc64
- From: James Clarke <jrtc27 at jrtc27 dot com>
- To: libc-alpha at sourceware dot org
- Cc: James Clarke <jrtc27 at jrtc27 dot com>
- Date: Sat, 2 Sep 2017 19:08:01 +0100
- Subject: [PATCH] Fix TLS relocations against local symbols on powerpc32, sparc32 and sparc64
- Authentication-results: sourceware.org; auth=none
* sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela):
Assign sym_map to be map for local symbols, as TLS relocations
use sym_map to determine whether the symbol is defined and to
extract the TLS information.
* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_rela):
Likewise.
* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela):
Likewise.
---
sysdeps/powerpc/powerpc32/dl-machine.h | 5 ++++-
sysdeps/sparc/sparc32/dl-machine.h | 1 +
sysdeps/sparc/sparc64/dl-machine.h | 1 +
3 files changed, 6 insertions(+), 1 deletion(-)
Normally, TLS relocations against local symbols are optimised by the linker to
be absolute. However, gold does not do this, and so it is possible to end up
with, for example, R_SPARC_TLS_DTPMOD64 referring to a local symbol. Since
sym_map is left as null in elf_machine_rela for the special local symbol case,
the relocation handling thinks it has nothing to do, and so the module gets
left as 0. Havoc then ensues when the variable in question is accessed. I have
written http://paste.debian.net/plain/984146 to demonstrate the problem. Before
this fix, the main_local_gold program would receive a SIGBUS on sparc64, and
SIGSEGV on powerpc32. With this fix applied, that test now passes like the rest
of them.
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index 1f8437ed9c..c19b3b7a16 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -310,7 +310,10 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
against local symbols. */
if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
&& sym->st_shndx != SHN_UNDEF)
- value = map->l_addr;
+ {
+ sym_map = map;
+ value = map->l_addr;
+ }
else
{
sym_map = RESOLVE_MAP (&sym, version, r_type);
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 436e4e6cc3..debf67bd1b 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -376,6 +376,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
&& sym->st_shndx != SHN_UNDEF)
{
+ sym_map = map;
value = map->l_addr;
}
else
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index c2871dca3a..e1ec7a532c 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -403,6 +403,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0)
&& sym->st_shndx != SHN_UNDEF)
{
+ sym_map = map;
value = map->l_addr;
}
else
--
2.14.1