xref: /openbsd-src/lib/libc/dlfcn/tib.c (revision 2c53affbcc0119d6480b86c18f2790523b6a0aad)
1*2c53affbSjmc /*	$OpenBSD: tib.c,v 1.3 2022/12/27 17:10:06 jmc Exp $ */
2fe38b55cSguenther /*
3fe38b55cSguenther  * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
4fe38b55cSguenther  *
5fe38b55cSguenther  * Permission to use, copy, modify, and distribute this software for any
6fe38b55cSguenther  * purpose with or without fee is hereby granted, provided that the above
7fe38b55cSguenther  * copyright notice and this permission notice appear in all copies.
8fe38b55cSguenther  *
9fe38b55cSguenther  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10fe38b55cSguenther  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11fe38b55cSguenther  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12fe38b55cSguenther  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13fe38b55cSguenther  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14fe38b55cSguenther  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15fe38b55cSguenther  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16fe38b55cSguenther  */
17fe38b55cSguenther 
18fe38b55cSguenther #include <tib.h>
19fe38b55cSguenther 
20fe38b55cSguenther #ifndef PIC
21f54aa464Sguenther # include <stdlib.h>		/* posix_memalign and free */
22fe38b55cSguenther #endif
23fe38b55cSguenther 
24fe38b55cSguenther #define ELF_ROUND(x,malign)	(((x) + (malign)-1) & ~((malign)-1))
25fe38b55cSguenther 
26fe38b55cSguenther 
27fe38b55cSguenther /*
28fe38b55cSguenther  * The functions here are weak so that the ld.so versions are used
29fe38b55cSguenther  * in dynamic links, whether or not libc is static
30fe38b55cSguenther  */
31fe38b55cSguenther void	*_dl_allocate_tib(size_t _extra) __attribute__((weak));
32fe38b55cSguenther void	_dl_free_tib(void *_tib, size_t _extra) __attribute__((weak));
33fe38b55cSguenther 
34fe38b55cSguenther /*
35fe38b55cSguenther  * Allocate a TIB for passing to __tfork for a new thread.  'extra'
36fe38b55cSguenther  * is the amount of space to allocate on the side of the TIB opposite
37fe38b55cSguenther  * of the TLS data: before the TIB for variant 1 and after the TIB
38fe38b55cSguenther  * for variant 2.  If non-zero, tib_thread is set to point to that area.
39fe38b55cSguenther  */
40fe38b55cSguenther void *
_dl_allocate_tib(size_t extra)41fe38b55cSguenther _dl_allocate_tib(size_t extra)
42fe38b55cSguenther {
43fe38b55cSguenther #ifdef PIC
44*2c53affbSjmc 	return NULL;			/* overridden by ld.so */
45fe38b55cSguenther #else
46f54aa464Sguenther 	void *base;
47fe38b55cSguenther 	char *thread;
48fe38b55cSguenther 
49fe38b55cSguenther # if TLS_VARIANT == 1
50f54aa464Sguenther 	/* round up the extra size to align the TIB and TLS data after it */
51f54aa464Sguenther 	extra = (extra <= _static_tls_align_offset) ? 0 :
52f54aa464Sguenther 	    ELF_ROUND(extra - _static_tls_align_offset, _static_tls_align);
53f54aa464Sguenther 	if (posix_memalign(&base, _static_tls_align, extra +
54f54aa464Sguenther 	    _static_tls_align_offset + sizeof(struct tib) +
55f54aa464Sguenther 	    _static_tls_size) != 0)
56f54aa464Sguenther 		return NULL;
57fe38b55cSguenther 	thread = base;
58f54aa464Sguenther 	base = (char *)base + extra;
59fe38b55cSguenther 
60fe38b55cSguenther # elif TLS_VARIANT == 2
61f54aa464Sguenther 	/* round up the TIB size to align the extra area after it */
62f54aa464Sguenther 	if (posix_memalign(&base, _static_tls_align,
63f54aa464Sguenther 	    _static_tls_align_offset + _static_tls_size +
64f54aa464Sguenther 	    ELF_ROUND(sizeof(struct tib), TIB_EXTRA_ALIGN) + extra) != 0)
65f54aa464Sguenther 		return NULL;
66f54aa464Sguenther 	thread = (char *)base + _static_tls_align_offset + _static_tls_size +
67f54aa464Sguenther 	    ELF_ROUND(sizeof(struct tib), TIB_EXTRA_ALIGN);
68fe38b55cSguenther # endif
69fe38b55cSguenther 
70f54aa464Sguenther 	return _static_tls_init(base, thread);
71fe38b55cSguenther #endif /* !PIC */
72fe38b55cSguenther }
73fe38b55cSguenther 
74fe38b55cSguenther void
_dl_free_tib(void * tib,size_t extra)75fe38b55cSguenther _dl_free_tib(void *tib, size_t extra)
76fe38b55cSguenther {
77fe38b55cSguenther #ifndef PIC
78fe38b55cSguenther 	size_t tib_offset;
79fe38b55cSguenther 
80fe38b55cSguenther # if TLS_VARIANT == 1
81f54aa464Sguenther 	tib_offset = (extra <= _static_tls_align_offset) ? 0 :
82f54aa464Sguenther 	    ELF_ROUND(extra - _static_tls_align_offset, _static_tls_align);
83fe38b55cSguenther # elif TLS_VARIANT == 2
84fe38b55cSguenther 	tib_offset = _static_tls_size;
85fe38b55cSguenther # endif
86f54aa464Sguenther 	tib_offset += _static_tls_align_offset;
87fe38b55cSguenther 
88fe38b55cSguenther 	free((char *)tib - tib_offset);
89fe38b55cSguenther #endif /* !PIC */
90fe38b55cSguenther }
91