[BACK]Return to tls.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / tls

Annotation of src/lib/libc/tls/tls.c, Revision 1.12

1.11      joerg       1: /*     $NetBSD: tls.c,v 1.10 2019/11/04 12:45:10 joerg Exp $   */
1.1       joerg       2:
                      3: /*-
                      4:  * Copyright (c) 2011 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Joerg Sonnenberger.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.11      joerg      33: __RCSID("$NetBSD: tls.c,v 1.10 2019/11/04 12:45:10 joerg Exp $");
1.1       joerg      34:
                     35: #include "namespace.h"
                     36:
1.2       joerg      37: #define        _rtld_tls_allocate      __libc_rtld_tls_allocate
                     38: #define        _rtld_tls_free          __libc_rtld_tls_free
                     39:
1.1       joerg      40: #include <sys/tls.h>
                     41:
                     42: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/mman.h>
                     46: #include <link_elf.h>
                     47: #include <lwp.h>
1.9       joerg      48: #include <stdbool.h>
1.11      joerg      49: #include <stdalign.h>
1.1       joerg      50: #include <stddef.h>
                     51: #include <stdlib.h>
                     52: #include <string.h>
                     53: #include <unistd.h>
                     54:
                     55: __dso_hidden void      __libc_static_tls_setup(void);
                     56:
1.9       joerg      57: static bool is_dynamic;
1.1       joerg      58: static const void *tls_initaddr;
                     59: static size_t tls_initsize;
                     60: static size_t tls_size;
                     61: static size_t tls_allocation;
                     62: static void *initial_thread_tcb;
                     63:
1.4       skrll      64: void * __libc_tls_get_addr(void);
                     65:
                     66: __weak_alias(__tls_get_addr, __libc_tls_get_addr)
1.1       joerg      67: #ifdef __i386__
1.4       skrll      68: __weak_alias(___tls_get_addr, __libc_tls_get_addr)
1.1       joerg      69: #endif
                     70:
1.4       skrll      71: void *
                     72: __libc_tls_get_addr(void)
                     73: {
                     74:
                     75:        abort();
1.5       he         76:        /* NOTREACHED */
1.4       skrll      77: }
                     78:
1.1       joerg      79: __weak_alias(_rtld_tls_allocate, __libc_rtld_tls_allocate)
                     80:
                     81: struct tls_tcb *
                     82: _rtld_tls_allocate(void)
                     83: {
                     84:        struct tls_tcb *tcb;
                     85:        uint8_t *p;
                     86:
                     87:        if (initial_thread_tcb == NULL) {
                     88: #ifdef __HAVE_TLS_VARIANT_II
1.12    ! joerg      89:                tls_allocation = roundup2(tls_size, alignof(max_align_t));
        !            90: #else
        !            91:                tls_allocation = tls_size;
1.1       joerg      92: #endif
                     93:
1.12    ! joerg      94:                initial_thread_tcb = p = mmap(NULL,
        !            95:                    tls_allocation + sizeof(*tcb), PROT_READ | PROT_WRITE,
        !            96:                    MAP_ANON, -1, 0);
1.1       joerg      97:        } else {
1.12    ! joerg      98:                p = calloc(1, tls_allocation + sizeof(*tcb));
1.1       joerg      99:        }
                    100:        if (p == NULL) {
                    101:                static const char msg[] =  "TLS allocation failed, terminating\n";
                    102:                write(STDERR_FILENO, msg, sizeof(msg));
                    103:                _exit(127);
                    104:        }
                    105: #ifdef __HAVE_TLS_VARIANT_I
                    106:        /* LINTED */
                    107:        tcb = (struct tls_tcb *)p;
                    108:        p += sizeof(struct tls_tcb);
                    109: #else
                    110:        /* LINTED tls_size is rounded above */
1.12    ! joerg     111:        tcb = (struct tls_tcb *)(p + tls_allocation);
        !           112:        p = (uint8_t *)tcb - tls_size;
1.1       joerg     113:        tcb->tcb_self = tcb;
                    114: #endif
                    115:        memcpy(p, tls_initaddr, tls_initsize);
                    116:
                    117:        return tcb;
                    118: }
                    119:
                    120: __weak_alias(_rtld_tls_free, __libc_rtld_tls_free)
                    121:
                    122: void
                    123: _rtld_tls_free(struct tls_tcb *tcb)
                    124: {
                    125:        uint8_t *p;
                    126:
                    127: #ifdef __HAVE_TLS_VARIANT_I
                    128:        /* LINTED */
                    129:        p = (uint8_t *)tcb;
                    130: #else
                    131:        /* LINTED */
1.12    ! joerg     132:        p = (uint8_t *)tcb - tls_allocation;
1.1       joerg     133: #endif
                    134:        if (p == initial_thread_tcb)
1.12    ! joerg     135:                munmap(p, tls_allocation + sizeof(*tcb));
1.1       joerg     136:        else
                    137:                free(p);
                    138: }
                    139:
1.7       matt      140: static int __section(".text.startup")
1.1       joerg     141: __libc_static_tls_setup_cb(struct dl_phdr_info *data, size_t len, void *cookie)
                    142: {
                    143:        const Elf_Phdr *phdr = data->dlpi_phdr;
                    144:        const Elf_Phdr *phlimit = data->dlpi_phdr + data->dlpi_phnum;
                    145:
                    146:        for (; phdr < phlimit; ++phdr) {
1.9       joerg     147:                if (phdr->p_type == PT_INTERP) {
                    148:                        is_dynamic = true;
                    149:                        return -1;
                    150:                }
1.1       joerg     151:                if (phdr->p_type != PT_TLS)
                    152:                        continue;
                    153:                tls_initaddr = (void *)(phdr->p_vaddr + data->dlpi_addr);
                    154:                tls_initsize = phdr->p_filesz;
                    155:                tls_size = phdr->p_memsz;
                    156:        }
                    157:        return 0;
                    158: }
                    159:
                    160: void
                    161: __libc_static_tls_setup(void)
                    162: {
                    163:        struct tls_tcb *tcb;
                    164:
1.9       joerg     165:        dl_iterate_phdr(__libc_static_tls_setup_cb, NULL);
                    166:        if (is_dynamic)
1.1       joerg     167:                return;
                    168:
                    169:        tcb = _rtld_tls_allocate();
1.3       matt      170: #ifdef __HAVE___LWP_SETTCB
                    171:        __lwp_settcb(tcb);
                    172: #else
1.1       joerg     173:        _lwp_setprivate(tcb);
1.3       matt      174: #endif
1.1       joerg     175: }
                    176:
                    177: #endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */

CVSweb <webmaster@jp.NetBSD.org>