xref: /freebsd/libexec/rtld-elf/tests/rtld_deepbind/rtld_deepbind.c (revision aa1a8ff2d6dbc51ef058f46f3db5a8bb77967145)
1 /*-
2  *
3  * Copyright (C) 2023 NetApp, Inc.
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  *
7  */
8 
9 #include <dlfcn.h>
10 
11 #include <atf-c.h>
12 
13 int get_value(void);
14 void set_value(int);
15 
16 #define	APP_VALUE	5
17 #define	LIB_VALUE	20
18 
19 ATF_TC_WITHOUT_HEAD(deepbind_simple);
20 ATF_TC_BODY(deepbind_simple, tc)
21 {
22 	void *hdl;
23 	void (*proxy_set_value)(int);
24 	int (*proxy_get_value)(void);
25 	int app_value, lib_value;
26 
27 	set_value(APP_VALUE);
28 
29 	/*
30 	 * libdeep has a dependency on libval2.so, which is a rebuild of
31 	 * libval.so that provides get_value() and set_value() for both us and
32 	 * the lib.  The lib's get_value() and set_value() should bind to the
33 	 * versions in libval2 instead of libval with RTLD_DEEPBIND.
34 	 */
35 	hdl = dlopen("$ORIGIN/libdeep.so", RTLD_LAZY | RTLD_DEEPBIND);
36 	ATF_REQUIRE(hdl != NULL);
37 
38 	proxy_set_value = dlsym(hdl, "proxy_set_value");
39 	ATF_REQUIRE(proxy_set_value != NULL);
40 
41 	proxy_get_value = dlsym(hdl, "proxy_get_value");
42 	ATF_REQUIRE(proxy_get_value != NULL);
43 
44 	(*proxy_set_value)(LIB_VALUE);
45 
46 	lib_value = (*proxy_get_value)();
47 	app_value = get_value();
48 
49 	/*
50 	 * In the initial implementation or if libdeep.so is *not* linked
51 	 * against its own libval2, then these both return the later set
52 	 * LIB_VALUE (20) as they bind to the symbol provided by libval and
53 	 * use its .bss val.
54 	 */
55 	ATF_REQUIRE_INTEQ(lib_value, LIB_VALUE);
56 	ATF_REQUIRE_INTEQ(app_value, APP_VALUE);
57 }
58 
59 ATF_TP_ADD_TCS(tp)
60 {
61 
62 	ATF_TP_ADD_TC(tp, deepbind_simple);
63 
64 	return atf_no_error();
65 }
66