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>