xref: /netbsd-src/tests/libexec/ld.elf_so/t_tls_extern.c (revision 41caf4e57810960e1c9317e2a147f2502878ed5d)
1*41caf4e5Sriastradh /*	$NetBSD: t_tls_extern.c,v 1.16 2024/07/23 18:11:53 riastradh Exp $	*/
212037d6aSriastradh 
312037d6aSriastradh /*-
412037d6aSriastradh  * Copyright (c) 2023 The NetBSD Foundation, Inc.
512037d6aSriastradh  * All rights reserved.
612037d6aSriastradh  *
712037d6aSriastradh  * Redistribution and use in source and binary forms, with or without
812037d6aSriastradh  * modification, are permitted provided that the following conditions
912037d6aSriastradh  * are met:
1012037d6aSriastradh  * 1. Redistributions of source code must retain the above copyright
1112037d6aSriastradh  *    notice, this list of conditions and the following disclaimer.
1212037d6aSriastradh  * 2. Redistributions in binary form must reproduce the above copyright
1312037d6aSriastradh  *    notice, this list of conditions and the following disclaimer in the
1412037d6aSriastradh  *    documentation and/or other materials provided with the distribution.
1512037d6aSriastradh  *
1612037d6aSriastradh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1712037d6aSriastradh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1812037d6aSriastradh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1912037d6aSriastradh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2012037d6aSriastradh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2112037d6aSriastradh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2212037d6aSriastradh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2312037d6aSriastradh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2412037d6aSriastradh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2512037d6aSriastradh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2612037d6aSriastradh  * POSSIBILITY OF SUCH DAMAGE.
2712037d6aSriastradh  */
2812037d6aSriastradh 
2912037d6aSriastradh #include <sys/types.h>
3012037d6aSriastradh 
3112037d6aSriastradh #include <atf-c.h>
3212037d6aSriastradh #include <dlfcn.h>
3312037d6aSriastradh 
342b3021f9Skre #define	ATF_REQUIRE_DL(x) ATF_REQUIRE_MSG((x) != 0, "%s: %s", #x, dlerror())
3512037d6aSriastradh 
36bc9d9d11Sriastradh enum order {
3798256cacSriastradh 	DEF_USE_EAGER,
3898256cacSriastradh 	DEF_USE_LAZY,
39bc9d9d11Sriastradh 	USE_DEF,
40bc9d9d11Sriastradh 	USE_DEF_NOLOAD,
41bc9d9d11Sriastradh };
42bc9d9d11Sriastradh 
43bc9d9d11Sriastradh static void
443caa8dc7Sjoerg tls_extern(const char *libdef, const char *libuse, enum order order)
45bc9d9d11Sriastradh {
46bc9d9d11Sriastradh 	void *def, *use;
47bc9d9d11Sriastradh 	int *(*fdef)(void), *(*fuse)(void);
48bc9d9d11Sriastradh 	int *pdef, *puse;
49bc9d9d11Sriastradh 
50bc9d9d11Sriastradh 	(void)dlerror();
51bc9d9d11Sriastradh 
52bc9d9d11Sriastradh 	switch (order) {
5398256cacSriastradh 	case DEF_USE_EAGER:
5498256cacSriastradh 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
5598256cacSriastradh 		ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
5698256cacSriastradh 		pdef = (*fdef)();
5798256cacSriastradh 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
5898256cacSriastradh 		ATF_REQUIRE_DL(fuse = dlsym(use, "fuse"));
5998256cacSriastradh 		puse = (*fuse)();
6098256cacSriastradh 		break;
6198256cacSriastradh 	case DEF_USE_LAZY:
62bc9d9d11Sriastradh 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
63bc9d9d11Sriastradh 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
6498256cacSriastradh 		goto lazy;
65bc9d9d11Sriastradh 	case USE_DEF:
66bc9d9d11Sriastradh 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
67bc9d9d11Sriastradh 		ATF_REQUIRE_DL(def = dlopen(libdef, 0));
6898256cacSriastradh 		goto lazy;
69bc9d9d11Sriastradh 	case USE_DEF_NOLOAD:
70bc9d9d11Sriastradh 		ATF_REQUIRE_DL(use = dlopen(libuse, 0));
71bc9d9d11Sriastradh 		ATF_REQUIRE_DL(def = dlopen(libdef, RTLD_NOLOAD));
7298256cacSriastradh lazy:		ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
7398256cacSriastradh 		ATF_REQUIRE_DL(fuse = dlsym(use, "fuse"));
7498256cacSriastradh 		pdef = (*fdef)();
7598256cacSriastradh 		puse = (*fuse)();
76bc9d9d11Sriastradh 		break;
77bc9d9d11Sriastradh 	}
78bc9d9d11Sriastradh 
79bc9d9d11Sriastradh 	ATF_CHECK_EQ_MSG(pdef, puse,
80bc9d9d11Sriastradh 	    "%p in defining library != %p in using library",
81bc9d9d11Sriastradh 	    pdef, puse);
82bc9d9d11Sriastradh }
83bc9d9d11Sriastradh 
84e04ffa37Sriastradh ATF_TC(dynamic_abusedef);
85e04ffa37Sriastradh ATF_TC_HEAD(dynamic_abusedef, tc)
866b7ae3beSriastradh {
876b7ae3beSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
886b7ae3beSriastradh 	    " loading static use than dynamic def");
896b7ae3beSriastradh }
90e04ffa37Sriastradh ATF_TC_BODY(dynamic_abusedef, tc)
916b7ae3beSriastradh {
923caa8dc7Sjoerg 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so", USE_DEF);
936b7ae3beSriastradh }
946b7ae3beSriastradh 
95e04ffa37Sriastradh ATF_TC(dynamic_abusedefnoload);
96e04ffa37Sriastradh ATF_TC_HEAD(dynamic_abusedefnoload, tc)
976b7ae3beSriastradh {
986b7ae3beSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
996b7ae3beSriastradh 	    " loading static use then dynamic def with RTLD_NOLOAD");
1006b7ae3beSriastradh }
101e04ffa37Sriastradh ATF_TC_BODY(dynamic_abusedefnoload, tc)
1026b7ae3beSriastradh {
1036b7ae3beSriastradh 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so",
1043caa8dc7Sjoerg 	    USE_DEF_NOLOAD);
1056b7ae3beSriastradh }
1066b7ae3beSriastradh 
10798256cacSriastradh ATF_TC(dynamic_defabuse_eager);
10898256cacSriastradh ATF_TC_HEAD(dynamic_defabuse_eager, tc)
1096b7ae3beSriastradh {
1104dedd5fcSriastradh 	atf_tc_set_md_var(tc, "descr", "dlopen refuses extern __thread for TLS,"
11198256cacSriastradh 	    " loading dynamic def then static use eagerly");
1126b7ae3beSriastradh }
11398256cacSriastradh ATF_TC_BODY(dynamic_defabuse_eager, tc)
1146b7ae3beSriastradh {
1154dedd5fcSriastradh 	void *def;
1164dedd5fcSriastradh 	int *(*fdef)(void);
1174dedd5fcSriastradh 
1184dedd5fcSriastradh 	ATF_REQUIRE_DL(def = dlopen("libh_def_dynamic.so", 0));
1194dedd5fcSriastradh 	ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
1204dedd5fcSriastradh 	(void)(*fdef)();
1214dedd5fcSriastradh 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_abuse_dynamic.so", 0),
1224dedd5fcSriastradh 	    "dlopen failed to detect static-then-dynamic abuse");
1236b7ae3beSriastradh }
1246b7ae3beSriastradh 
12598256cacSriastradh ATF_TC(dynamic_defabuse_lazy);
12698256cacSriastradh ATF_TC_HEAD(dynamic_defabuse_lazy, tc)
12798256cacSriastradh {
12898256cacSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
12998256cacSriastradh 	    " loading dynamic def then static use lazily");
13098256cacSriastradh }
13198256cacSriastradh ATF_TC_BODY(dynamic_defabuse_lazy, tc)
13298256cacSriastradh {
13398256cacSriastradh 	tls_extern("libh_def_dynamic.so", "libh_abuse_dynamic.so",
1343caa8dc7Sjoerg 	    DEF_USE_LAZY);
13598256cacSriastradh }
13698256cacSriastradh 
13798256cacSriastradh ATF_TC(dynamic_defuse_eager);
13898256cacSriastradh ATF_TC_HEAD(dynamic_defuse_eager, tc)
13905e97b5aSriastradh {
14005e97b5aSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
14198256cacSriastradh 	    " loading def then use eagerly");
14205e97b5aSriastradh }
14398256cacSriastradh ATF_TC_BODY(dynamic_defuse_eager, tc)
14405e97b5aSriastradh {
145bc9d9d11Sriastradh 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
1463caa8dc7Sjoerg 	    DEF_USE_EAGER);
14798256cacSriastradh }
14898256cacSriastradh 
14998256cacSriastradh ATF_TC(dynamic_defuse_lazy);
15098256cacSriastradh ATF_TC_HEAD(dynamic_defuse_lazy, tc)
15198256cacSriastradh {
15298256cacSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
15398256cacSriastradh 	    " loading def then use lazyly");
15498256cacSriastradh }
15598256cacSriastradh ATF_TC_BODY(dynamic_defuse_lazy, tc)
15698256cacSriastradh {
15798256cacSriastradh 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
1583caa8dc7Sjoerg 	    DEF_USE_LAZY);
15905e97b5aSriastradh }
16005e97b5aSriastradh 
161e04ffa37Sriastradh ATF_TC(dynamic_usedef);
162e04ffa37Sriastradh ATF_TC_HEAD(dynamic_usedef, tc)
16305e97b5aSriastradh {
16405e97b5aSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
16505e97b5aSriastradh 	    " loading use then def");
16605e97b5aSriastradh }
167e04ffa37Sriastradh ATF_TC_BODY(dynamic_usedef, tc)
16805e97b5aSriastradh {
169bc9d9d11Sriastradh 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
1703caa8dc7Sjoerg 	    USE_DEF);
17105e97b5aSriastradh }
17205e97b5aSriastradh 
173e04ffa37Sriastradh ATF_TC(dynamic_usedefnoload);
174e04ffa37Sriastradh ATF_TC_HEAD(dynamic_usedefnoload, tc)
17505e97b5aSriastradh {
17605e97b5aSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for dynamic TLS works,"
17705e97b5aSriastradh 	    " loading use then def with RTLD_NOLOAD");
17805e97b5aSriastradh }
179e04ffa37Sriastradh ATF_TC_BODY(dynamic_usedefnoload, tc)
18005e97b5aSriastradh {
181bc9d9d11Sriastradh 	tls_extern("libh_def_dynamic.so", "libh_use_dynamic.so",
1823caa8dc7Sjoerg 	    USE_DEF_NOLOAD);
18305e97b5aSriastradh }
18405e97b5aSriastradh 
185e04ffa37Sriastradh ATF_TC(static_abusedef);
186e04ffa37Sriastradh ATF_TC_HEAD(static_abusedef, tc)
1876b7ae3beSriastradh {
1886b7ae3beSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
1896b7ae3beSriastradh 	    " loading dynamic use then static def");
1906b7ae3beSriastradh }
191e04ffa37Sriastradh ATF_TC_BODY(static_abusedef, tc)
1926b7ae3beSriastradh {
1933caa8dc7Sjoerg 	tls_extern("libh_def_static.so", "libh_abuse_static.so", USE_DEF);
1946b7ae3beSriastradh }
1956b7ae3beSriastradh 
196e04ffa37Sriastradh ATF_TC(static_abusedefnoload);
197e04ffa37Sriastradh ATF_TC_HEAD(static_abusedefnoload, tc)
1986b7ae3beSriastradh {
1996b7ae3beSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
2006b7ae3beSriastradh 	    " loading dynamic use then static def with RTLD_NOLOAD");
2016b7ae3beSriastradh }
202e04ffa37Sriastradh ATF_TC_BODY(static_abusedefnoload, tc)
2036b7ae3beSriastradh {
2046b7ae3beSriastradh 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
2053caa8dc7Sjoerg 	    USE_DEF_NOLOAD);
2066b7ae3beSriastradh }
2076b7ae3beSriastradh 
20898256cacSriastradh ATF_TC(static_defabuse_eager);
20998256cacSriastradh ATF_TC_HEAD(static_defabuse_eager, tc)
2106b7ae3beSriastradh {
2116b7ae3beSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
21298256cacSriastradh 	    " loading static def then dynamic use eagerly");
2136b7ae3beSriastradh }
21498256cacSriastradh ATF_TC_BODY(static_defabuse_eager, tc)
2156b7ae3beSriastradh {
2166b7ae3beSriastradh 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
2173caa8dc7Sjoerg 	    DEF_USE_EAGER);
2186b7ae3beSriastradh }
2196b7ae3beSriastradh 
22098256cacSriastradh ATF_TC(static_defabuse_lazy);
22198256cacSriastradh ATF_TC_HEAD(static_defabuse_lazy, tc)
22298256cacSriastradh {
22398256cacSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
22498256cacSriastradh 	    " loading static def then dynamic use lazyly");
22598256cacSriastradh }
22698256cacSriastradh ATF_TC_BODY(static_defabuse_lazy, tc)
22798256cacSriastradh {
22898256cacSriastradh 	tls_extern("libh_def_static.so", "libh_abuse_static.so",
2293caa8dc7Sjoerg 	    DEF_USE_LAZY);
23098256cacSriastradh }
23198256cacSriastradh 
23298256cacSriastradh ATF_TC(static_defuse_eager);
23398256cacSriastradh ATF_TC_HEAD(static_defuse_eager, tc)
23412037d6aSriastradh {
235f4e155a4Sriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
23698256cacSriastradh 	    " loading def then use eagerly");
23712037d6aSriastradh }
23898256cacSriastradh ATF_TC_BODY(static_defuse_eager, tc)
23912037d6aSriastradh {
240bc9d9d11Sriastradh 	tls_extern("libh_def_static.so", "libh_use_static.so",
2413caa8dc7Sjoerg 	    DEF_USE_EAGER);
24298256cacSriastradh }
24398256cacSriastradh 
24498256cacSriastradh ATF_TC(static_defuse_lazy);
24598256cacSriastradh ATF_TC_HEAD(static_defuse_lazy, tc)
24698256cacSriastradh {
24798256cacSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
24898256cacSriastradh 	    " loading def then use lazyly");
24998256cacSriastradh }
25098256cacSriastradh ATF_TC_BODY(static_defuse_lazy, tc)
25198256cacSriastradh {
25298256cacSriastradh 	tls_extern("libh_def_static.so", "libh_use_static.so",
2533caa8dc7Sjoerg 	    DEF_USE_LAZY);
254f4e155a4Sriastradh }
255f4e155a4Sriastradh 
256e04ffa37Sriastradh ATF_TC(static_usedef);
257e04ffa37Sriastradh ATF_TC_HEAD(static_usedef, tc)
258f4e155a4Sriastradh {
259f4e155a4Sriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
260f4e155a4Sriastradh 	    " loading use then def");
261f4e155a4Sriastradh }
262e04ffa37Sriastradh ATF_TC_BODY(static_usedef, tc)
263f4e155a4Sriastradh {
264bc9d9d11Sriastradh 	tls_extern("libh_def_static.so", "libh_use_static.so",
2653caa8dc7Sjoerg 	    USE_DEF);
266f4e155a4Sriastradh }
267f4e155a4Sriastradh 
268e04ffa37Sriastradh ATF_TC(static_usedefnoload);
269e04ffa37Sriastradh ATF_TC_HEAD(static_usedefnoload, tc)
270f4e155a4Sriastradh {
271f4e155a4Sriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for static TLS works,"
272f4e155a4Sriastradh 	    " loading use then def with RTLD_NOLOAD");
273f4e155a4Sriastradh }
274e04ffa37Sriastradh ATF_TC_BODY(static_usedefnoload, tc)
275f4e155a4Sriastradh {
276bc9d9d11Sriastradh 	tls_extern("libh_def_static.so", "libh_use_static.so",
2773caa8dc7Sjoerg 	    USE_DEF_NOLOAD);
27812037d6aSriastradh }
27912037d6aSriastradh 
280067c5136Sriastradh ATF_TC(onlydef_dynamic_static_ctor);
281067c5136Sriastradh ATF_TC_HEAD(onlydef_dynamic_static_ctor, tc)
282067c5136Sriastradh {
283067c5136Sriastradh 	atf_tc_set_md_var(tc, "descr", "definition-only library,"
284067c5136Sriastradh 	    " dynamic load and use in ctor, then static load fails");
285067c5136Sriastradh }
286067c5136Sriastradh ATF_TC_BODY(onlydef_dynamic_static_ctor, tc)
287067c5136Sriastradh {
288067c5136Sriastradh 
289067c5136Sriastradh 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
290067c5136Sriastradh 	ATF_REQUIRE_DL(dlopen("libh_onlyctor_dynamic.so", 0));
291067c5136Sriastradh 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_onlyuse_static.so", 0),
292067c5136Sriastradh 	    "dlopen failed to detect dynamic-then-static abuse");
293067c5136Sriastradh }
294067c5136Sriastradh 
295f4e534ddSriastradh ATF_TC(onlydef_dynamic_static_eager);
296f4e534ddSriastradh ATF_TC_HEAD(onlydef_dynamic_static_eager, tc)
297f4e534ddSriastradh {
298f4e534ddSriastradh 	atf_tc_set_md_var(tc, "descr", "definition-only library,"
299f4e534ddSriastradh 	    " dynamic load and use, then static load fails");
300f4e534ddSriastradh }
301f4e534ddSriastradh ATF_TC_BODY(onlydef_dynamic_static_eager, tc)
302f4e534ddSriastradh {
303f4e534ddSriastradh 	void *use_dynamic;
304f4e534ddSriastradh 	int *(*fdynamic)(void);
305f4e534ddSriastradh 
306f4e534ddSriastradh 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
307f4e534ddSriastradh 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
308f4e534ddSriastradh 	(void)(*fdynamic)();
309f4e534ddSriastradh 	ATF_CHECK_EQ_MSG(NULL, dlopen("libh_onlyuse_static.so", 0),
310f4e534ddSriastradh 	    "dlopen failed to detect dynamic-then-static abuse");
311f4e534ddSriastradh }
312f4e534ddSriastradh 
313f4e534ddSriastradh ATF_TC(onlydef_dynamic_static_lazy);
314f4e534ddSriastradh ATF_TC_HEAD(onlydef_dynamic_static_lazy, tc)
315f4e534ddSriastradh {
316f4e534ddSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
317f4e534ddSriastradh 	    " with definition-only library, dynamic and static load and use");
318f4e534ddSriastradh }
319f4e534ddSriastradh ATF_TC_BODY(onlydef_dynamic_static_lazy, tc)
320f4e534ddSriastradh {
321f4e534ddSriastradh 	void *use_dynamic, *use_static;
322f4e534ddSriastradh 	int *(*fdynamic)(void), *(*fstatic)(void);
323f4e534ddSriastradh 	int *pdynamic, *pstatic;
324f4e534ddSriastradh 
325f4e534ddSriastradh 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
326f4e534ddSriastradh 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
327f4e534ddSriastradh 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
328f4e534ddSriastradh 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
329f4e534ddSriastradh 	pdynamic = (*fdynamic)();
330f4e534ddSriastradh 	pstatic = (*fstatic)();
331f4e534ddSriastradh 	ATF_CHECK_EQ_MSG(pdynamic, pstatic,
332f4e534ddSriastradh 	    "%p in dynamic tls user != %p in static tls user",
333f4e534ddSriastradh 	    pdynamic, pstatic);
334f4e534ddSriastradh }
335f4e534ddSriastradh 
336f4e534ddSriastradh ATF_TC(onlydef_static_dynamic_eager);
337f4e534ddSriastradh ATF_TC_HEAD(onlydef_static_dynamic_eager, tc)
338f4e534ddSriastradh {
339f4e534ddSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
340f4e534ddSriastradh 	    " with definition-only library,"
341f4e534ddSriastradh 	    " static load and use, then dynamic load and use");
342f4e534ddSriastradh }
343f4e534ddSriastradh ATF_TC_BODY(onlydef_static_dynamic_eager, tc)
344f4e534ddSriastradh {
345f4e534ddSriastradh 	void *use_static, *use_dynamic;
346f4e534ddSriastradh 	int *(*fstatic)(void), *(*fdynamic)(void);
347f4e534ddSriastradh 	int *pstatic, *pdynamic;
348f4e534ddSriastradh 
349f4e534ddSriastradh 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
350f4e534ddSriastradh 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
351f4e534ddSriastradh 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
352f4e534ddSriastradh 	pstatic = (*fstatic)();
353f4e534ddSriastradh 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
354f4e534ddSriastradh 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
355f4e534ddSriastradh 	pdynamic = (*fdynamic)();
356f4e534ddSriastradh 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
357f4e534ddSriastradh 	    "%p in static tls user != %p in dynamic tls user",
358f4e534ddSriastradh 	    pstatic, pdynamic);
359f4e534ddSriastradh }
360f4e534ddSriastradh 
361f4e534ddSriastradh ATF_TC(onlydef_static_dynamic_lazy);
362f4e534ddSriastradh ATF_TC_HEAD(onlydef_static_dynamic_lazy, tc)
363f4e534ddSriastradh {
364f4e534ddSriastradh 	atf_tc_set_md_var(tc, "descr", "extern __thread for TLS works,"
365f4e534ddSriastradh 	    " with definition-only library, static and dynamic load and use");
366f4e534ddSriastradh }
367f4e534ddSriastradh ATF_TC_BODY(onlydef_static_dynamic_lazy, tc)
368f4e534ddSriastradh {
369f4e534ddSriastradh 	void *use_static, *use_dynamic;
370f4e534ddSriastradh 	int *(*fstatic)(void), *(*fdynamic)(void);
371f4e534ddSriastradh 	int *pstatic, *pdynamic;
372f4e534ddSriastradh 
373f4e534ddSriastradh 	ATF_REQUIRE_DL(dlopen("libh_onlydef.so", 0));
374f4e534ddSriastradh 	ATF_REQUIRE_DL(use_static = dlopen("libh_onlyuse_static.so", 0));
375f4e534ddSriastradh 	ATF_REQUIRE_DL(use_dynamic = dlopen("libh_onlyuse_dynamic.so", 0));
376f4e534ddSriastradh 	ATF_REQUIRE_DL(fstatic = dlsym(use_static, "fstatic"));
377f4e534ddSriastradh 	ATF_REQUIRE_DL(fdynamic = dlsym(use_dynamic, "fdynamic"));
378f4e534ddSriastradh 	pstatic = (*fstatic)();
379f4e534ddSriastradh 	pdynamic = (*fdynamic)();
380f4e534ddSriastradh 	ATF_CHECK_EQ_MSG(pstatic, pdynamic,
381f4e534ddSriastradh 	    "%p in static tls user != %p in dynamic tls user",
382f4e534ddSriastradh 	    pstatic, pdynamic);
383f4e534ddSriastradh }
384f4e534ddSriastradh 
3859a31d868Sriastradh ATF_TC(opencloseloop_use);
3869a31d868Sriastradh ATF_TC_HEAD(opencloseloop_use, tc)
3879a31d868Sriastradh {
3889a31d868Sriastradh 	atf_tc_set_md_var(tc, "descr", "Testing opening and closing in a loop,"
3899a31d868Sriastradh 	    " then opening and using dynamic TLS");
3909a31d868Sriastradh }
3919a31d868Sriastradh ATF_TC_BODY(opencloseloop_use, tc)
3929a31d868Sriastradh {
3939a31d868Sriastradh 	unsigned i;
3949a31d868Sriastradh 	void *def, *use;
3959a31d868Sriastradh 	int *(*fdef)(void), *(*fuse)(void);
3969a31d868Sriastradh 	int *pdef, *puse;
3979a31d868Sriastradh 
3989a31d868Sriastradh 	/*
3999a31d868Sriastradh 	 * Open and close the definition library repeatedly.  This
4009a31d868Sriastradh 	 * should trigger allocation of many DTV offsets, which are
4019a31d868Sriastradh 	 * (currently) not recycled, so the required DTV offsets should
4029a31d868Sriastradh 	 * become very long -- pages past what is actually allocated
4039a31d868Sriastradh 	 * before we attempt to use it.
4049a31d868Sriastradh 	 *
4059a31d868Sriastradh 	 * This way, we will exercise the wrong-way-conditional fast
4069a31d868Sriastradh 	 * path of PR lib/58154.
4079a31d868Sriastradh 	 */
4089a31d868Sriastradh 	for (i = sysconf(_SC_PAGESIZE); i --> 0;) {
4099a31d868Sriastradh 		ATF_REQUIRE_DL(def = dlopen("libh_def_dynamic.so", 0));
4109a31d868Sriastradh 		ATF_REQUIRE_EQ_MSG(dlclose(def), 0,
4119a31d868Sriastradh 		    "dlclose(def): %s", dlerror());
4129a31d868Sriastradh 	}
4139a31d868Sriastradh 
4149a31d868Sriastradh 	/*
4159a31d868Sriastradh 	 * Now open the definition library and keep it open.
4169a31d868Sriastradh 	 */
4179a31d868Sriastradh 	ATF_REQUIRE_DL(def = dlopen("libh_def_dynamic.so", 0));
4189a31d868Sriastradh 	ATF_REQUIRE_DL(fdef = dlsym(def, "fdef"));
4199a31d868Sriastradh 
4209a31d868Sriastradh 	/*
4219a31d868Sriastradh 	 * Open libraries that use the definition and verify they
4229a31d868Sriastradh 	 * observe the same pointer.
4239a31d868Sriastradh 	 */
4249a31d868Sriastradh 	ATF_REQUIRE_DL(use = dlopen("libh_use_dynamic.so", 0));
4259a31d868Sriastradh 	ATF_REQUIRE_DL(fuse = dlsym(use, "fuse"));
4269a31d868Sriastradh 	pdef = (*fdef)();
4279a31d868Sriastradh 	puse = (*fuse)();
4289a31d868Sriastradh 	ATF_CHECK_EQ_MSG(pdef, puse,
4299a31d868Sriastradh 	    "%p in defining library != %p in using library",
4309a31d868Sriastradh 	    pdef, puse);
4319a31d868Sriastradh 
4329a31d868Sriastradh 	/*
4339a31d868Sriastradh 	 * Also verify the pointer can be used.
4349a31d868Sriastradh 	 */
4359a31d868Sriastradh 	*pdef = 123;
4369a31d868Sriastradh 	*puse = 456;
4379a31d868Sriastradh 	ATF_CHECK_EQ_MSG(*pdef, *puse,
4389a31d868Sriastradh 	    "%d in defining library != %d in using library",
4399a31d868Sriastradh 	    *pdef, *puse);
4409a31d868Sriastradh }
4419a31d868Sriastradh 
44212037d6aSriastradh ATF_TP_ADD_TCS(tp)
44312037d6aSriastradh {
444f4e155a4Sriastradh 
445e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, dynamic_abusedef);
446e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, dynamic_abusedefnoload);
44798256cacSriastradh 	ATF_TP_ADD_TC(tp, dynamic_defabuse_eager);
44898256cacSriastradh 	ATF_TP_ADD_TC(tp, dynamic_defabuse_lazy);
44998256cacSriastradh 	ATF_TP_ADD_TC(tp, dynamic_defuse_eager);
45098256cacSriastradh 	ATF_TP_ADD_TC(tp, dynamic_defuse_lazy);
451e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, dynamic_usedef);
452e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, dynamic_usedefnoload);
453067c5136Sriastradh 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_ctor);
454f4e534ddSriastradh 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_eager);
455f4e534ddSriastradh 	ATF_TP_ADD_TC(tp, onlydef_dynamic_static_lazy);
456f4e534ddSriastradh 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_eager);
457f4e534ddSriastradh 	ATF_TP_ADD_TC(tp, onlydef_static_dynamic_lazy);
4589a31d868Sriastradh 	ATF_TP_ADD_TC(tp, opencloseloop_use);
459e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, static_abusedef);
460e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, static_abusedefnoload);
46198256cacSriastradh 	ATF_TP_ADD_TC(tp, static_defabuse_eager);
46298256cacSriastradh 	ATF_TP_ADD_TC(tp, static_defabuse_lazy);
46398256cacSriastradh 	ATF_TP_ADD_TC(tp, static_defuse_eager);
46498256cacSriastradh 	ATF_TP_ADD_TC(tp, static_defuse_lazy);
465e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, static_usedef);
466e04ffa37Sriastradh 	ATF_TP_ADD_TC(tp, static_usedefnoload);
46712037d6aSriastradh 	return atf_no_error();
46812037d6aSriastradh }
469