NEWS: Fix typos, grammar, and missing words
[glibc.git] / elf / tst-tls20.c
blob831c3336c914790d618d6b5f2800dc87015349d4
1 /* Test dtv setup if entries don't have monotone increasing generation.
2 Copyright (C) 2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <array_length.h>
20 #include <dlfcn.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <support/check.h>
25 #include <support/support.h>
26 #include <support/test-driver.h>
27 #include <support/xdlfcn.h>
28 #include <support/xthread.h>
30 #define NMOD 100
31 static void *mod[NMOD];
33 static void
34 load_fail (void)
36 /* Expected to fail because of a missing symbol. */
37 void *m = dlopen ("tst-tls20mod-bad.so", RTLD_NOW);
38 if (m != NULL)
39 FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
42 static void
43 load_mod (int i)
45 char *buf = xasprintf ("tst-tls-manydynamic%02dmod.so", i);
46 mod[i] = xdlopen (buf, RTLD_LAZY);
47 free (buf);
50 static void
51 unload_mod (int i)
53 if (mod[i] != NULL)
54 xdlclose (mod[i]);
55 mod[i] = NULL;
58 static void
59 access (int i)
61 char *buf = xasprintf ("tls_global_%02d", i);
62 dlerror ();
63 int *p = dlsym (mod[i], buf);
64 if (test_verbose)
65 printf ("mod[%d]: &tls = %p\n", i, p);
66 if (p == NULL)
67 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
68 TEST_COMPARE (*p, 0);
69 ++*p;
70 free (buf);
73 static void
74 access_mod (const char *modname, void *mod, int i)
76 char *modsym = xasprintf ("tls_global_%d", i);
77 dlerror ();
78 int *p = dlsym (mod, modsym);
79 if (test_verbose)
80 printf ("%s: &tls = %p\n", modname, p);
81 if (p == NULL)
82 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
83 TEST_COMPARE (*p, 0);
84 ++*p;
85 free (modsym);
88 static void
89 access_dep (int i)
91 char *modname = xasprintf ("tst-tls-manydynamic%dmod-dep.so", i);
92 void *moddep = xdlopen (modname, RTLD_LAZY);
93 access_mod (modname, moddep, i);
94 free (modname);
95 xdlclose (moddep);
98 struct start_args
100 const char *modname;
101 void *mod;
102 int modi;
103 int ndeps;
104 const int *deps;
107 static void *
108 start (void *a)
110 struct start_args *args = a;
112 for (int i = 0; i < NMOD; i++)
113 if (mod[i] != NULL)
114 access (i);
116 if (args != NULL)
118 access_mod (args->modname, args->mod, args->modi);
119 for (int n = 0; n < args->ndeps; n++)
120 access_dep (args->deps[n]);
123 return 0;
126 /* This test gaps with shared libraries with dynamic TLS that has no
127 dependencies. The DTV gap is set with by trying to load an invalid
128 module, the entry should be used on the dlopen. */
129 static void
130 do_test_no_depedency (void)
132 for (int i = 0; i < NMOD; i++)
134 load_mod (i);
135 /* Bump the generation of mod[0] without using new dtv slot. */
136 unload_mod (0);
137 load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135. */
138 load_mod (0);
139 /* Access TLS in all loaded modules. */
140 pthread_t t = xpthread_create (0, start, 0);
141 xpthread_join (t);
143 for (int i = 0; i < NMOD; i++)
144 unload_mod (i);
147 /* The following test check DTV gaps handling with shared libraries that has
148 dependencies. It defines 5 different sets:
150 1. Single dependency:
151 mod0 -> mod1
152 2. Double dependency:
153 mod2 -> [mod3,mod4]
154 3. Double dependency with each dependency depent of another module:
155 mod5 -> [mod6,mod7] -> mod8
156 4. Long chain with one double dependency in the middle:
157 mod9 -> [mod10, mod11] -> mod12 -> mod13
158 5. Long chain with two double depedencies in the middle:
159 mod14 -> mod15 -> [mod16, mod17]
160 mod15 -> [mod18, mod19]
162 This does not cover all the possible gaps and configuration, but it
163 should check if different dynamic shared sets are placed correctly in
164 different gaps configurations. */
166 static int
167 nmodules (uint32_t v)
169 unsigned int r = 0;
170 while (v >>= 1)
171 r++;
172 return r + 1;
175 static inline bool
176 is_mod_set (uint32_t g, uint32_t n)
178 return (1U << (n - 1)) & g;
181 static void
182 print_gap (uint32_t g)
184 if (!test_verbose)
185 return;
186 printf ("gap: ");
187 int nmods = nmodules (g);
188 for (int n = 1; n <= nmods; n++)
189 printf ("%c", ((1 << (n - 1)) & g) == 0 ? 'G' : 'M');
190 printf ("\n");
193 static void
194 do_test_dependency (void)
196 /* Maps the module and its dependencies, use thread to access the TLS on
197 each loaded module. */
198 static const int tlsmanydeps0[] = { 1 };
199 static const int tlsmanydeps1[] = { 3, 4 };
200 static const int tlsmanydeps2[] = { 6, 7, 8 };
201 static const int tlsmanydeps3[] = { 10, 11, 12 };
202 static const int tlsmanydeps4[] = { 15, 16, 17, 18, 19 };
203 static const struct tlsmanydeps_t
205 int modi;
206 int ndeps;
207 const int *deps;
208 } tlsmanydeps[] =
210 { 0, array_length (tlsmanydeps0), tlsmanydeps0 },
211 { 2, array_length (tlsmanydeps1), tlsmanydeps1 },
212 { 5, array_length (tlsmanydeps2), tlsmanydeps2 },
213 { 9, array_length (tlsmanydeps3), tlsmanydeps3 },
214 { 14, array_length (tlsmanydeps4), tlsmanydeps4 },
217 /* The gap configuration is defined as a bitmap: the bit set represents a
218 loaded module prior the tests execution, while a bit unsed is a module
219 unloaded. Not all permtation will show gaps, but it is simpler than
220 define each one independently. */
221 for (uint32_t g = 0; g < 64; g++)
223 print_gap (g);
224 int nmods = nmodules (g);
226 int mods[nmods];
227 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
228 cleanup. */
229 for (int n = 1; n < nmods; n++)
231 load_mod (n);
232 mods[n] = n;
234 for (int n = 1; n < nmods; n++)
236 if (!is_mod_set (g, n))
238 unload_mod (n);
239 mods[n] = 0;
243 for (int t = 0; t < array_length (tlsmanydeps); t++)
245 char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep.so",
246 tlsmanydeps[t].modi);
247 void *moddep = xdlopen (moddepname, RTLD_LAZY);
249 /* Access TLS in all loaded modules. */
250 struct start_args args =
252 moddepname,
253 moddep,
254 tlsmanydeps[t].modi,
255 tlsmanydeps[t].ndeps,
256 tlsmanydeps[t].deps
258 pthread_t t = xpthread_create (0, start, &args);
259 xpthread_join (t);
261 free (moddepname);
262 xdlclose (moddep);
265 for (int n = 1; n <= nmods; n++)
266 if (mods[n] != 0)
267 unload_mod (n);
271 /* The following test check DTV gaps handling with shared libraries that has
272 invalid dependencies. It defines 5 different sets:
274 1. Single dependency:
275 mod0 -> invalid
276 2. Double dependency:
277 mod1 -> [mod2,invalid]
278 3. Double dependency with each dependency depent of another module:
279 mod3 -> [mod4,mod5] -> invalid
280 4. Long chain with one double dependency in the middle:
281 mod6 -> [mod7, mod8] -> mod12 -> invalid
282 5. Long chain with two double depedencies in the middle:
283 mod10 -> mod11 -> [mod12, mod13]
284 mod12 -> [mod14, invalid]
286 This does not cover all the possible gaps and configuration, but it
287 should check if different dynamic shared sets are placed correctly in
288 different gaps configurations. */
290 static void
291 do_test_invalid_dependency (bool bind_now)
293 static const int tlsmanydeps[] = { 0, 1, 3, 6, 10 };
295 /* The gap configuration is defined as a bitmap: the bit set represents a
296 loaded module prior the tests execution, while a bit unsed is a module
297 unloaded. Not all permtation will show gaps, but it is simpler than
298 define each one independently. */
299 for (uint32_t g = 0; g < 64; g++)
301 print_gap (g);
302 int nmods = nmodules (g);
304 int mods[nmods];
305 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
306 cleanup. */
307 for (int n = 1; n < nmods; n++)
309 load_mod (n);
310 mods[n] = n;
312 for (int n = 1; n < nmods; n++)
314 if (!is_mod_set (g, n))
316 unload_mod (n);
317 mods[n] = 0;
321 for (int t = 0; t < array_length (tlsmanydeps); t++)
323 char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep-bad.so",
324 tlsmanydeps[t]);
325 void *moddep;
326 if (bind_now)
328 moddep = dlopen (moddepname, RTLD_NOW);
329 TEST_VERIFY (moddep == 0);
331 else
332 moddep = dlopen (moddepname, RTLD_LAZY);
334 /* Access TLS in all loaded modules. */
335 pthread_t t = xpthread_create (0, start, NULL);
336 xpthread_join (t);
338 free (moddepname);
339 if (!bind_now)
340 xdlclose (moddep);
343 for (int n = 1; n <= nmods; n++)
344 if (mods[n] != 0)
345 unload_mod (n);
349 static int
350 do_test (void)
352 do_test_no_depedency ();
353 do_test_dependency ();
354 do_test_invalid_dependency (true);
355 do_test_invalid_dependency (false);
357 return 0;
360 #include <support/test-driver.c>