]> sourceware.org Git - glibc.git/blame - csu/libc-tls.c
elf: Introduce <dl-call_tls_init_tp.h> and call_tls_init_tp (bug 29249)
[glibc.git] / csu / libc-tls.c
CommitLineData
8a30f00f 1/* Initialization code for TLS in statically linked application.
581c785b 2 Copyright (C) 2002-2022 Free Software Foundation, Inc.
8a30f00f
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
8a30f00f 18
086df229 19#include <startup.h>
7d0b1164 20#include <errno.h>
8a30f00f
UD
21#include <ldsodefs.h>
22#include <tls.h>
23#include <unistd.h>
82412d54 24#include <stdio.h>
99343c05 25#include <sys/param.h>
cba932a5 26#include <array_length.h>
627f5ede 27#include <pthreadP.h>
1f34a232 28#include <dl-call_tls_init_tp.h>
82412d54 29
b9cb349f
RM
30#ifdef SHARED
31 #error makefile bug, this file is for static only
32#endif
8a30f00f 33
b80af2f4 34dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS];
8a30f00f
UD
35
36
cba932a5
FW
37static struct dtv_slotinfo_list static_slotinfo =
38 {
39 /* Allocate an array of 2 + TLS_SLOTINFO_SURPLUS elements. */
40 .slotinfo = { [array_length (_dl_static_dtv) - 1] = { 0 } },
41 };
8a30f00f 42
b9cb349f
RM
43/* Highest dtv index currently needed. */
44size_t _dl_tls_max_dtv_idx;
45/* Flag signalling whether there are gaps in the module ID allocation. */
46bool _dl_tls_dtv_gaps;
47/* Information about the dtv slots. */
48struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
49/* Number of modules in the static TLS block. */
50size_t _dl_tls_static_nelem;
0c7b002f
SN
51/* Size of the static TLS block. */
52size_t _dl_tls_static_size;
80f6f981
UD
53/* Size actually allocated in the static TLS block. */
54size_t _dl_tls_static_used;
b9cb349f
RM
55/* Alignment requirement of the static TLS block. */
56size_t _dl_tls_static_align;
0c7b002f
SN
57/* Size of surplus space in the static TLS area for dynamically
58 loaded modules with IE-model TLS or for TLSDESC optimization.
59 See comments in elf/dl-tls.c where it is initialized. */
60size_t _dl_tls_static_surplus;
ffb17e7b
SN
61/* Remaining amount of static TLS that may be used for optimizing
62 dynamic TLS access (e.g. with TLSDESC). */
63size_t _dl_tls_static_optional;
b9cb349f
RM
64
65/* Generation counter for the dtv. */
66size_t _dl_tls_generation;
67
68
2a76f7ef
UD
69/* Additional definitions needed by TLS initialization. */
70#ifdef TLS_INIT_HELPER
71TLS_INIT_HELPER
72#endif
73
f1d70dad 74static void
216455bc
RM
75init_slotinfo (void)
76{
cba932a5
FW
77 /* Create the slotinfo list. Note that the type of static_slotinfo
78 has effectively a zero-length array, so we cannot use the size of
79 static_slotinfo to determine the array length. */
80 static_slotinfo.len = array_length (_dl_static_dtv);
81 /* static_slotinfo.next = NULL; -- Already zero. */
216455bc
RM
82
83 /* The slotinfo list. Will be extended by the code doing dynamic
84 linking. */
85 GL(dl_tls_max_dtv_idx) = 1;
cba932a5 86 GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo;
216455bc
RM
87}
88
f1d70dad 89static void
216455bc
RM
90init_static_tls (size_t memsz, size_t align)
91{
0c7b002f
SN
92 /* That is the size of the TLS memory for this object. */
93 GL(dl_tls_static_size) = roundup (memsz + GLRO(dl_tls_static_surplus),
627f5ede 94 TCB_ALIGNMENT);
96553893
UD
95#if TLS_TCB_AT_TP
96 GL(dl_tls_static_size) += TLS_TCB_SIZE;
97#endif
216455bc
RM
98 GL(dl_tls_static_used) = memsz;
99 /* The alignment requirement for the static TLS block. */
100 GL(dl_tls_static_align) = align;
101 /* Number of elements in the static TLS block. */
102 GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
103}
2a76f7ef 104
8a30f00f 105void
003a27e8 106__libc_setup_tls (void)
8a30f00f
UD
107{
108 void *tlsblock;
109 size_t memsz = 0;
110 size_t filesz = 0;
d10c6430 111 void *initimage = NULL;
8a30f00f 112 size_t align = 0;
003a27e8 113 size_t max_align = TCB_ALIGNMENT;
8a30f00f 114 size_t tcb_offset;
dc0a0263 115 const ElfW(Phdr) *phdr;
8a30f00f 116
9d7a3741
L
117 struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
118
d017b0ab
FW
119 __tls_pre_init_tp ();
120
8a30f00f
UD
121 /* Look through the TLS segment if there is any. */
122 if (_dl_phdr != NULL)
a162642d 123 for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
d10c6430
RM
124 if (phdr->p_type == PT_TLS)
125 {
126 /* Remember the values we need. */
127 memsz = phdr->p_memsz;
128 filesz = phdr->p_filesz;
9d7a3741 129 initimage = (void *) phdr->p_vaddr + main_map->l_addr;
d10c6430
RM
130 align = phdr->p_align;
131 if (phdr->p_align > max_align)
132 max_align = phdr->p_align;
133 break;
134 }
8a30f00f 135
17796419
SN
136 /* Calculate the size of the static TLS surplus, with 0 auditors. */
137 _dl_tls_static_surplus_init (0);
0c7b002f 138
8a30f00f
UD
139 /* We have to set up the TCB block which also (possibly) contains
140 'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
141 Instead we use 'sbrk' which would only uses 'errno' if it fails.
142 In this case we are right away out of memory and the user gets
0c7b002f 143 what she/he deserves. */
11bf311e 144#if TLS_TCB_AT_TP
a7fcc2f8
L
145 /* Align the TCB offset to the maximum alignment, as
146 _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
147 and dl_tls_static_align. */
0c7b002f 148 tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align);
f787e138
FW
149 tlsblock = _dl_early_allocate (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
150 if (tlsblock == NULL)
1f34a232 151 _startup_fatal_tls_error ();
11bf311e 152#elif TLS_DTV_AT_TP
003a27e8 153 tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
f787e138
FW
154 tlsblock = _dl_early_allocate (tcb_offset + memsz + max_align
155 + TLS_PRE_TCB_SIZE
156 + GLRO(dl_tls_static_surplus));
157 if (tlsblock == NULL)
1f34a232 158 _startup_fatal_tls_error ();
aff4519d 159 tlsblock += TLS_PRE_TCB_SIZE;
11bf311e 160#else
8a30f00f
UD
161 /* In case a model with a different layout for the TCB and DTV
162 is defined add another #elif here and in the following #ifs. */
11bf311e
UD
163# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
164#endif
8a30f00f
UD
165
166 /* Align the TLS block. */
167 tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
168 & ~(max_align - 1));
169
170 /* Initialize the dtv. [0] is the length, [1] the generation counter. */
b80af2f4
L
171 _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2;
172 // _dl_static_dtv[1].counter = 0; would be needed if not already done
8a30f00f
UD
173
174 /* Initialize the TLS block. */
11bf311e 175#if TLS_TCB_AT_TP
b80af2f4 176 _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
9dcafc55 177 - roundup (memsz, align ?: 1));
0d23a5c1 178 main_map->l_tls_offset = roundup (memsz, align ?: 1);
11bf311e 179#elif TLS_DTV_AT_TP
b80af2f4 180 _dl_static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
0d23a5c1 181 main_map->l_tls_offset = tcb_offset;
11bf311e
UD
182#else
183# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
184#endif
a2ff21f8 185 _dl_static_dtv[2].pointer.to_free = NULL;
82412d54 186 /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */
b80af2f4 187 memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz);
8a30f00f
UD
188
189 /* Install the pointer to the dtv. */
190
191 /* Initialize the thread pointer. */
11bf311e 192#if TLS_TCB_AT_TP
b80af2f4 193 INSTALL_DTV ((char *) tlsblock + tcb_offset, _dl_static_dtv);
8a30f00f 194
1f34a232 195 call_tls_init_tp ((char *) tlsblock + tcb_offset);
11bf311e 196#elif TLS_DTV_AT_TP
b80af2f4 197 INSTALL_DTV (tlsblock, _dl_static_dtv);
1f34a232 198 call_tls_init_tp (tlsblock);
11bf311e 199#endif
1daccf40 200
0d23a5c1
MR
201 /* Update the executable's link map with enough information to make
202 the TLS routines happy. */
203 main_map->l_tls_align = align;
204 main_map->l_tls_blocksize = memsz;
205 main_map->l_tls_initimage = initimage;
206 main_map->l_tls_initimage_size = filesz;
207 main_map->l_tls_modid = 1;
8a30f00f 208
216455bc 209 init_slotinfo ();
cba932a5
FW
210 /* static_slotinfo.slotinfo[1].gen = 0; -- Already zero. */
211 static_slotinfo.slotinfo[1].map = main_map;
8a30f00f 212
c56baa87 213 memsz = roundup (memsz, align ?: 1);
216455bc 214
96553893 215#if TLS_DTV_AT_TP
aff4519d 216 memsz += tcb_offset;
11bf311e 217#endif
c56baa87 218
627f5ede 219 init_static_tls (memsz, MAX (TCB_ALIGNMENT, max_align));
216455bc 220}
This page took 0.468252 seconds and 5 git commands to generate.