]> git.ipfire.org Git - thirdparty/glibc.git/blame - csu/libc-tls.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / csu / libc-tls.c
CommitLineData
8a30f00f 1/* Initialization code for TLS in statically linked application.
04277e02 2 Copyright (C) 2002-2019 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
PE
16 License along with the GNU C Library; if not, see
17 <http://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>
8a30f00f 26
82412d54 27
b9cb349f
RM
28#ifdef SHARED
29 #error makefile bug, this file is for static only
30#endif
8a30f00f 31
b80af2f4 32dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS];
8a30f00f
UD
33
34
35static struct
36{
37 struct dtv_slotinfo_list si;
38 /* The dtv_slotinfo_list data structure does not include the actual
8265947d
RM
39 information since it is defined as an array of size zero. We define
40 here the necessary entries. Note that it is not important whether
41 there is padding or not since we will always access the information
42 through the 'si' element. */
8a30f00f
UD
43 struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
44} static_slotinfo;
45
8a30f00f 46
b9cb349f
RM
47/* Highest dtv index currently needed. */
48size_t _dl_tls_max_dtv_idx;
49/* Flag signalling whether there are gaps in the module ID allocation. */
50bool _dl_tls_dtv_gaps;
51/* Information about the dtv slots. */
52struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
53/* Number of modules in the static TLS block. */
54size_t _dl_tls_static_nelem;
fcae3b76
UD
55/* Size of the static TLS block. Giving this initialized value
56 preallocates some surplus bytes in the static TLS area. */
57size_t _dl_tls_static_size = 2048;
80f6f981
UD
58/* Size actually allocated in the static TLS block. */
59size_t _dl_tls_static_used;
b9cb349f
RM
60/* Alignment requirement of the static TLS block. */
61size_t _dl_tls_static_align;
62
63/* Generation counter for the dtv. */
64size_t _dl_tls_generation;
65
66
2a76f7ef
UD
67/* Additional definitions needed by TLS initialization. */
68#ifdef TLS_INIT_HELPER
69TLS_INIT_HELPER
70#endif
71
f1d70dad 72static void
216455bc
RM
73init_slotinfo (void)
74{
75 /* Create the slotinfo list. */
76 static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
77 - (char *) &static_slotinfo.si.slotinfo[0])
78 / sizeof static_slotinfo.si.slotinfo[0]);
79 // static_slotinfo.si.next = NULL; already zero
80
81 /* The slotinfo list. Will be extended by the code doing dynamic
82 linking. */
83 GL(dl_tls_max_dtv_idx) = 1;
84 GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
85}
86
f1d70dad 87static void
216455bc
RM
88init_static_tls (size_t memsz, size_t align)
89{
90 /* That is the size of the TLS memory for this object. The initialized
91 value of _dl_tls_static_size is provided by dl-open.c to request some
92 surplus that permits dynamic loading of modules with IE-model TLS. */
93 GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
94 TLS_TCB_ALIGN);
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
8a30f00f
UD
119 /* Look through the TLS segment if there is any. */
120 if (_dl_phdr != NULL)
a162642d 121 for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
d10c6430
RM
122 if (phdr->p_type == PT_TLS)
123 {
124 /* Remember the values we need. */
125 memsz = phdr->p_memsz;
126 filesz = phdr->p_filesz;
9d7a3741 127 initimage = (void *) phdr->p_vaddr + main_map->l_addr;
d10c6430
RM
128 align = phdr->p_align;
129 if (phdr->p_align > max_align)
130 max_align = phdr->p_align;
131 break;
132 }
8a30f00f 133
8a30f00f
UD
134 /* We have to set up the TCB block which also (possibly) contains
135 'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
136 Instead we use 'sbrk' which would only uses 'errno' if it fails.
137 In this case we are right away out of memory and the user gets
e7e6e437
RM
138 what she/he deserves.
139
140 The initialized value of _dl_tls_static_size is provided by dl-open.c
141 to request some surplus that permits dynamic loading of modules with
142 IE-model TLS. */
11bf311e 143#if TLS_TCB_AT_TP
a7fcc2f8
L
144 /* Align the TCB offset to the maximum alignment, as
145 _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
146 and dl_tls_static_align. */
147 tcb_offset = roundup (memsz + GL(dl_tls_static_size), max_align);
003a27e8 148 tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
11bf311e 149#elif TLS_DTV_AT_TP
003a27e8 150 tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
aff4519d
UD
151 tlsblock = __sbrk (tcb_offset + memsz + max_align
152 + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
153 tlsblock += TLS_PRE_TCB_SIZE;
11bf311e 154#else
8a30f00f
UD
155 /* In case a model with a different layout for the TCB and DTV
156 is defined add another #elif here and in the following #ifs. */
11bf311e
UD
157# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
158#endif
8a30f00f
UD
159
160 /* Align the TLS block. */
161 tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
162 & ~(max_align - 1));
163
164 /* Initialize the dtv. [0] is the length, [1] the generation counter. */
b80af2f4
L
165 _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2;
166 // _dl_static_dtv[1].counter = 0; would be needed if not already done
8a30f00f
UD
167
168 /* Initialize the TLS block. */
11bf311e 169#if TLS_TCB_AT_TP
b80af2f4 170 _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
9dcafc55 171 - roundup (memsz, align ?: 1));
0d23a5c1 172 main_map->l_tls_offset = roundup (memsz, align ?: 1);
11bf311e 173#elif TLS_DTV_AT_TP
b80af2f4 174 _dl_static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
0d23a5c1 175 main_map->l_tls_offset = tcb_offset;
11bf311e
UD
176#else
177# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
178#endif
a2ff21f8 179 _dl_static_dtv[2].pointer.to_free = NULL;
82412d54 180 /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */
b80af2f4 181 memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz);
8a30f00f
UD
182
183 /* Install the pointer to the dtv. */
184
185 /* Initialize the thread pointer. */
11bf311e 186#if TLS_TCB_AT_TP
b80af2f4 187 INSTALL_DTV ((char *) tlsblock + tcb_offset, _dl_static_dtv);
8a30f00f 188
774f9285 189 const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset);
11bf311e 190#elif TLS_DTV_AT_TP
b80af2f4 191 INSTALL_DTV (tlsblock, _dl_static_dtv);
774f9285 192 const char *lossage = TLS_INIT_TP (tlsblock);
11bf311e
UD
193#else
194# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
195#endif
82412d54 196 if (__builtin_expect (lossage != NULL, 0))
086df229 197 _startup_fatal (lossage);
8a30f00f 198
0d23a5c1
MR
199 /* Update the executable's link map with enough information to make
200 the TLS routines happy. */
201 main_map->l_tls_align = align;
202 main_map->l_tls_blocksize = memsz;
203 main_map->l_tls_initimage = initimage;
204 main_map->l_tls_initimage_size = filesz;
205 main_map->l_tls_modid = 1;
8a30f00f 206
216455bc
RM
207 init_slotinfo ();
208 // static_slotinfo.si.slotinfo[1].gen = 0; already zero
0d23a5c1 209 static_slotinfo.si.slotinfo[1].map = main_map;
8a30f00f 210
c56baa87 211 memsz = roundup (memsz, align ?: 1);
216455bc 212
96553893 213#if TLS_DTV_AT_TP
aff4519d 214 memsz += tcb_offset;
11bf311e 215#endif
c56baa87 216
216455bc
RM
217 init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
218}