1 /* Test dtv setup if entries don't have monotone increasing generation.
2 Copyright (C) 2021-2023 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>
26 #include <support/check.h>
27 #include <support/support.h>
28 #include <support/test-driver.h>
29 #include <support/xdlfcn.h>
30 #include <support/xthread.h>
33 static void *mod
[NMOD
];
38 /* Expected to fail because of a missing symbol. */
39 void *m
= dlopen ("tst-tls20mod-bad.so", RTLD_NOW
);
41 FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
47 char *buf
= xasprintf ("tst-tls-manydynamic%02dmod.so", i
);
48 mod
[i
] = xdlopen (buf
, RTLD_LAZY
);
63 char *buf
= xasprintf ("tls_global_%02d", i
);
65 int *p
= dlsym (mod
[i
], buf
);
67 printf ("mod[%d]: &tls = %p\n", i
, p
);
69 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
76 access_mod (const char *modname
, void *mod
, int i
)
78 char *modsym
= xasprintf ("tls_global_%d", i
);
80 int *p
= dlsym (mod
, modsym
);
82 printf ("%s: &tls = %p\n", modname
, p
);
84 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
93 char *modname
= xasprintf ("tst-tls-manydynamic%dmod-dep.so", i
);
94 void *moddep
= xdlopen (modname
, RTLD_LAZY
);
95 access_mod (modname
, moddep
, i
);
112 struct start_args
*args
= a
;
114 for (int i
= 0; i
< NMOD
; i
++)
120 access_mod (args
->modname
, args
->mod
, args
->modi
);
121 for (int n
= 0; n
< args
->ndeps
; n
++)
122 access_dep (args
->deps
[n
]);
128 /* This test gaps with shared libraries with dynamic TLS that has no
129 dependencies. The DTV gap is set with by trying to load an invalid
130 module, the entry should be used on the dlopen. */
132 do_test_no_depedency (void)
134 for (int i
= 0; i
< NMOD
; i
++)
137 /* Bump the generation of mod[0] without using new dtv slot. */
139 load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135. */
141 /* Access TLS in all loaded modules. */
142 pthread_t t
= xpthread_create (0, start
, 0);
145 for (int i
= 0; i
< NMOD
; i
++)
149 /* The following test check DTV gaps handling with shared libraries that has
150 dependencies. It defines 5 different sets:
152 1. Single dependency:
154 2. Double dependency:
156 3. Double dependency with each dependency depent of another module:
157 mod5 -> [mod6,mod7] -> mod8
158 4. Long chain with one double dependency in the middle:
159 mod9 -> [mod10, mod11] -> mod12 -> mod13
160 5. Long chain with two double depedencies in the middle:
161 mod14 -> mod15 -> [mod16, mod17]
162 mod15 -> [mod18, mod19]
164 This does not cover all the possible gaps and configuration, but it
165 should check if different dynamic shared sets are placed correctly in
166 different gaps configurations. */
169 nmodules (uint32_t v
)
178 is_mod_set (uint32_t g
, uint32_t n
)
180 return (1U << (n
- 1)) & g
;
184 print_gap (uint32_t g
)
189 int nmods
= nmodules (g
);
190 for (int n
= 1; n
<= nmods
; n
++)
191 printf ("%c", ((1 << (n
- 1)) & g
) == 0 ? 'G' : 'M');
196 do_test_dependency (void)
198 /* Maps the module and its dependencies, use thread to access the TLS on
199 each loaded module. */
200 static const int tlsmanydeps0
[] = { 1 };
201 static const int tlsmanydeps1
[] = { 3, 4 };
202 static const int tlsmanydeps2
[] = { 6, 7, 8 };
203 static const int tlsmanydeps3
[] = { 10, 11, 12 };
204 static const int tlsmanydeps4
[] = { 15, 16, 17, 18, 19 };
205 static const struct tlsmanydeps_t
212 { 0, array_length (tlsmanydeps0
), tlsmanydeps0
},
213 { 2, array_length (tlsmanydeps1
), tlsmanydeps1
},
214 { 5, array_length (tlsmanydeps2
), tlsmanydeps2
},
215 { 9, array_length (tlsmanydeps3
), tlsmanydeps3
},
216 { 14, array_length (tlsmanydeps4
), tlsmanydeps4
},
219 /* The gap configuration is defined as a bitmap: the bit set represents a
220 loaded module prior the tests execution, while a bit unsed is a module
221 unloaded. Not all permtation will show gaps, but it is simpler than
222 define each one independently. */
223 for (uint32_t g
= 0; g
< 64; g
++)
226 int nmods
= nmodules (g
);
229 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
231 for (int n
= 1; n
< nmods
; n
++)
236 for (int n
= 1; n
< nmods
; n
++)
238 if (!is_mod_set (g
, n
))
245 for (int t
= 0; t
< array_length (tlsmanydeps
); t
++)
247 char *moddepname
= xasprintf ("tst-tls-manydynamic%dmod-dep.so",
248 tlsmanydeps
[t
].modi
);
249 void *moddep
= xdlopen (moddepname
, RTLD_LAZY
);
251 /* Access TLS in all loaded modules. */
252 struct start_args args
=
257 tlsmanydeps
[t
].ndeps
,
260 pthread_t t
= xpthread_create (0, start
, &args
);
267 for (int n
= 1; n
< nmods
; n
++)
273 /* The following test check DTV gaps handling with shared libraries that has
274 invalid dependencies. It defines 5 different sets:
276 1. Single dependency:
278 2. Double dependency:
279 mod1 -> [mod2,invalid]
280 3. Double dependency with each dependency depent of another module:
281 mod3 -> [mod4,mod5] -> invalid
282 4. Long chain with one double dependency in the middle:
283 mod6 -> [mod7, mod8] -> mod12 -> invalid
284 5. Long chain with two double depedencies in the middle:
285 mod10 -> mod11 -> [mod12, mod13]
286 mod12 -> [mod14, invalid]
288 This does not cover all the possible gaps and configuration, but it
289 should check if different dynamic shared sets are placed correctly in
290 different gaps configurations. */
293 do_test_invalid_dependency (bool bind_now
)
295 static const int tlsmanydeps
[] = { 0, 1, 3, 6, 10 };
297 /* The gap configuration is defined as a bitmap: the bit set represents a
298 loaded module prior the tests execution, while a bit unsed is a module
299 unloaded. Not all permtation will show gaps, but it is simpler than
300 define each one independently. */
301 for (uint32_t g
= 0; g
< 64; g
++)
304 int nmods
= nmodules (g
);
307 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
309 for (int n
= 1; n
< nmods
; n
++)
314 for (int n
= 1; n
< nmods
; n
++)
316 if (!is_mod_set (g
, n
))
323 for (int t
= 0; t
< array_length (tlsmanydeps
); t
++)
325 char *moddepname
= xasprintf ("tst-tls-manydynamic%dmod-dep-bad.so",
330 moddep
= dlopen (moddepname
, RTLD_NOW
);
331 TEST_VERIFY (moddep
== 0);
334 moddep
= dlopen (moddepname
, RTLD_LAZY
);
336 /* Access TLS in all loaded modules. */
337 pthread_t t
= xpthread_create (0, start
, NULL
);
345 for (int n
= 1; n
< nmods
; n
++)
354 do_test_no_depedency ();
355 do_test_dependency ();
356 do_test_invalid_dependency (true);
357 do_test_invalid_dependency (false);
362 #include <support/test-driver.c>