Module Name: src
Committed By: snj
Date: Wed Jul 26 15:54:15 UTC 2017
Modified Files:
src/libexec/ld.elf_so [netbsd-7]: tls.c
Log Message:
Pull up following revision(s) (requested by joerg in ticket #1455):
libexec/ld.elf_so/tls.c: revision 1.11
Fix two bugs related to promotion of DSO TLS blocks into the static
thread allocation:
(1) Set the DTV vector up whenever an offset into the static allocation
is assigned, even if the block itself is not initialized. This has been
seen in libstdc++.
(2) Do not free a DTV block if it is part of the static thread
allocation.
To generate a diff of this commit:
cvs rdiff -u -r1.9.4.1 -r1.9.4.2 src/libexec/ld.elf_so/tls.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/libexec/ld.elf_so/tls.c
diff -u src/libexec/ld.elf_so/tls.c:1.9.4.1 src/libexec/ld.elf_so/tls.c:1.9.4.2
--- src/libexec/ld.elf_so/tls.c:1.9.4.1 Wed Dec 31 06:51:08 2014
+++ src/libexec/ld.elf_so/tls.c Wed Jul 26 15:54:15 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tls.c,v 1.9.4.1 2014/12/31 06:51:08 snj Exp $ */
+/* $NetBSD: tls.c,v 1.9.4.2 2017/07/26 15:54:15 snj Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: tls.c,v 1.9.4.1 2014/12/31 06:51:08 snj Exp $");
+__RCSID("$NetBSD: tls.c,v 1.9.4.2 2017/07/26 15:54:15 snj Exp $");
#include <sys/param.h>
#include <sys/ucontext.h>
@@ -134,7 +134,7 @@ _rtld_tls_allocate_locked(void)
SET_DTV_GENERATION(tcb->tcb_dtv, _rtld_tls_dtv_generation);
for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
- if (obj->tlsinitsize && obj->tls_done) {
+ if (obj->tls_done) {
#ifdef __HAVE_TLS_VARIANT_I
q = p + obj->tlsoffset;
#else
@@ -142,7 +142,8 @@ _rtld_tls_allocate_locked(void)
#endif
dbg(("obj %p dtv %p tlsoffset %zu",
obj, q, obj->tlsoffset));
- memcpy(q, obj->tlsinit, obj->tlsinitsize);
+ if (obj->tlsinitsize)
+ memcpy(q, obj->tlsinit, obj->tlsinitsize);
tcb->tcb_dtv[obj->tlsindex] = q;
}
}
@@ -167,21 +168,25 @@ void
_rtld_tls_free(struct tls_tcb *tcb)
{
size_t i, max_index;
- uint8_t *p;
+ uint8_t *p, *p_end;
sigset_t mask;
_rtld_exclusive_enter(&mask);
- max_index = DTV_MAX_INDEX(tcb->tcb_dtv);
- for (i = 1; i <= max_index; ++i)
- xfree(tcb->tcb_dtv[i]);
- xfree(tcb->tcb_dtv - 1);
-
#ifdef __HAVE_TLS_VARIANT_I
p = (uint8_t *)tcb;
#else
p = (uint8_t *)tcb - _rtld_tls_static_space;
#endif
+ p_end = p + _rtld_tls_static_space;
+
+ max_index = DTV_MAX_INDEX(tcb->tcb_dtv);
+ for (i = 1; i <= max_index; ++i) {
+ if ((uint8_t *)tcb->tcb_dtv[i] < p ||
+ (uint8_t *)tcb->tcb_dtv[i] >= p_end)
+ xfree(tcb->tcb_dtv[i]);
+ }
+ xfree(tcb->tcb_dtv - 1);
xfree(p);
_rtld_exclusive_exit(&mask);