1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <ldsodefs.h>
22: #include <tls.h>
23: #include <unistd.h>
24: #include <stdio.h>
25: #include <sys/param.h>
26:
27:
28: #ifdef SHARED
29: #error makefile bug, this file is for static only
30: #endif
31:
32: extern ElfW(Phdr) *_dl_phdr;
33: extern size_t _dl_phnum;
34:
35:
36: static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
37:
38:
39: static struct
40: {
41: struct dtv_slotinfo_list si;
42:
43:
44:
45:
46:
47: struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
48: } static_slotinfo;
49:
50:
51: static struct link_map static_map;
52:
53:
54:
55: size_t _dl_tls_max_dtv_idx;
56:
57: bool _dl_tls_dtv_gaps;
58:
59: struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
60:
61: size_t _dl_tls_static_nelem;
62:
63:
64: size_t _dl_tls_static_size = 2048;
65:
66: size_t _dl_tls_static_used;
67:
68: size_t _dl_tls_static_align;
69:
70:
71: size_t _dl_tls_generation;
72:
73:
74:
75: #ifdef TLS_INIT_HELPER
76: TLS_INIT_HELPER
77: #endif
78:
79: static inline void
80: init_slotinfo (void)
81: {
82:
83: static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
84: - (char *) &static_slotinfo.si.slotinfo[0])
85: / sizeof static_slotinfo.si.slotinfo[0]);
86:
87:
88:
89:
90: GL(dl_tls_max_dtv_idx) = 1;
91: GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
92: }
93:
94: static inline void
95: init_static_tls (size_t memsz, size_t align)
96: {
97:
98:
99:
100: GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
101: TLS_TCB_ALIGN);
102: GL(dl_tls_static_used) = memsz;
103:
104: GL(dl_tls_static_align) = align;
105:
106: GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
107: }
108:
109: void
110: __libc_setup_tls (size_t tcbsize, size_t tcbalign)
111: {
112: void *tlsblock;
113: size_t memsz = 0;
114: size_t filesz = 0;
115: void *initimage = NULL;
116: size_t align = 0;
117: size_t max_align = tcbalign;
118: size_t tcb_offset;
119: ElfW(Phdr) *phdr;
120:
121:
122: if (_dl_phdr != NULL)
123: for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
124: if (phdr->p_type == PT_TLS)
125: {
126:
127: memsz = phdr->p_memsz;
128: filesz = phdr->p_filesz;
129: initimage = (void *) phdr->p_vaddr;
130: align = phdr->p_align;
131: if (phdr->p_align > max_align)
132: max_align = phdr->p_align;
133: break;
134: }
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145: #if TLS_TCB_AT_TP
146: tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
147: tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
148: #elif TLS_DTV_AT_TP
149: tcb_offset = roundup (tcbsize, align ?: 1);
150: tlsblock = __sbrk (tcb_offset + memsz + max_align
151: + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
152: tlsblock += TLS_PRE_TCB_SIZE;
153: #else
154:
155:
156: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
157: #endif
158:
159:
160: tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
161: & ~(max_align - 1));
162:
163:
164: static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2;
165:
166:
167:
168: #if TLS_TCB_AT_TP
169: static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
170: - roundup (memsz, align ?: 1));
171: static_map.l_tls_offset = roundup (memsz, align ?: 1);
172: #elif TLS_DTV_AT_TP
173: static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
174: static_map.l_tls_offset = tcb_offset;
175: #else
176: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
177: #endif
178: static_dtv[2].pointer.is_static = true;
179:
180: memcpy (static_dtv[2].pointer.val, initimage, filesz);
181:
182:
183:
184:
185: #if TLS_TCB_AT_TP
186: INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
187:
188: const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
189: #elif TLS_DTV_AT_TP
190: INSTALL_DTV (tlsblock, static_dtv);
191: const char *lossage = TLS_INIT_TP (tlsblock, 0);
192: #else
193: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
194: #endif
195: if (__builtin_expect (lossage != NULL, 0))
196: __libc_fatal (lossage);
197:
198:
199:
200:
201: static_map.l_tls_align = align;
202: static_map.l_tls_blocksize = memsz;
203: static_map.l_tls_initimage = initimage;
204: static_map.l_tls_initimage_size = filesz;
205: static_map.l_type = lt_executable;
206: static_map.l_tls_modid = 1;
207:
208: init_slotinfo ();
209:
210: static_slotinfo.si.slotinfo[1].map = &static_map;
211:
212: memsz = roundup (memsz, align ?: 1);
213:
214: #if TLS_TCB_AT_TP
215: memsz += tcbsize;
216: #elif TLS_DTV_AT_TP
217: memsz += tcb_offset;
218: #endif
219:
220: init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
221: }
222:
223:
224:
225:
226: int
227: internal_function
228: _dl_tls_setup (void)
229: {
230: init_slotinfo ();
231: init_static_tls (
232: #if TLS_TCB_AT_TP
233: TLS_TCB_SIZE,
234: #else
235: 0,
236: #endif
237: TLS_TCB_ALIGN);
238: return 0;
239: }
240:
241:
242:
243:
244: void
245: __attribute__ ((weak))
246: __pthread_initialize_minimal (void)
247: {
248: __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
249: }