Module Name: src
Committed By: snj
Date: Sun Jul 23 14:25:46 UTC 2017
Modified Files:
src/libexec/ld.elf_so [netbsd-6]: tls.c
Log Message:
Pull up following revision(s) (requested by joerg in ticket #1462):
libexec/ld.elf_so/tls.c: revision 1.11 via patch
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.7.6.1 -r1.7.6.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.7.6.1 src/libexec/ld.elf_so/tls.c:1.7.6.2
--- src/libexec/ld.elf_so/tls.c:1.7.6.1 Thu Nov 7 20:23:46 2013
+++ src/libexec/ld.elf_so/tls.c Sun Jul 23 14:25:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: tls.c,v 1.7.6.1 2013/11/07 20:23:46 snj Exp $ */
+/* $NetBSD: tls.c,v 1.7.6.2 2017/07/23 14:25:46 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.7.6.1 2013/11/07 20:23:46 snj Exp $");
+__RCSID("$NetBSD: tls.c,v 1.7.6.2 2017/07/23 14:25:46 snj Exp $");
#include <sys/param.h>
#include <sys/ucontext.h>
@@ -138,13 +138,14 @@ _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
q = p - obj->tlsoffset;
#endif
- memcpy(q, obj->tlsinit, obj->tlsinitsize);
+ if (obj->tlsinitsize)
+ memcpy(q, obj->tlsinit, obj->tlsinitsize);
tcb->tcb_dtv[obj->tlsindex] = q;
}
}
@@ -169,21 +170,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);