2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004 Doug Rabson
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * Define stubs for TLS internals so that programs and libraries can
33 * link. These functions will be replaced by functional versions at
34 * runtime from ld-elf.so.1.
37 #include <sys/cdefs.h>
38 #include <sys/param.h>
44 #include "libc_private.h"
46 #define tls_assert(cond) ((cond) ? (void) 0 : \
47 (tls_msg(#cond ": assert failed: " __FILE__ ":" \
48 __XSTRING(__LINE__) "\n"), abort()))
49 #define tls_msg(s) write(STDOUT_FILENO, s, strlen(s))
51 /* Provided by jemalloc to avoid bootstrapping issues. */
52 void *__je_bootstrap_malloc(size_t size);
53 void *__je_bootstrap_calloc(size_t num, size_t size);
54 void __je_bootstrap_free(void *ptr);
56 __weak_reference(__libc_allocate_tls, _rtld_allocate_tls);
57 __weak_reference(__libc_free_tls, _rtld_free_tls);
61 __weak_reference(___libc_tls_get_addr, ___tls_get_addr);
62 __attribute__((__regparm__(1))) void * ___libc_tls_get_addr(void *);
66 void * __libc_tls_get_addr(void *);
67 __weak_reference(__libc_tls_get_addr, __tls_get_addr);
69 void *_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign);
70 void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
71 void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign);
72 void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
74 #if defined(__amd64__)
75 #define TLS_TCB_ALIGN 16
76 #elif defined(__aarch64__) || defined(__arm__) || defined(__i386__) || \
77 defined(__mips__) || defined(__powerpc__) || defined(__riscv) || \
79 #define TLS_TCB_ALIGN sizeof(void *)
81 #error TLS_TCB_ALIGN undefined for target architecture
84 #if defined(__aarch64__) || defined(__arm__) || defined(__mips__) || \
85 defined(__powerpc__) || defined(__riscv)
88 #if defined(__i386__) || defined(__amd64__) || defined(__sparc64__)
89 #define TLS_VARIANT_II
94 static size_t tls_static_space;
95 static size_t tls_init_size;
96 static size_t tls_init_align;
97 static void *tls_init;
104 __attribute__((__regparm__(1)))
106 ___libc_tls_get_addr(void *ti __unused)
114 __libc_tls_get_addr(void *ti __unused)
122 malloc_aligned(size_t size, size_t align)
126 if (align < sizeof(void *))
127 align = sizeof(void *);
129 mem = __je_bootstrap_malloc(size + sizeof(void *) + align - 1);
130 res = (void *)roundup2((uintptr_t)mem + sizeof(void *), align);
131 *(void **)((uintptr_t)res - sizeof(void *)) = mem;
136 free_aligned(void *ptr)
147 __je_bootstrap_free(mem);
152 #define TLS_TCB_SIZE (2 * sizeof(void *))
155 * Free Static TLS using the Variant I method.
158 __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign __unused)
163 tls = (Elf_Addr **)tcb;
165 __je_bootstrap_free(dtv);
170 * Allocate Static TLS using the Variant I method.
173 __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign)
178 if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE)
181 tls_assert(tcbalign >= TLS_TCB_ALIGN);
182 tls_assert(tcbsize == TLS_TCB_SIZE);
184 tcbsize = roundup2(tcbsize, tcbalign);
185 tls = malloc_aligned(tcbsize + tls_static_space, tcbalign);
187 tls_msg("__libc_allocate_tls: Out of memory.\n");
190 memset(tls, 0, tcbsize + tls_static_space);
192 if (oldtcb != NULL) {
193 memcpy(tls, oldtcb, tcbsize + tls_static_space);
194 __je_bootstrap_free(oldtcb);
196 /* Adjust the DTV. */
198 dtv[2] = (Elf_Addr)tls + tcbsize;
200 dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr));
202 tls_msg("__libc_allocate_tls: Out of memory.\n");
206 dtv[0] = 1; /* Generation. */
207 dtv[1] = 1; /* Segments count. */
208 dtv[2] = (Elf_Addr)tls + tcbsize;
210 if (tls_init_size > 0)
211 memcpy((void*)dtv[2], tls_init, tls_init_size);
219 #ifdef TLS_VARIANT_II
221 #define TLS_TCB_SIZE (3 * sizeof(Elf_Addr))
224 * Free Static TLS using the Variant II method.
227 __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign)
231 Elf_Addr tlsstart, tlsend;
234 * Figure out the size of the initial TLS block so that we can
235 * find stuff which ___tls_get_addr() allocated dynamically.
237 size = roundup2(tls_static_space, tcbalign);
239 dtv = ((Elf_Addr**)tcb)[1];
240 tlsend = (Elf_Addr) tcb;
241 tlsstart = tlsend - size;
242 free_aligned((void*)tlsstart);
243 __je_bootstrap_free(dtv);
247 * Allocate Static TLS using the Variant II method.
250 __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign)
255 Elf_Addr segbase, oldsegbase;
257 size = roundup2(tls_static_space, tcbalign);
259 if (tcbsize < 2 * sizeof(Elf_Addr))
260 tcbsize = 2 * sizeof(Elf_Addr);
261 tls = malloc_aligned(size + tcbsize, tcbalign);
263 tls_msg("__libc_allocate_tls: Out of memory.\n");
266 memset(tls, 0, size + tcbsize);
267 dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr));
269 tls_msg("__libc_allocate_tls: Out of memory.\n");
273 segbase = (Elf_Addr)(tls + size);
274 ((Elf_Addr*)segbase)[0] = segbase;
275 ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
279 dtv[2] = segbase - tls_static_space;
283 * Copy the static TLS block over whole.
285 oldsegbase = (Elf_Addr) oldtls;
286 memcpy((void *)(segbase - tls_static_space),
287 (const void *)(oldsegbase - tls_static_space),
291 * We assume that this block was the one we created with
292 * allocate_initial_tls().
294 _rtld_free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr));
296 memcpy((void *)(segbase - tls_static_space),
297 tls_init, tls_init_size);
298 memset((void *)(segbase - tls_static_space + tls_init_size),
299 0, tls_static_space - tls_init_size);
302 return (void*) segbase;
305 #endif /* TLS_VARIANT_II */
310 __libc_allocate_tls(void *oldtls __unused, size_t tcbsize __unused,
311 size_t tcbalign __unused)
317 __libc_free_tls(void *tcb __unused, size_t tcbsize __unused,
318 size_t tcbalign __unused)
324 extern char **environ;
331 Elf_Auxinfo *aux, *auxp;
337 sp = (Elf_Addr *) environ;
340 aux = (Elf_Auxinfo *) sp;
343 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) {
344 switch (auxp->a_type) {
346 phdr = auxp->a_un.a_ptr;
350 phent = auxp->a_un.a_val;
354 phnum = auxp->a_un.a_val;
358 if (phdr == NULL || phent != sizeof(Elf_Phdr) || phnum == 0)
361 for (i = 0; (unsigned) i < phnum; i++) {
362 if (phdr[i].p_type == PT_TLS) {
363 tls_static_space = roundup2(phdr[i].p_memsz,
365 tls_init_size = phdr[i].p_filesz;
366 tls_init_align = phdr[i].p_align;
367 tls_init = (void*) phdr[i].p_vaddr;
372 tls = _rtld_allocate_tls(NULL, TLS_TCB_SIZE,
373 MAX(TLS_TCB_ALIGN, tls_init_align));