2 * Copyright (c) 2004 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libc/gen/tls.c,v 1.7 2005/03/01 23:42:00 davidxu Exp $
27 * $DragonFly: src/lib/libc/gen/tls.c,v 1.4 2005/03/28 03:33:12 dillon Exp $
31 * Define stubs for TLS internals so that programs and libraries can
32 * link. These functions will be replaced by functional versions at
33 * runtime from ld-elf.so.1.
36 #include <sys/cdefs.h>
43 #include "libc_private.h"
45 __weak_reference(__libc_allocate_tls, _rtld_allocate_tls);
46 __weak_reference(__libc_free_tls, _rtld_free_tls);
48 __weak_reference(___libc_tls_get_addr, ___tls_get_addr);
50 __weak_reference(__libc_tls_get_addr, __tls_get_addr);
52 struct tls_tcb *_rtld_allocate_tls(struct tls_tcb *, size_t tcbsize, int flags);
53 void _rtld_free_tls(struct tls_tcb *tcb, size_t tcb_size);
54 struct tls_tcb *__libc_allocate_tls(struct tls_tcb *old_tcb, size_t tcbsize,
56 void __libc_free_tls(struct tls_tcb *tcb, size_t tcb_size);
58 #if defined(__ia64__) || defined(__powerpc__)
61 #if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \
63 #define TLS_VARIANT_II
68 #define round(size, align) \
69 (((size) + (align) - 1) & ~((align) - 1))
71 static size_t tls_static_space;
72 static size_t tls_init_size;
73 static void *tls_init;
80 void *___libc_tls_get_addr(void *ti) __attribute__((__regparm__(1)));
82 __attribute__((__regparm__(1)))
84 ___libc_tls_get_addr(void *ti __unused)
91 void *__libc_tls_get_addr(void *ti);
94 __libc_tls_get_addr(void *ti __unused)
105 __libc_free_tls(struct tls_tcb *tcb, size_t tcb_size __unused)
111 data_size = (tls_static_space + RTLD_STATIC_TLS_ALIGN_MASK) &
112 ~RTLD_STATIC_TLS_ALIGN_MASK;
113 free((char *)tcb - data_size);
117 * Allocate Static TLS.
120 __libc_allocate_tls(struct tls_tcb *old_tcb, size_t tcb_size, int flags)
126 data_size = (tls_static_space + RTLD_STATIC_TLS_ALIGN_MASK) &
127 ~RTLD_STATIC_TLS_ALIGN_MASK;
128 tcb = malloc(data_size + tcb_size);
129 tcb = (struct tls_tcb *)((char *)tcb + data_size);
130 bzero(tcb, tcb_size);
131 dtv = malloc(3 * sizeof(Elf_Addr));
137 dtv[2] = (Elf_Addr)((char *)tcb - tls_static_space);
141 * Copy the static TLS block over whole.
143 memcpy((char *)tcb - tls_static_space,
144 (char *)old_tcb - tls_static_space,
148 * We assume that this block was the one we created with
149 * allocate_initial_tls().
151 _rtld_free_tls(old_tcb, sizeof(struct tls_tcb));
153 memcpy((char *)tcb - tls_static_space,
154 tls_init, tls_init_size);
155 memset((char *)tcb - tls_static_space + tls_init_size,
156 0, tls_static_space - tls_init_size);
164 __libc_allocate_tls(struct tls_tcb *old_tls __unused, size_t tcb_size __unused,
171 __libc_free_tls(struct tls_tcb *tcb __unused, size_t tcb_size __unused)
177 extern char **environ;
184 Elf_Auxinfo *aux, *auxp;
190 sp = (Elf_Addr *) environ;
193 aux = (Elf_Auxinfo *) sp;
196 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) {
197 switch (auxp->a_type) {
199 phdr = auxp->a_un.a_ptr;
203 phent = auxp->a_un.a_val;
207 phnum = auxp->a_un.a_val;
211 if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0)
214 for (i = 0; (unsigned)i < phnum; i++) {
215 if (phdr[i].p_type == PT_TLS) {
216 tls_static_space = round(phdr[i].p_memsz,
218 tls_init_size = phdr[i].p_filesz;
219 tls_init = (void*) phdr[i].p_vaddr;
223 if (tls_static_space) {
224 tcb = _rtld_allocate_tls(NULL, sizeof(struct tls_tcb), 0);
225 _set_tp(tcb, (size_t)-1);