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>
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>
31 static void *mod
[NMOD
];
36 /* Expected to fail because of a missing symbol. */
37 void *m
= dlopen ("tst-tls20mod-bad.so", RTLD_NOW
);
39 FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
45 char *buf
= xasprintf ("tst-tls-manydynamic%02dmod.so", i
);
46 mod
[i
] = xdlopen (buf
, RTLD_LAZY
);
61 char *buf
= xasprintf ("tls_global_%02d", i
);
63 int *p
= dlsym (mod
[i
], buf
);
65 printf ("mod[%d]: &tls = %p\n", i
, p
);
67 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
74 access_mod (const char *modname
, void *mod
, int i
)
76 char *modsym
= xasprintf ("tls_global_%d", i
);
78 int *p
= dlsym (mod
, modsym
);
80 printf ("%s: &tls = %p\n", modname
, p
);
82 FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
91 char *modname
= xasprintf ("tst-tls-manydynamic%dmod-dep.so", i
);
92 void *moddep
= xdlopen (modname
, RTLD_LAZY
);
93 access_mod (modname
, moddep
, i
);
110 struct start_args
*args
= a
;
112 for (int i
= 0; i
< NMOD
; i
++)
118 access_mod (args
->modname
, args
->mod
, args
->modi
);
119 for (int n
= 0; n
< args
->ndeps
; n
++)
120 access_dep (args
->deps
[n
]);
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. */
130 do_test_no_depedency (void)
132 for (int i
= 0; i
< NMOD
; i
++)
135 /* Bump the generation of mod[0] without using new dtv slot. */
137 load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135. */
139 /* Access TLS in all loaded modules. */
140 pthread_t t
= xpthread_create (0, start
, 0);
143 for (int i
= 0; i
< NMOD
; 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:
152 2. Double dependency:
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. */
167 nmodules (uint32_t v
)
176 is_mod_set (uint32_t g
, uint32_t n
)
178 return (1U << (n
- 1)) & g
;
182 print_gap (uint32_t g
)
187 int nmods
= nmodules (g
);
188 for (int n
= 1; n
<= nmods
; n
++)
189 printf ("%c", ((1 << (n
- 1)) & g
) == 0 ? 'G' : 'M');
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
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
++)
224 int nmods
= nmodules (g
);
227 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
229 for (int n
= 1; n
< nmods
; n
++)
234 for (int n
= 1; n
< nmods
; n
++)
236 if (!is_mod_set (g
, n
))
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
=
255 tlsmanydeps
[t
].ndeps
,
258 pthread_t t
= xpthread_create (0, start
, &args
);
265 for (int n
= 1; n
<= nmods
; 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:
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. */
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
++)
302 int nmods
= nmodules (g
);
305 /* We use '0' as indication for a gap, to avoid the dlclose on iteration
307 for (int n
= 1; n
< nmods
; n
++)
312 for (int n
= 1; n
< nmods
; n
++)
314 if (!is_mod_set (g
, n
))
321 for (int t
= 0; t
< array_length (tlsmanydeps
); t
++)
323 char *moddepname
= xasprintf ("tst-tls-manydynamic%dmod-dep-bad.so",
328 moddep
= dlopen (moddepname
, RTLD_NOW
);
329 TEST_VERIFY (moddep
== 0);
332 moddep
= dlopen (moddepname
, RTLD_LAZY
);
334 /* Access TLS in all loaded modules. */
335 pthread_t t
= xpthread_create (0, start
, NULL
);
343 for (int n
= 1; n
<= nmods
; n
++)
352 do_test_no_depedency ();
353 do_test_dependency ();
354 do_test_invalid_dependency (true);
355 do_test_invalid_dependency (false);
360 #include <support/test-driver.c>