1/*	$NetBSD$	*/
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by NONAKA Kimihiro.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33
34#include <atf-c.h>
35#include <stdlib.h>
36#include <dlfcn.h>
37
38ATF_TC(rtld_dlvsym_v1);
39ATF_TC_HEAD(rtld_dlvsym_v1, tc)
40{
41	atf_tc_set_md_var(tc, "descr", "Check dlvsym() function (V_1)");
42}
43ATF_TC_BODY(rtld_dlvsym_v1, tc)
44{
45	void *handle;
46	char *error;
47	int (*sym)(void);
48	int result;
49
50	/* Clear previous error */
51	(void) dlerror();
52
53	handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
54	error = dlerror();
55	ATF_CHECK(error == NULL);
56	ATF_CHECK(handle != NULL);
57
58	sym = dlvsym(handle, "testfunc", "V_1");
59	error = dlerror();
60	ATF_CHECK(error == NULL);
61
62	result = (*sym)();
63	ATF_CHECK(result == 1);
64
65	dlclose(handle);
66	error = dlerror();
67	ATF_CHECK(error == NULL);
68}
69
70ATF_TC(rtld_dlvsym_v3);
71ATF_TC_HEAD(rtld_dlvsym_v3, tc)
72{
73	atf_tc_set_md_var(tc, "descr", "Check dlvsym() function (V_3)");
74}
75ATF_TC_BODY(rtld_dlvsym_v3, tc)
76{
77	void *handle;
78	char *error;
79	int (*sym)(void);
80	int result;
81
82	/* Clear previous error */
83	(void) dlerror();
84
85	handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
86	error = dlerror();
87	ATF_CHECK(error == NULL);
88	ATF_CHECK(handle != NULL);
89
90	sym = dlvsym(handle, "testfunc", "V_3");
91	error = dlerror();
92	ATF_CHECK(error == NULL);
93
94	result = (*sym)();
95	ATF_CHECK(result == 3);
96
97	dlclose(handle);
98	error = dlerror();
99	ATF_CHECK(error == NULL);
100}
101
102ATF_TC(rtld_dlvsym_symbol_nonexistent);
103ATF_TC_HEAD(rtld_dlvsym_symbol_nonexistent, tc)
104{
105	atf_tc_set_md_var(tc, "descr",
106	    "Check dlvsym() function (symbol is nonexistent)");
107}
108ATF_TC_BODY(rtld_dlvsym_symbol_nonexistent, tc)
109{
110	void *handle;
111	char *error;
112	int (*sym)(void);
113
114	/* Clear previous error */
115	(void) dlerror();
116
117	handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
118	error = dlerror();
119	ATF_CHECK(error == NULL);
120	ATF_CHECK(handle != NULL);
121
122	sym = dlvsym(handle, "symbol_nonexistent", "V_3");
123	error = dlerror();
124	ATF_CHECK(sym == NULL);
125	ATF_CHECK(error != NULL);
126
127	dlclose(handle);
128	error = dlerror();
129	ATF_CHECK(error == NULL);
130}
131
132ATF_TC(rtld_dlvsym_version_nonexistent);
133ATF_TC_HEAD(rtld_dlvsym_version_nonexistent, tc)
134{
135	atf_tc_set_md_var(tc, "descr",
136	    "Check dlvsym() function (version is nonexistent)");
137}
138ATF_TC_BODY(rtld_dlvsym_version_nonexistent, tc)
139{
140	void *handle;
141	char *error;
142	int (*sym)(void);
143
144	/* Clear previous error */
145	(void) dlerror();
146
147	handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
148	error = dlerror();
149	ATF_CHECK(error == NULL);
150	ATF_CHECK(handle != NULL);
151
152	sym = dlvsym(handle, "testfunc", "");
153	error = dlerror();
154	ATF_CHECK(sym == NULL);
155	ATF_CHECK(error != NULL);
156
157	dlclose(handle);
158	error = dlerror();
159	ATF_CHECK(error == NULL);
160}
161
162ATF_TC(rtld_dlvsym_version_null);
163ATF_TC_HEAD(rtld_dlvsym_version_null, tc)
164{
165	atf_tc_set_md_var(tc, "descr",
166	    "Check dlvsym() function (version is NULL)");
167}
168ATF_TC_BODY(rtld_dlvsym_version_null, tc)
169{
170	void *handle;
171	char *error;
172	int (*sym)(void);
173	int result;
174
175	/* Clear previous error */
176	(void) dlerror();
177
178	handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
179	error = dlerror();
180	ATF_CHECK(error == NULL);
181	ATF_CHECK(handle != NULL);
182
183	sym = dlvsym(handle, "testfunc", NULL);
184	error = dlerror();
185	ATF_CHECK(error == NULL);
186
187	result = (*sym)();
188	ATF_CHECK(result == 3);
189
190	dlclose(handle);
191	error = dlerror();
192	ATF_CHECK(error == NULL);
193}
194
195ATF_TP_ADD_TCS(tp)
196{
197	ATF_TP_ADD_TC(tp, rtld_dlvsym_v1);
198	ATF_TP_ADD_TC(tp, rtld_dlvsym_v3);
199	ATF_TP_ADD_TC(tp, rtld_dlvsym_symbol_nonexistent);
200	ATF_TP_ADD_TC(tp, rtld_dlvsym_version_nonexistent);
201	ATF_TP_ADD_TC(tp, rtld_dlvsym_version_null);
202	return atf_no_error();
203}
204