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