Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add TLS support infrastructure. For dynamic binaries, ld.elf...
details: https://anonhg.NetBSD.org/src/rev/11c4ca8d8815
branches: trunk
changeset: 763080:11c4ca8d8815
user: joerg <joerg%NetBSD.org@localhost>
date: Wed Mar 09 23:10:05 2011 +0000
description:
Add TLS support infrastructure. For dynamic binaries, ld.elf_so exports
_rtld_tls_allocate and _rtld_tls_free. libpthread uses this functions to
setup the thread private area of all new threads. ld.elf_so is
responsible for setting up the private area for the initial thread.
Similar functions are called from _libc_init for static binaries, using
dl_iterate_phdr to access the ELF Program Header.
Add test cases to exercise the different TLS storage models. Test cases
are compiled and installed on all platforms, but are skipped on
platforms not marked for TLS support.
This material is based upon work partially supported by
The NetBSD Foundation under a contract with Joerg Sonnenberger.
It is inspired by the TLS support in FreeBSD by Doug Rabson and the
clean ups of the DragonFly port of the original FreeBSD modifications.
diffstat:
distrib/sets/lists/comp/mi | 3 +-
distrib/sets/lists/tests/mi | 15 +-
etc/mtree/NetBSD.dist.tests | 4 +-
lib/libc/Makefile | 3 +-
lib/libc/misc/initfini.c | 14 +-
lib/libc/tls/Makefile.inc | 8 +
lib/libc/tls/tls.c | 156 ++++++++++++++++++++
lib/libpthread/pthread.c | 35 +++-
lib/libpthread/pthread_int.h | 16 +-
libexec/ld.elf_so/Makefile | 5 +-
libexec/ld.elf_so/README.TLS | 81 ++++++++++
libexec/ld.elf_so/TODO | 4 +
libexec/ld.elf_so/headers.c | 14 +-
libexec/ld.elf_so/map_object.c | 39 ++++-
libexec/ld.elf_so/rtld.c | 17 +-
libexec/ld.elf_so/rtld.h | 35 ++++-
libexec/ld.elf_so/symbol.c | 9 +-
libexec/ld.elf_so/tls.c | 235 +++++++++++++++++++++++++++++++
rescue/list.ldd | 4 +-
sys/sys/Makefile | 4 +-
sys/sys/tls.h | 61 ++++++++
tests/lib/libc/Makefile | 6 +-
tests/lib/libc/tls/Makefile | 15 +
tests/lib/libc/tls/dso/Makefile | 18 ++
tests/lib/libc/tls/dso/h_tls_dlopen.c | 53 ++++++
tests/lib/libc/tls/t_tls_dlopen.c | 106 +++++++++++++
tests/lib/libc/tls/t_tls_dynamic.c | 96 ++++++++++++
tests/lib/libc/tls/t_tls_static.c | 93 ++++++++++++
tests/lib/libc/tls/t_tls_static_helper.c | 53 ++++++
tests/lib/libc/tls_dso/Makefile | 20 ++
tests/lib/libc/tls_dso/h_tls_dynamic.c | 53 ++++++
usr.bin/ldd/Makefile.elf | 4 +-
usr.bin/ldd/elf32/Makefile | 10 +-
usr.bin/ldd/elf64/Makefile | 4 +-
usr.bin/ldd/ldd.c | 14 +-
35 files changed, 1271 insertions(+), 36 deletions(-)
diffs (truncated from 1861 to 300 lines):
diff -r ccbcf683594e -r 11c4ca8d8815 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi Wed Mar 09 22:26:36 2011 +0000
+++ b/distrib/sets/lists/comp/mi Wed Mar 09 23:10:05 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1594 2011/03/07 15:49:56 njoly Exp $
+# $NetBSD: mi,v 1.1595 2011/03/09 23:10:05 joerg Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -2173,6 +2173,7 @@
./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
diff -r ccbcf683594e -r 11c4ca8d8815 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi Wed Mar 09 22:26:36 2011 +0000
+++ b/distrib/sets/lists/tests/mi Wed Mar 09 23:10:05 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.262 2011/03/09 19:04:57 bouyer Exp $
+# $NetBSD: mi,v 1.263 2011/03/09 23:10:05 joerg Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -420,6 +420,10 @@
./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
@@ -1848,6 +1852,15 @@
./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
diff -r ccbcf683594e -r 11c4ca8d8815 etc/mtree/NetBSD.dist.tests
--- a/etc/mtree/NetBSD.dist.tests Wed Mar 09 22:26:36 2011 +0000
+++ b/etc/mtree/NetBSD.dist.tests Wed Mar 09 23:10:05 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: NetBSD.dist.tests,v 1.30 2011/03/06 17:08:12 bouyer Exp $
+# $NetBSD: NetBSD.dist.tests,v 1.31 2011/03/09 23:10:06 joerg Exp $
./usr/libdata/debug/usr/tests
./usr/libdata/debug/usr/tests/atf
@@ -61,6 +61,7 @@
./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
@@ -175,6 +176,7 @@
./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
diff -r ccbcf683594e -r 11c4ca8d8815 lib/libc/Makefile
--- a/lib/libc/Makefile Wed Mar 09 22:26:36 2011 +0000
+++ b/lib/libc/Makefile Wed Mar 09 23:10:05 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.143 2010/09/04 12:17:58 ahoka Exp $
+# $NetBSD: Makefile,v 1.144 2011/03/09 23:10:06 joerg Exp $
# @(#)Makefile 8.2 (Berkeley) 2/3/94
#
# All library objects contain sccsid strings by default; they may be
@@ -92,6 +92,7 @@
.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")
diff -r ccbcf683594e -r 11c4ca8d8815 lib/libc/misc/initfini.c
--- a/lib/libc/misc/initfini.c Wed Mar 09 22:26:36 2011 +0000
+++ b/lib/libc/misc/initfini.c Wed Mar 09 23:10:05 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: initfini.c,v 1.8 2011/03/07 05:09:11 joerg Exp $ */
+/* $NetBSD: initfini.c,v 1.9 2011/03/09 23:10:06 joerg Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: initfini.c,v 1.8 2011/03/07 05:09:11 joerg Exp $");
+__RCSID("$NetBSD: initfini.c,v 1.9 2011/03/09 23:10:06 joerg Exp $");
#ifdef _LIBC
#include "namespace.h"
@@ -38,6 +38,7 @@
#include <sys/param.h>
#include <sys/exec.h>
+#include <sys/tls.h>
#include <stdbool.h>
void _libc_init(void) __attribute__((__constructor__, __used__));
@@ -48,6 +49,10 @@
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);
@@ -78,6 +83,11 @@
/* 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();
diff -r ccbcf683594e -r 11c4ca8d8815 lib/libc/tls/Makefile.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libc/tls/Makefile.inc Wed Mar 09 23:10:05 2011 +0000
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile.inc,v 1.1 2011/03/09 23:10:06 joerg Exp $
+
+.include <bsd.own.mk>
+
+# Our sources
+.PATH: ${.PARSEDIR} ${ARCHDIR}/tls
+
+SRCS+= tls.c
diff -r ccbcf683594e -r 11c4ca8d8815 lib/libc/tls/tls.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libc/tls/tls.c Wed Mar 09 23:10:05 2011 +0000
@@ -0,0 +1,156 @@
+/* $NetBSD: tls.c,v 1.1 2011/03/09 23:10:06 joerg Exp $ */
+
+/*-
+ * 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: tls.c,v 1.1 2011/03/09 23:10:06 joerg Exp $");
+
+#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;
+}
Home |
Main Index |
Thread Index |
Old Index