tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
TLS support, MI part
Hi all,
attached is the MI part of supporting Thread Locale Storage.
I've also attached SH3 as example for the MD part.
This patch doesn't change anything for platforms (currently) without TLS
support. TLS support is enabled by defining __HAVE_TLS_VARIANT_I or
__HAVE_TLS_VARIANT_II. The TLS variants are part of the ABI
specification. Generally, platforms with newer TLS ABI use variant I,
platforms with early TLS ABI use variant II.
Joerg
Index: src/distrib/sets/lists/comp/mi
===================================================================
--- src/distrib/sets/lists/comp/mi
+++ src/distrib/sets/lists/comp/mi
@@ -2171,10 +2171,11 @@
./usr/include/sys/time.h comp-c-include
./usr/include/sys/timeb.h comp-c-include
./usr/include/sys/timepps.h comp-c-include
./usr/include/sys/times.h comp-c-include
./usr/include/sys/timex.h comp-c-include
+./usr/include/sys/tls.h comp-c-include
./usr/include/sys/tprintf.h comp-obsolete obsolete
./usr/include/sys/trace.h comp-c-include
./usr/include/sys/tree.h comp-c-include
./usr/include/sys/tty.h comp-c-include
./usr/include/sys/ttychars.h comp-c-include
Index: src/distrib/sets/lists/tests/mi
===================================================================
--- src/distrib/sets/lists/tests/mi
+++ src/distrib/sets/lists/tests/mi
@@ -418,10 +418,14 @@
./usr/libdata/debug/usr/tests/lib/libc/sys
tests-lib-debug
./usr/libdata/debug/usr/tests/lib/libc/sys/t_clone.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_context.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_cerror.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_sigqueue.debug
tests-lib-debug debug,atf
+./usr/libdata/debug/usr/tests/lib/libc/tls
tests-lib-debug
+./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_dlopen.debug
tests-lib-debug debug,atf
+./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_dynamic.debug
tests-lib-debug debug,atf
+./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_static.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/ttyio
tests-lib-debug
./usr/libdata/debug/usr/tests/lib/libc/ttyio/t_ptm.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/ttyio/t_ttyio.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/t_cerror.debug
tests-obsolete obsolete
./usr/libdata/debug/usr/tests/lib/libc/t_clone.debug
tests-obsolete obsolete
@@ -1845,10 +1849,19 @@
./usr/tests/lib/libc/sys/Atffile tests-lib-tests atf
./usr/tests/lib/libc/sys/t_clone tests-lib-tests atf
./usr/tests/lib/libc/sys/t_context tests-lib-tests atf
./usr/tests/lib/libc/sys/t_cerror tests-lib-tests atf
./usr/tests/lib/libc/sys/t_sigqueue tests-lib-tests atf
+./usr/tests/lib/libc/tls tests-lib-tests
+./usr/tests/lib/libc/tls/Atffile tests-lib-tests atf
+./usr/tests/lib/libc/tls/h_tls_dlopen.so tests-lib-tests atf
+./usr/tests/lib/libc/tls/h_tls_dlopen.so.1 tests-lib-tests atf
+./usr/tests/lib/libc/tls/libh_tls_dynamic.so tests-lib-tests atf
+./usr/tests/lib/libc/tls/libh_tls_dynamic.so.1 tests-lib-tests atf
+./usr/tests/lib/libc/tls/t_tls_dlopen tests-lib-tests atf
+./usr/tests/lib/libc/tls/t_tls_dynamic tests-lib-tests atf
+./usr/tests/lib/libc/tls/t_tls_static tests-lib-tests atf
./usr/tests/lib/libc/ttyio tests-lib-tests
./usr/tests/lib/libc/ttyio/Atffile tests-lib-tests atf
./usr/tests/lib/libc/ttyio/t_ptm tests-lib-tests atf
./usr/tests/lib/libc/ttyio/t_ttyio tests-lib-tests atf
./usr/tests/lib/libc/t_atexit tests-obsolete obsolete
Index: src/etc/mtree/NetBSD.dist.tests
===================================================================
--- src/etc/mtree/NetBSD.dist.tests
+++ src/etc/mtree/NetBSD.dist.tests
@@ -59,10 +59,11 @@
./usr/libdata/debug/usr/tests/lib/libc/ssp
./usr/libdata/debug/usr/tests/lib/libc/stdio
./usr/libdata/debug/usr/tests/lib/libc/stdlib
./usr/libdata/debug/usr/tests/lib/libc/string
./usr/libdata/debug/usr/tests/lib/libc/sys
+./usr/libdata/debug/usr/tests/lib/libc/tls
./usr/libdata/debug/usr/tests/lib/libc/ttyio
./usr/libdata/debug/usr/tests/lib/libc/time
./usr/libdata/debug/usr/tests/lib/libdes
./usr/libdata/debug/usr/tests/lib/libevent
./usr/libdata/debug/usr/tests/lib/semaphore
@@ -173,10 +174,11 @@
./usr/tests/lib/libc/ssp
./usr/tests/lib/libc/stdio
./usr/tests/lib/libc/stdlib
./usr/tests/lib/libc/string
./usr/tests/lib/libc/sys
+./usr/tests/lib/libc/tls
./usr/tests/lib/libc/ttyio
./usr/tests/lib/libc/time
./usr/tests/lib/libdes
./usr/tests/lib/semaphore
./usr/tests/lib/semaphore/pthread
Index: src/lib/libc/Makefile
===================================================================
--- src/lib/libc/Makefile
+++ src/lib/libc/Makefile
@@ -90,10 +90,11 @@
.include "${.CURDIR}/stdlib/Makefile.inc"
.include "${.CURDIR}/string/Makefile.inc"
.include "${.CURDIR}/termios/Makefile.inc"
.include "${.CURDIR}/thread-stub/Makefile.inc"
.include "${.CURDIR}/time/Makefile.inc"
+.include "${.CURDIR}/tls/Makefile.inc"
.include "${.CURDIR}/sys/Makefile.inc"
.include "${.CURDIR}/uuid/Makefile.inc"
.if (${MKYP} != "no")
.include "${.CURDIR}/yp/Makefile.inc"
.endif
Index: src/lib/libc/misc/initfini.c
===================================================================
--- src/lib/libc/misc/initfini.c
+++ src/lib/libc/misc/initfini.c
@@ -36,19 +36,24 @@
#include "namespace.h"
#endif
#include <sys/param.h>
#include <sys/exec.h>
+#include <sys/tls.h>
#include <stdbool.h>
void _libc_init(void) __attribute__((__constructor__, __used__));
void __guard_setup(void);
void __libc_thr_init(void);
void __libc_atomic_init(void);
void __libc_atexit_init(void);
void __libc_env_init(void);
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+__dso_hidden void __libc_static_tls_setup(void);
+#endif
static bool libc_initialised;
void _libc_init(void);
@@ -75,10 +80,15 @@
/* For -fstack-protector */
__guard_setup();
/* Atomic operations */
__libc_atomic_init();
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ /* Initialize TLS for statically linked programs. */
+ __libc_static_tls_setup();
+#endif
/* Threads */
__libc_thr_init();
/* Initialize the atexit mutexes */
ADDED src/lib/libc/tls/Makefile.inc
Index: src/lib/libc/tls/Makefile.inc
===================================================================
--- src/lib/libc/tls/Makefile.inc
+++ src/lib/libc/tls/Makefile.inc
@@ -0,0 +1,8 @@
+# $NetBSD$
+
+.include <bsd.own.mk>
+
+# Our sources
+.PATH: ${.PARSEDIR} ${ARCHDIR}/tls
+
+SRCS+= tls.c
ADDED src/lib/libc/tls/tls.c
Index: src/lib/libc/tls/tls.c
===================================================================
--- src/lib/libc/tls/tls.c
+++ src/lib/libc/tls/tls.c
@@ -0,0 +1,156 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "namespace.h"
+
+#include <sys/tls.h>
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+
+#define _rtld_tls_allocate __libc_rtld_tls_allocate
+#define _rtld_tls_free __libc_rtld_tls_free
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <link_elf.h>
+#include <lwp.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+__dso_hidden void __libc_static_tls_setup(void);
+
+static const void *tls_initaddr;
+static size_t tls_initsize;
+static size_t tls_size;
+static size_t tls_allocation;
+static void *initial_thread_tcb;
+
+__weak_alias(__tls_get_addr, 0)
+#ifdef __i386__
+__weak_alias(___tls_get_addr, 0)
+#endif
+
+__weak_alias(_rtld_tls_allocate, __libc_rtld_tls_allocate)
+
+struct tls_tcb *
+_rtld_tls_allocate(void)
+{
+ struct tls_tcb *tcb;
+ uint8_t *p;
+
+ if (initial_thread_tcb == NULL) {
+#ifdef __HAVE_TLS_VARIANT_II
+ tls_size = roundup2(tls_size, sizeof(void *));
+#endif
+ tls_allocation = tls_size + sizeof(*tcb);
+
+ initial_thread_tcb = p = mmap(NULL, tls_allocation,
+ PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
+ } else {
+ p = calloc(1, tls_allocation);
+ }
+ if (p == NULL) {
+ static const char msg[] = "TLS allocation failed,
terminating\n";
+ write(STDERR_FILENO, msg, sizeof(msg));
+ _exit(127);
+ }
+#ifdef __HAVE_TLS_VARIANT_I
+ /* LINTED */
+ tcb = (struct tls_tcb *)p;
+ p += sizeof(struct tls_tcb);
+#else
+ /* LINTED tls_size is rounded above */
+ tcb = (struct tls_tcb *)(p + tls_size);
+ tcb->tcb_self = tcb;
+#endif
+ memcpy(p, tls_initaddr, tls_initsize);
+
+ return tcb;
+}
+
+__weak_alias(_rtld_tls_free, __libc_rtld_tls_free)
+
+void
+_rtld_tls_free(struct tls_tcb *tcb)
+{
+ uint8_t *p;
+
+#ifdef __HAVE_TLS_VARIANT_I
+ /* LINTED */
+ p = (uint8_t *)tcb;
+#else
+ /* LINTED */
+ p = (uint8_t *)tcb - tls_size;
+#endif
+ if (p == initial_thread_tcb)
+ munmap(p, tls_allocation);
+ else
+ free(p);
+}
+
+__weakref_visible int rtld_DYNAMIC __weak_reference(_DYNAMIC);
+
+static int
+__libc_static_tls_setup_cb(struct dl_phdr_info *data, size_t len, void *cookie)
+{
+ const Elf_Phdr *phdr = data->dlpi_phdr;
+ const Elf_Phdr *phlimit = data->dlpi_phdr + data->dlpi_phnum;
+
+ for (; phdr < phlimit; ++phdr) {
+ if (phdr->p_type != PT_TLS)
+ continue;
+ tls_initaddr = (void *)(phdr->p_vaddr + data->dlpi_addr);
+ tls_initsize = phdr->p_filesz;
+ tls_size = phdr->p_memsz;
+ }
+ return 0;
+}
+
+void
+__libc_static_tls_setup(void)
+{
+ struct tls_tcb *tcb;
+
+ if (&rtld_DYNAMIC != NULL)
+ return;
+
+ dl_iterate_phdr(__libc_static_tls_setup_cb, NULL);
+
+ tcb = _rtld_tls_allocate();
+ _lwp_setprivate(tcb);
+}
+
+#endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
Index: src/lib/libpthread/pthread.c
===================================================================
--- src/lib/libpthread/pthread.c
+++ src/lib/libpthread/pthread.c
@@ -36,10 +36,11 @@
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <sys/lwpctl.h>
+#include <sys/tls.h>
#include <err.h>
#include <errno.h>
#include <lwp.h>
#include <signal.h>
@@ -192,10 +193,15 @@
/* Create the thread structure corresponding to main() */
pthread__initmain(&first);
pthread__initthread(first);
pthread__scrubthread(first, NULL, 0);
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ first->pt_tls = _lwp_getprivate();
+ first->pt_tls->tcb_pthread = first;
+#endif
+
first->pt_lid = _lwp_self();
PTQ_INSERT_HEAD(&pthread__allqueue, first, pt_allq);
RB_INSERT(__pthread__alltree, &pthread__alltree, first);
if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &first->pt_lwpctl) != 0) {
@@ -282,10 +288,13 @@
static void
pthread__initthread(pthread_t t)
{
t->pt_self = t;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ t->pt_tls = NULL;
+#endif
t->pt_magic = PT_MAGIC;
t->pt_willpark = 0;
t->pt_unpark = 0;
t->pt_nwaiters = 0;
t->pt_sleepobj = NULL;
@@ -305,10 +314,16 @@
static void
pthread__scrubthread(pthread_t t, char *name, int flags)
{
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ if (t->pt_tls) {
+ _rtld_tls_free(t->pt_tls);
+ t->pt_tls = NULL;
+ }
+#endif
t->pt_state = PT_STATE_RUNNING;
t->pt_exitval = NULL;
t->pt_flags = flags;
t->pt_cancel = 0;
t->pt_errno = 0;
@@ -324,10 +339,11 @@
pthread_t newthread;
pthread_attr_t nattr;
struct pthread_attr_private *p;
char * volatile name;
unsigned long flag;
+ void *private_area;
int ret;
/*
* It's okay to check this without a lock because there can
* only be one thread before it becomes true.
@@ -405,12 +421,19 @@
* Create the new LWP.
*/
pthread__scrubthread(newthread, name, nattr.pta_flags);
newthread->pt_func = startfunc;
newthread->pt_arg = arg;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ private_area = newthread->pt_tls = _rtld_tls_allocate();
+ newthread->pt_tls->tcb_pthread = newthread;
+#else
+ private_area = newthread;
+#endif
+
_lwp_makecontext(&newthread->pt_uc, pthread__create_tramp,
- newthread, newthread, newthread->pt_stack.ss_sp,
+ newthread, private_area, newthread->pt_stack.ss_sp,
newthread->pt_stack.ss_size);
flag = LWP_DETACHED;
if ((newthread->pt_flags & PT_FLAG_SUSPENDED) != 0 ||
(nattr.pta_flags & PT_FLAG_EXPLICIT_SCHED) != 0)
@@ -1238,13 +1261,13 @@
/* XXX */
errx(2, "failed to setup main thread: error=%d", error);
}
*newt = t;
-
- /* Set up identity register. */
- (void)_lwp_setprivate(t);
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+ _lwp_setprivate(t);
+#endif
}
static int
/*ARGSUSED*/
pthread__stackid_setup(void *base, size_t size, pthread_t *tp)
Index: src/lib/libpthread/pthread_int.h
===================================================================
--- src/lib/libpthread/pthread_int.h
+++ src/lib/libpthread/pthread_int.h
@@ -35,10 +35,12 @@
*/
#ifndef _LIB_PTHREAD_INT_H
#define _LIB_PTHREAD_INT_H
+#include <sys/tls.h>
+
/* #define PTHREAD__DEBUG */
#define ERRORCHECK
#include "pthread_types.h"
#include "pthread_queue.h"
@@ -90,10 +92,13 @@
void (*plo_lock)(__cpu_simple_lock_t *);
};
struct __pthread_st {
pthread_t pt_self; /* Must be first. */
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ struct tls_tcb *pt_tls; /* Thread Local Storage area */
+#endif
unsigned int pt_magic; /* Magic number */
int pt_state; /* running, blocked, etc. */
pthread_mutex_t pt_lock; /* lock on state */
int pt_flags; /* see PT_FLAG_* below */
int pt_cancel; /* Deferred cancellation */
@@ -249,15 +254,24 @@
_INITCONTEXT_U_MD(ucp) \
} while (/*CONSTCOND*/0)
#if 0 && defined(__HAVE___LWP_GETPRIVATE_FAST)
+# if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+static inline pthread_t __constfunc
+pthread__self(void)
+{
+ struct tls_tcb *tcb = __lwp_getprivate_fast()
+ return (pthread_t)tcb->tcb_pthread;
+}
+# else
static inline pthread_t __constfunc
pthread__self(void)
{
return (pthread_t)__lwp_getprivate_fast();
}
+# endif
#else
/* Stack location of pointer to a particular thread */
extern vaddr_t pthread__mainbase;
extern vaddr_t pthread__mainstruct;
static inline pthread_t
Index: src/libexec/ld.elf_so/Makefile
===================================================================
--- src/libexec/ld.elf_so/Makefile
+++ src/libexec/ld.elf_so/Makefile
@@ -59,11 +59,12 @@
.endif
CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
SRCS+= rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \
- map_object.c load.c search.c headers.c paths.c expand.c
+ map_object.c load.c search.c headers.c paths.c expand.c \
+ tls.c
.if ${USE_FORT} == "yes"
.PATH.c: ${NETBSDSRCDIR}/lib/libc/misc
SRCS+= stack_protector.c
.endif
ADDED src/libexec/ld.elf_so/README.TLS
Index: src/libexec/ld.elf_so/README.TLS
===================================================================
--- src/libexec/ld.elf_so/README.TLS
+++ src/libexec/ld.elf_so/README.TLS
@@ -0,0 +1,81 @@
+Steps for adding TLS support for a new platform:
+
+(1) Declare TLS variant in machine/types.h by defining either
+__HAVE_TLS_VARIANT_I or __HAVE_TLS_VARIANT_II.
+
+(2) crt0.o has to call _rtld_tls_static_setup() if _DYNAMIC == NULL.
+This part is already done if the new src/lib/csu/arch layout is used
+by the architecture.
+
+(3) _lwp_makecontext has to set the reserved register or kernel transfer
+variable in uc_mcontext to the provided value of 'private'.
+
+This is not possible on the VAX as there is no free space in ucontext_t.
+This requires either a special version of _lwp_create or versioning
+everything using ucontext_t. Debug support depends on getting the data from
+ucontext_t, so the second option is possibly required.
+
+(4) _lwp_setprivate(2) has to update the same register as
+_lwp_makecontext. cpu_lwp_setprivate has to call _lwp_setprivate(2) to
+reflect the kernel view. cpu_switch has to update the mapping.
+
+_lwp_setprivate is used for the initial thread, all other threads
+created by libpthread use _lwp_makecontext for this purpose.
+
+(5) Provide __tls_get_addr and possible other MD functions for dynamic
+TLS offset computation. If such alternative entry points exist (currently
+only i386), also add a weak reference to 0 in src/lib/libc/tls/tls.c.
+
+The generic implementation is:
+
+#include <sys/cdefs.h>
+#include <sys/tls.h>
+#include <lwp.h>
+
+/* Weak entry is overriden by ld.elf_so for dynamic linkage */
+weak_alias(__tls_get_addr, __libc__tls_get_addr)
+
+void *
+__libc__tls_get_addr(size_t idx[2])
+{
+ struct tls_tcb *tcb;
+
+ tcb = _lwp_getprivate();
+ return _rtld_tls_get_addr(tcb, idx[0], idx[1]);
+}
+
+XXX Document optimisations based idx[0]
+
+(6) Implement the necessary relocation records in mdreloc.c. There are
+typically three relocation types found in dynamic binaries:
+
+(a) R_TYPE(TLS_DTPOFF): Offset inside the module. The common TLS code
+ensures that the DTV vector points to offset 0 inside the module TLS block.
+This is normally def->st_value + rela->r_addend.
+
+(b) R_TYPE(TLS_DTPMOD): Module index.
+
+(c) R_TYPE(TLS_TPOFF): Static TLS offset. The code has to check whether
+the static TLS offset for this module has been allocated
+(defobj->tls_done) and otherwise call _rtld_tls_offset_allocate(). This
+may fail if no static space is available and the object has been pulled
+in via dlopen(3).
+
+For TLS Variant I, this is typically:
+
+def->st_value + rela->r_addend + defobj->tlsoffset + sizeof(struct tls_tcb)
+
+e.g. the relocation doesn't include the fixed TCB.
+
+For TLS Variant II, this is typically:
+
+def->st_value - defobj->tlsoffset + rela->r_addend
+
+e.g. starting offset is counting down from the TCB.
+
+(7) Implement _lwp_getprivate_fast() in machine/mcontext.h and set
+__HAVE___LWP_GETPRIVATE_FAST.
+
+(8) Test using src/tests/lib/libc/tls. Make sure with "objdump -R" that
+t_tls_dynamic has two TPOFF relocations and h_tls_dlopen.so.1 and
+libh_tls_dynamic.so.1 have both two DTPMOD and DTPOFF relocations.
Index: src/libexec/ld.elf_so/TODO
===================================================================
--- src/libexec/ld.elf_so/TODO
+++ src/libexec/ld.elf_so/TODO
@@ -1,7 +1,11 @@
rtld:
* resolve MIPS binding lossage
+
+TLS:
+* implement proper allocator for static TLS and support for actively
+ freeing DTV entries.
binutils/gcc:
* alpha: why are there GLOB_DAT relocs in ld.elf_so?
* alpha: bogus textrels in rtti info
* mips: why are there global GOT relocs in ld.elf_so?
Index: src/libexec/ld.elf_so/headers.c
===================================================================
--- src/libexec/ld.elf_so/headers.c
+++ src/libexec/ld.elf_so/headers.c
@@ -358,12 +358,22 @@
break;
case PT_DYNAMIC:
obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
break;
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ case PT_TLS:
+ obj->tlsindex = 1;
+ obj->tlssize = ph->p_memsz;
+ obj->tlsalign = ph->p_align;
+ obj->tlsinitsize = ph->p_filesz;
+ obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr;
+ break;
+#endif
}
}
assert(nsegs == 2);
obj->entry = entry;
return obj;
}
Index: src/libexec/ld.elf_so/map_object.c
===================================================================
--- src/libexec/ld.elf_so/map_object.c
+++ src/libexec/ld.elf_so/map_object.c
@@ -64,10 +64,13 @@
_rtld_map_object(const char *path, int fd, const struct stat *sb)
{
Obj_Entry *obj;
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ Elf_Phdr *phtls;
+#endif
size_t phsize;
Elf_Phdr *phlimit;
Elf_Phdr *segs[2];
int nsegs;
caddr_t mapbase = MAP_FAILED;
@@ -85,10 +88,13 @@
Elf_Off data_offset;
Elf_Addr data_vaddr;
Elf_Addr data_vlimit;
int data_flags;
caddr_t data_addr;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ Elf_Addr tls_vaddr = 0; /* Noise GCC */
+#endif
Elf_Addr phdr_vaddr;
size_t phdr_memsz;
caddr_t gap_addr;
size_t gap_size;
int i;
@@ -157,10 +163,13 @@
*
* We rely on there being exactly two load segments, text and data,
* in that order.
*/
phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ phtls = NULL;
+#endif
phsize = ehdr->e_phnum * sizeof(phdr[0]);
obj->phdr = NULL;
phdr_vaddr = EA_UNDEF;
phdr_memsz = 0;
phlimit = phdr + ehdr->e_phnum;
@@ -188,10 +197,16 @@
case PT_DYNAMIC:
obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr;
dbg(("%s: PT_DYNAMIC %p", obj->path, obj->dynamic));
break;
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ case PT_TLS:
+ phtls = phdr;
+ break;
+#endif
}
++phdr;
}
phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
@@ -235,10 +250,21 @@
#endif
obj->textsize = text_vlimit - base_vaddr;
obj->vaddrbase = base_vaddr;
obj->isdynamic = ehdr->e_type == ET_DYN;
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ if (phtls != NULL) {
+ ++_rtld_tls_dtv_generation;
+ obj->tlsindex = ++_rtld_tls_max_index;
+ obj->tlssize = phtls->p_memsz;
+ obj->tlsalign = phtls->p_align;
+ obj->tlsinitsize = phtls->p_filesz;
+ tls_vaddr = phtls->p_vaddr;
+ }
+#endif
obj->phdr_loaded = false;
for (i = 0; i < nsegs; i++) {
if (phdr_vaddr != EA_UNDEF &&
segs[i]->p_vaddr <= phdr_vaddr &&
@@ -337,10 +363,15 @@
memset(clear_addr, 0, nclear);
/* Non-file portion of BSS mapped above. */
#endif
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ if (phtls != NULL)
+ obj->tlsinit = mapbase + tls_vaddr;
+#endif
+
obj->mapbase = mapbase;
obj->mapsize = mapsize;
obj->relocbase = mapbase - base_vaddr;
if (obj->dynamic)
@@ -366,10 +397,14 @@
void
_rtld_obj_free(Obj_Entry *obj)
{
Objlist_Entry *elm;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ if (obj->tls_done)
+ _rtld_tls_offset_free(obj);
+#endif
xfree(obj->path);
while (obj->needed != NULL) {
Needed_Entry *needed = obj->needed;
obj->needed = needed->next;
xfree(needed);
Index: src/libexec/ld.elf_so/rtld.c
===================================================================
--- src/libexec/ld.elf_so/rtld.c
+++ src/libexec/ld.elf_so/rtld.c
@@ -313,10 +313,13 @@
*pAUX_ruid, *pAUX_rgid;
const AuxInfo *pAUX_pagesz;
char **env, **oenvp;
const AuxInfo *aux;
const AuxInfo *auxp;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ Obj_Entry *obj;
+#endif
Elf_Addr *const osp = sp;
bool bind_now = 0;
const char *ld_bind_now, *ld_preload, *ld_library_path;
const char **argv;
const char *execname;
@@ -570,10 +573,20 @@
}
dbg(("loading needed objects"));
if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
_rtld_die();
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ dbg(("initializing initial Thread Local Storage"));
+ /*
+ * All initial objects get the TLS space from the static block.
+ */
+ for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
+ _rtld_tls_offset_allocate(obj);
+ _rtld_tls_initial_allocation();
+#endif
dbg(("relocating objects"));
if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
_rtld_die();
Index: src/libexec/ld.elf_so/rtld.h
===================================================================
--- src/libexec/ld.elf_so/rtld.h
+++ src/libexec/ld.elf_so/rtld.h
@@ -39,10 +39,11 @@
#include <stddef.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/exec_elf.h>
+#include <sys/tls.h>
#include "rtldenv.h"
#include "link.h"
#if defined(_RTLD_SOURCE)
@@ -209,10 +210,14 @@
* priority over others */
z_noopen:1, /* True if object should never be
dlopen'ed */
phdr_loaded:1, /* Phdr is loaded and doesn't need to
* be freed. */
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ tls_done:1, /* True if static TLS offset
+ * has been allocated */
+#endif
ref_nodel:1; /* Refcount increased to prevent
dlclose */
struct link_map linkmap; /* for GDB */
/* These items are computed by map_object() or by digest_phdr(). */
@@ -229,12 +234,23 @@
uint8_t nbuckets_s1;
uint8_t nbuckets_s2;
size_t pathlen; /* Pathname length */
STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this
object we
know about. */
+
#ifdef __powerpc__
Elf_Addr *gotptr; /* GOT table (secure-plt only) */
+#endif
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ /* Thread Local Storage support for this module */
+ size_t tlsindex; /* Index in DTV */
+ void *tlsinit; /* Base address of TLS init block */
+ size_t tlsinitsize; /* Size of TLS init block */
+ size_t tlssize; /* Size of TLS block */
+ size_t tlsoffset; /* Offset in the static TLS block */
+ size_t tlsalign; /* Needed alignment for static TLS */
#endif
} Obj_Entry;
typedef struct Struct_DoneList {
const Obj_Entry **objs; /* Array of object pointers */
@@ -265,10 +281,13 @@
/* Flags for _rtld_load_object() and friends. */
#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */
#define _RTLD_MAIN 0x02
#define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */
#define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen().
*/
+
+/* Preallocation for static TLS model */
+#define RTLD_STATIC_TLS_RESERVATION 64
/* rtld.c */
/* We export these symbols using _rtld_symbol_lookup and is_exported. */
__dso_public char *dlerror(void);
@@ -340,10 +359,22 @@
const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
const Needed_Entry *, const Obj_Entry **, bool,
DoneList *, DoneList *);
#ifdef COMBRELOC
void _rtld_combreloc_reset(const Obj_Entry *);
+#endif
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+/* tls.c */
+void *_rtld_tls_get_addr(void *, size_t, size_t);
+void _rtld_tls_initial_allocation(void);
+void *_rtld_tls_module_allocate(size_t index);
+int _rtld_tls_offset_allocate(Obj_Entry *);
+void _rtld_tls_offset_free(Obj_Entry *);
+
+extern size_t _rtld_tls_dtv_generation;
+extern size_t _rtld_tls_max_index;
#endif
/* map_object.c */
struct stat;
Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
Index: src/libexec/ld.elf_so/symbol.c
===================================================================
--- src/libexec/ld.elf_so/symbol.c
+++ src/libexec/ld.elf_so/symbol.c
@@ -83,18 +83,27 @@
}
static bool
_rtld_is_exported(const Elf_Sym *def)
{
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ extern void __tls_get_addr(void *);
+#endif
+
static const fptr_t _rtld_exports[] = {
(fptr_t)dlopen,
(fptr_t)dlclose,
(fptr_t)dlsym,
(fptr_t)dlerror,
(fptr_t)dladdr,
(fptr_t)dlinfo,
(fptr_t)dl_iterate_phdr,
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+ (fptr_t)_rtld_tls_allocate,
+ (fptr_t)_rtld_tls_free,
+ (fptr_t)__tls_get_addr,
+#endif
NULL
};
int i;
fptr_t value;
ADDED src/libexec/ld.elf_so/tls.c
Index: src/libexec/ld.elf_so/tls.c
===================================================================
--- src/libexec/ld.elf_so/tls.c
+++ src/libexec/ld.elf_so/tls.c
@@ -0,0 +1,235 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <sys/param.h>
+#include <lwp.h>
+#include <string.h>
+#include "rtld.h"
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+
+static size_t _rtld_tls_static_space; /* Static TLS space allocated */
+static size_t _rtld_tls_static_offset; /* Next offset for static TLS to use */
+size_t _rtld_tls_dtv_generation = 1;
+size_t _rtld_tls_max_index = 1;
+
+#define DTV_GENERATION(dtv) ((size_t)((dtv)[0]))
+#define DTV_MAX_INDEX(dtv) ((size_t)((dtv)[-1]))
+#define SET_DTV_GENERATION(dtv, val) (dtv)[0] = (void *)(size_t)(val)
+#define SET_DTV_MAX_INDEX(dtv, val) (dtv)[-1] = (void
*)(size_t)(val)
+
+void *
+_rtld_tls_get_addr(void *tls, size_t idx, size_t offset)
+{
+ struct tls_tcb *tcb = tls;
+ void **dtv, **new_dtv;
+
+ dtv = tcb->tcb_dtv;
+
+ if (__predict_false(DTV_GENERATION(dtv) != _rtld_tls_dtv_generation)) {
+ size_t to_copy = DTV_MAX_INDEX(dtv);
+
+ new_dtv = xcalloc((2 + _rtld_tls_max_index) * sizeof(*dtv));
+ ++new_dtv;
+ if (to_copy > _rtld_tls_max_index)
+ to_copy = _rtld_tls_max_index;
+ memcpy(new_dtv + 1, dtv + 1, to_copy * sizeof(*dtv));
+ xfree(dtv - 1);
+ dtv = tcb->tcb_dtv = new_dtv;
+ SET_DTV_MAX_INDEX(dtv, _rtld_tls_max_index);
+ SET_DTV_GENERATION(dtv, _rtld_tls_dtv_generation);
+ }
+
+ if (__predict_false(dtv[idx] == NULL))
+ dtv[idx] = _rtld_tls_module_allocate(idx);
+
+ return (uint8_t *)dtv[idx] + offset;
+}
+
+void
+_rtld_tls_initial_allocation(void)
+{
+ struct tls_tcb *tcb;
+
+ _rtld_tls_static_space = _rtld_tls_static_offset +
+ RTLD_STATIC_TLS_RESERVATION;
+
+#ifndef __HAVE_TLS_VARIANT_I
+ _rtld_tls_static_space = roundup2(_rtld_tls_static_space,
+ sizeof(void *));
+#endif
+
+ tcb = _rtld_tls_allocate();
+ _lwp_setprivate(tcb);
+}
+
+struct tls_tcb *
+_rtld_tls_allocate(void)
+{
+ Obj_Entry *obj;
+ struct tls_tcb *tcb;
+ uint8_t *p, *q;
+
+ p = xcalloc(_rtld_tls_static_space + sizeof(struct tls_tcb));
+#ifdef __HAVE_TLS_VARIANT_I
+ tcb = (struct tls_tcb *)p;
+ p += sizeof(struct tls_tcb);
+#else
+ p += _rtld_tls_static_space;
+ tcb = (struct tls_tcb *)p;
+ tcb->tcb_self = tcb;
+#endif
+ tcb->tcb_dtv = xcalloc(sizeof(*tcb->tcb_dtv) * (2 +
_rtld_tls_max_index));
+ ++tcb->tcb_dtv;
+ SET_DTV_MAX_INDEX(tcb->tcb_dtv, _rtld_tls_max_index);
+ SET_DTV_GENERATION(tcb->tcb_dtv, _rtld_tls_dtv_generation);
+
+ for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
+ if (obj->tlssize) {
+#ifdef __HAVE_TLS_VARIANT_I
+ q = p + obj->tlsoffset;
+#else
+ q = p - obj->tlsoffset;
+#endif
+ memcpy(q, obj->tlsinit, obj->tlsinitsize);
+ tcb->tcb_dtv[obj->tlsindex] = q;
+ }
+ }
+
+ return tcb;
+}
+
+void
+_rtld_tls_free(struct tls_tcb *tcb)
+{
+ size_t i, max_index;
+ uint8_t *p;
+
+ 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
+ xfree(p);
+}
+
+void *
+_rtld_tls_module_allocate(size_t idx)
+{
+ Obj_Entry *obj;
+ uint8_t *p;
+
+ for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
+ if (obj->tlsindex == idx)
+ break;
+ }
+ if (obj == NULL) {
+ _rtld_error("Module for TLS index %zu missing", idx);
+ _rtld_die();
+ }
+
+ p = xmalloc(obj->tlssize);
+ memcpy(p, obj->tlsinit, obj->tlsinitsize);
+ memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
+
+ return p;
+}
+
+int
+_rtld_tls_offset_allocate(Obj_Entry *obj)
+{
+ size_t offset, next_offset;
+
+ if (obj->tls_done)
+ return 0;
+ if (obj->tlssize == 0) {
+ obj->tlsoffset = 0;
+ obj->tls_done = 1;
+ return 0;
+ }
+
+#ifdef __HAVE_TLS_VARIANT_I
+ offset = roundup2(_rtld_tls_static_offset, obj->tlsalign);
+ next_offset = offset + obj->tlssize;
+#else
+ offset = roundup2(_rtld_tls_static_offset + obj->tlssize,
+ obj->tlsalign);
+ next_offset = offset;
+#endif
+
+ /*
+ * Check if the static allocation was already done.
+ * This happens if dynamically loaded modules want to use
+ * static TLS space.
+ *
+ * XXX Keep an actual free list and callbacks for initialisation.
+ */
+ if (_rtld_tls_static_space) {
+ if (obj->tlsinitsize) {
+ _rtld_error("%s: Use of initialized "
+ "Thread Locale Storage with model initial-exec "
+ "and dlopen is not supported",
+ obj->path);
+ return -1;
+ }
+ if (next_offset > _rtld_tls_static_space) {
+ _rtld_error("%s: No space available "
+ "for static Thread Local Storage",
+ obj->path);
+ return -1;
+ }
+ }
+ obj->tlsoffset = offset;
+ _rtld_tls_static_offset = next_offset;
+ obj->tls_done = 1;
+
+ return 0;
+}
+
+void
+_rtld_tls_offset_free(Obj_Entry *obj)
+{
+
+ /*
+ * XXX See above.
+ */
+ obj->tls_done = 0;
+ return;
+}
+
+#endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
Index: src/rescue/list.ldd
===================================================================
--- src/rescue/list.ldd
+++ src/rescue/list.ldd
@@ -3,11 +3,11 @@
PROG ldd
LIBS ${LDD_ELF32DIR}/libldd_elf32.a
LIBS ${LDD_ELF64DIR}/libldd_elf64.a
-SPECIAL ldd keepsymbols _rtld_pagesz _rtld_error _rtld_trust
+SPECIAL ldd keepsymbols _rtld_pagesz _rtld_die _rtld_error _rtld_trust
SPECIAL ldd keepsymbols _rtld_default_paths _rtld_paths
SPECIAL ldd keepsymbols _rtld_xforms _rtld_objmain
SPECIAL ldd keepsymbols _rtld_objtail _rtld_objlist
SPECIAL ldd keepsymbols _rtld_objcount _rtld_objloads
SPECIAL ldd keepsymbols print_needed main_local main_progname
Index: src/sys/sys/Makefile
===================================================================
--- src/sys/sys/Makefile
+++ src/sys/sys/Makefile
@@ -34,11 +34,11 @@
sleepq.h socket.h \
socketvar.h sockio.h specificdata.h stat.h statvfs.h \
syscall.h syscallargs.h sysctl.h stdint.h swap.h \
syncobj.h syslimits.h syslog.h \
tape.h termios.h time.h timeb.h timepps.h times.h \
- timex.h trace.h tree.h tty.h ttychars.h ttycom.h \
+ timex.h tls.h trace.h tree.h tty.h ttychars.h ttycom.h \
ttydefaults.h ttydev.h types.h \
ucontext.h ucred.h uio.h un.h unistd.h unpcb.h user.h utsname.h uuid.h \
vadvise.h verified_exec.h videoio.h vmmeter.h vnode.h vnode_if.h \
wait.h wapbl.h wapbl_replay.h wdog.h
ADDED src/sys/sys/tls.h
Index: src/sys/sys/tls.h
===================================================================
--- src/sys/sys/tls.h
+++ src/sys/sys/tls.h
@@ -0,0 +1,61 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_TLS_H_
+#define _SYS_TLS_H_
+
+#include <sys/cdefs.h>
+#include <machine/types.h>
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+
+#if defined(__HAVE_TLS_VARIANT_I) && defined(__HAVE_TLS_VARIANT_II)
+#error Only one TLS variant can be supported at a time
+#endif
+
+struct tls_tcb {
+#ifdef __HAVE_TLS_VARIANT_I
+ void **tcb_dtv;
+ void *tcb_pthread;
+#else
+ void *tcb_self;
+ void **tcb_dtv;
+ void *tcb_pthread;
+#endif
+};
+
+__BEGIN_PUBLIC_DECLS
+struct tls_tcb *_rtld_tls_allocate(void);
+void _rtld_tls_free(struct tls_tcb *);
+void _rtld_tls_static_setup(void);
+__END_PUBLIC_DECLS
+#endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
+
+#endif /* _SYS_TLS_H_ */
Index: src/tests/lib/libc/Makefile
===================================================================
--- src/tests/lib/libc/Makefile
+++ src/tests/lib/libc/Makefile
@@ -1,12 +1,14 @@
# $NetBSD: Makefile,v 1.37 2011/01/13 14:32:35 pgoyette Exp $
.include <bsd.own.mk>
.include <bsd.sys.mk>
+SUBDIR+= tls_dso .WAIT
+
TESTS_SUBDIRS+= db gen hash ieeefp inet net regex rpc setjmp stdlib
-TESTS_SUBDIRS+= stdio string sys time ttyio
+TESTS_SUBDIRS+= stdio string sys time tls ttyio
.if ${HAS_SSP} == "yes"
TESTS_SUBDIRS+= ssp
.endif
ADDED src/tests/lib/libc/tls/Makefile
Index: src/tests/lib/libc/tls/Makefile
===================================================================
--- src/tests/lib/libc/tls/Makefile
+++ src/tests/lib/libc/tls/Makefile
@@ -0,0 +1,15 @@
+# $NetBSD$
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/lib/libc/tls
+SUBDIR+= dso
+
+TESTS_C+= t_tls_static t_tls_dynamic t_tls_dlopen
+SRCS.t_tls_static= t_tls_static.c t_tls_static_helper.c
+LDADD.t_tls_static+= -lpthread -static
+LDADD.t_tls_dynamic+= -lpthread \
+ -Wl,-rpath,${TESTSDIR} -L../tls_dso -lh_tls_dynamic
+LDADD.t_tls_dlopen+= -lpthread -Wl,-rpath,${TESTSDIR} -Wl,-export-dynamic
+
+.include <bsd.test.mk>
ADDED src/tests/lib/libc/tls/dso/Makefile
Index: src/tests/lib/libc/tls/dso/Makefile
===================================================================
--- src/tests/lib/libc/tls/dso/Makefile
+++ src/tests/lib/libc/tls/dso/Makefile
@@ -0,0 +1,18 @@
+# $NetBSD$
+
+NOMAN= # defined
+NOLINT= # defined
+
+.include <bsd.own.mk>
+
+LIB= h_tls_dlopen
+SRCS= h_tls_dlopen.c
+
+LIBDIR= ${TESTSBASE}/lib/libc/tls
+SHLIBDIR= ${TESTSBASE}/lib/libc/tls
+SHLIB_MAJOR= 1
+
+LIBISCXX= yes
+LIBISMODULE= yes
+
+.include <bsd.lib.mk>
ADDED src/tests/lib/libc/tls/dso/h_tls_dlopen.c
Index: src/tests/lib/libc/tls/dso/h_tls_dlopen.c
===================================================================
--- src/tests/lib/libc/tls/dso/h_tls_dlopen.c
+++ src/tests/lib/libc/tls/dso/h_tls_dlopen.c
@@ -0,0 +1,53 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+extern __thread int var1;
+extern __thread int var2;
+
+void testf_dso_helper(int x, int y);
+
+void
+testf_dso_helper(int x, int y)
+{
+ var1 = x;
+ var2 = y;
+}
ADDED src/tests/lib/libc/tls/t_tls_dlopen.c
Index: src/tests/lib/libc/tls/t_tls_dlopen.c
===================================================================
--- src/tests/lib/libc/tls/t_tls_dlopen.c
+++ src/tests/lib/libc/tls/t_tls_dlopen.c
@@ -0,0 +1,106 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <atf-c.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+ATF_TC(t_tls_dlopen);
+
+ATF_TC_HEAD(t_tls_dlopen, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test (un)initialized TLS variables and dlopen");
+}
+
+void (*testf_helper)(int, int);
+
+__thread int var1 = 1;
+__thread int var2;
+
+static void *
+testf(void *dummy)
+{
+ ATF_CHECK_EQ(var1, 1);
+ ATF_CHECK_EQ(var2, 0);
+ testf_helper(2, 2);
+ ATF_CHECK_EQ(var1, 2);
+ ATF_CHECK_EQ(var2, 2);
+ testf_helper(3, 3);
+ ATF_CHECK_EQ(var1, 3);
+ ATF_CHECK_EQ(var2, 3);
+
+ return NULL;
+}
+
+ATF_TC_BODY(t_tls_dlopen, tc)
+{
+ void *handle;
+ pthread_t t;
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+ atf_tc_skip("no TLS support on this platform");
+#endif
+
+ handle = dlopen("h_tls_dlopen.so", RTLD_NOW | RTLD_LOCAL);
+ ATF_REQUIRE(handle != NULL);
+
+ testf_helper = dlsym(handle, "testf_dso_helper");
+ ATF_REQUIRE(testf_helper != NULL);
+
+ testf(NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+
+ dlclose(handle);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, t_tls_dlopen);
+
+ return atf_no_error();
+}
ADDED src/tests/lib/libc/tls/t_tls_dynamic.c
Index: src/tests/lib/libc/tls/t_tls_dynamic.c
===================================================================
--- src/tests/lib/libc/tls/t_tls_dynamic.c
+++ src/tests/lib/libc/tls/t_tls_dynamic.c
@@ -0,0 +1,96 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <atf-c.h>
+#include <pthread.h>
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+ATF_TC(t_tls_dynamic);
+
+ATF_TC_HEAD(t_tls_dynamic, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test (un)initialized TLS variables in dynamic binaries");
+}
+
+void testf_dso_helper(int, int);
+
+extern __thread int var1;
+extern __thread int var2;
+
+static void *
+testf(void *dummy)
+{
+ ATF_CHECK_EQ(var1, 1);
+ ATF_CHECK_EQ(var2, 0);
+ testf_dso_helper(2, 2);
+ ATF_CHECK_EQ(var1, 2);
+ ATF_CHECK_EQ(var2, 2);
+ testf_dso_helper(3, 3);
+ ATF_CHECK_EQ(var1, 3);
+ ATF_CHECK_EQ(var2, 3);
+
+ return NULL;
+}
+
+ATF_TC_BODY(t_tls_dynamic, tc)
+{
+ pthread_t t;
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+ atf_tc_skip("no TLS support on this platform");
+#endif
+
+ testf(NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, t_tls_dynamic);
+
+ return atf_no_error();
+}
ADDED src/tests/lib/libc/tls/t_tls_static.c
Index: src/tests/lib/libc/tls/t_tls_static.c
===================================================================
--- src/tests/lib/libc/tls/t_tls_static.c
+++ src/tests/lib/libc/tls/t_tls_static.c
@@ -0,0 +1,93 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <atf-c.h>
+#include <pthread.h>
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+ATF_TC(t_tls_static);
+
+ATF_TC_HEAD(t_tls_static, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test (un)initialized TLS variables in static binaries");
+}
+
+void testf_helper(void);
+
+__thread int var1 = 1;
+__thread int var2;
+
+static void *
+testf(void *dummy)
+{
+ ATF_CHECK_EQ(var1, 1);
+ ATF_CHECK_EQ(var2, 0);
+ testf_helper();
+ ATF_CHECK_EQ(var1, -1);
+ ATF_CHECK_EQ(var2, -1);
+
+ return NULL;
+}
+
+ATF_TC_BODY(t_tls_static, tc)
+{
+ pthread_t t;
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+ atf_tc_skip("no TLS support on this platform");
+#endif
+
+ testf(NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+
+ pthread_create(&t, 0, testf, 0);
+ pthread_join(t, NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, t_tls_static);
+
+ return atf_no_error();
+}
ADDED src/tests/lib/libc/tls/t_tls_static_helper.c
Index: src/tests/lib/libc/tls/t_tls_static_helper.c
===================================================================
--- src/tests/lib/libc/tls/t_tls_static_helper.c
+++ src/tests/lib/libc/tls/t_tls_static_helper.c
@@ -0,0 +1,53 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+extern __thread int var1;
+extern __thread int var2;
+
+void testf_helper(void);
+
+void
+testf_helper(void)
+{
+ var1 = -1;
+ var2 = -1;
+}
ADDED src/tests/lib/libc/tls_dso/Makefile
Index: src/tests/lib/libc/tls_dso/Makefile
===================================================================
--- src/tests/lib/libc/tls_dso/Makefile
+++ src/tests/lib/libc/tls_dso/Makefile
@@ -0,0 +1,20 @@
+# $NetBSD: Makefile,v 1.1 2010/07/28 13:51:40 joerg Exp $
+
+.include <bsd.own.mk>
+
+LIB= h_tls_dynamic
+SRCS= h_tls_dynamic.c
+
+LIBDIR= ${TESTSBASE}/lib/libc/tls
+SHLIBDIR= ${TESTSBASE}/lib/libc/tls
+SHLIB_MAJOR= 1
+
+LIBISCXX= yes
+MKSTATICLIB= no
+MKPROFILE= no
+MKPICINSTALL= no
+MKLINT= no
+
+NOMAN= # defined
+
+.include <bsd.lib.mk>
ADDED src/tests/lib/libc/tls_dso/h_tls_dynamic.c
Index: src/tests/lib/libc/tls_dso/h_tls_dynamic.c
===================================================================
--- src/tests/lib/libc/tls_dso/h_tls_dynamic.c
+++ src/tests/lib/libc/tls_dso/h_tls_dynamic.c
@@ -0,0 +1,53 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <sys/tls.h>
+
+#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II)
+#define __thread
+#endif
+
+__thread int var1 = 1;
+__thread int var2;
+
+void testf_dso_helper(int x, int y);
+
+void
+testf_dso_helper(int x, int y)
+{
+ var1 = x;
+ var2 = y;
+}
Index: src/usr.bin/ldd/Makefile.elf
===================================================================
--- src/usr.bin/ldd/Makefile.elf
+++ src/usr.bin/ldd/Makefile.elf
@@ -3,8 +3,8 @@
# Makefile fragment to build a (32 or 64 bit) libldd_elfxx.a.
# Expects CPPFLAGS to have ELFSIZE set, and LIB to be set.
SRCS= ldd_elfxx.c
SRCS+= xmalloc.c debug.c expand.c map_object.c load.c search.c \
- headers.c paths.c
+ headers.c paths.c tls.c
.include "Makefile.common"
Index: src/usr.bin/ldd/elf32/Makefile
===================================================================
--- src/usr.bin/ldd/elf32/Makefile
+++ src/usr.bin/ldd/elf32/Makefile
@@ -1,9 +1,17 @@
# $NetBSD: Makefile,v 1.7 2009/12/13 08:50:56 mrg Exp $
.include <bsd.own.mk>
.include <bsd.init.mk>
+
+RTLD_FUNCS = \
+ _rtld_tls_allocate \
+ _rtld_tls_free \
+
+.for _d in ${RTLD_FUNCS}
+CPPFLAGS+= -D${_d}=_elf32_${_d}
+.endfor
CPPFLAGS+= -DELFSIZE=32
LIB= ldd_elf32
# XXX Force one member
Index: src/usr.bin/ldd/elf64/Makefile
===================================================================
--- src/usr.bin/ldd/elf64/Makefile
+++ src/usr.bin/ldd/elf64/Makefile
@@ -28,10 +28,12 @@
_rtld_obj_free \
_rtld_obj_new \
_rtld_add_paths \
_rtld_process_hints \
_rtld_sysctl \
+ _rtld_tls_allocate \
+ _rtld_tls_free \
_rtld_load_library
.for _d in ${RTLD_FUNCS}
CPPFLAGS+= -D${_d}=_elf64_${_d}
.endfor
Index: src/usr.bin/ldd/ldd.c
===================================================================
--- src/usr.bin/ldd/ldd.c
+++ src/usr.bin/ldd/ldd.c
@@ -300,6 +300,16 @@
}
} else {
fmtprint(libname, needed->obj, fmt1, fmt2);
}
}
+}
+
+void
+_rtld_die(void)
+{
+ const char *msg = dlerror();
+
+ if (msg == NULL)
+ msg = "Fatal error";
+ xerrx(1, "%s", msg);
}
Index: src/libexec/ld.elf_so/arch/sh3/Makefile.inc
===================================================================
--- src/libexec/ld.elf_so/arch/sh3/Makefile.inc
+++ src/libexec/ld.elf_so/arch/sh3/Makefile.inc
@@ -1,10 +1,10 @@
# $NetBSD: Makefile.inc,v 1.7 2005/06/04 16:17:17 lukem Exp $
-SRCS+= rtld_start.S mdreloc.c
+SRCS+= rtld_start.S mdreloc.c mdtls.c
# XXX Should not be in CPPFLAGS!
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=32
LDFLAGS+= -Wl,-e,.rtld_start
Index: src/libexec/ld.elf_so/arch/sh3/mdreloc.c
===================================================================
--- src/libexec/ld.elf_so/arch/sh3/mdreloc.c
+++ src/libexec/ld.elf_so/arch/sh3/mdreloc.c
@@ -9,10 +9,11 @@
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.28 2010/08/06 16:33:18 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
+#include <sys/tls.h>
#include "debug.h"
#include "rtld.h"
void _rtld_bind_start(void);
@@ -152,10 +153,53 @@
return -1;
}
rdbg(("COPY (avoid in main)"));
break;
+ case R_TYPE(TLS_DTPOFF32):
+ def = _rtld_find_symdef(symnum, obj, &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr)(def->st_value);
+
+ rdbg(("TLS_DTPOFF32 %s in %s --> %p",
+ obj->strtab + obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+
+ break;
+ case R_TYPE(TLS_DTPMOD32):
+ def = _rtld_find_symdef(symnum, obj, &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr)(defobj->tlsindex);
+
+ rdbg(("TLS_DTPMOD32 %s in %s --> %p",
+ obj->strtab + obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+
+ break;
+
+ case R_TYPE(TLS_TPOFF32):
+ def = _rtld_find_symdef(symnum, obj, &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ if (!defobj->tls_done &&
+ _rtld_tls_offset_allocate(obj))
+ return -1;
+
+ *where = (Elf_Addr)def->st_value +
+ rela->r_addend + defobj->tlsoffset +
+ sizeof(struct tls_tcb);
+
+ rdbg(("TLS_TPOFF32 %s in %s --> %p",
+ obj->strtab + obj->symtab[symnum].st_name,
+ obj->path, (void *)*where));
+ break;
+
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
symnum, (u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
@@ -165,10 +209,11 @@
"in non-PLT relocations",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
}
+
return 0;
}
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
ADDED src/libexec/ld.elf_so/arch/sh3/mdtls.c
Index: src/libexec/ld.elf_so/arch/sh3/mdtls.c
===================================================================
--- src/libexec/ld.elf_so/arch/sh3/mdtls.c
+++ src/libexec/ld.elf_so/arch/sh3/mdtls.c
@@ -1,0 +1,17 @@
+#include <sys/cdefs.h>
+
+__RCSID("$NetBSD$");
+
+#include <sys/tls.h>
+#include "rtld.h"
+
+__dso_public void *__tls_get_addr(int[2]);
+
+void *
+__tls_get_addr(int idx[2])
+{
+ void *p;
+
+ asm volatile ("stc\tgbr, %0" : "=r" (p));
+ return _rtld_tls_get_addr(p, idx[0], idx[1]);
+}
Index: src/sys/arch/sh3/include/types.h
===================================================================
--- src/sys/arch/sh3/include/types.h
+++ src/sys/arch/sh3/include/types.h
@@ -77,7 +77,8 @@
#define __HAVE_RAS
#endif
#define __HAVE_CPU_LWP_SETPRIVATE
#define __HAVE___LWP_GETPRIVATE_FAST
+#define __HAVE_TLS_VARIANT_I
#endif /* !_SH3_TYPES_H_ */
Home |
Main Index |
Thread Index |
Old Index