1 | /* Global object symbol access tests with a static executable (BZ #15022). |
2 | Copyright (C) 2013-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
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. |
9 | |
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. |
14 | |
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 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <dlfcn.h> |
20 | #include <stddef.h> |
21 | #include <stdio.h> |
22 | |
23 | #define MAGIC0 0 |
24 | #define MAGIC1 0x5500ffaa |
25 | #define MAGIC2 0xaaff0055 |
26 | #define MAGIC3 0xff55aa00 |
27 | |
28 | /* Check the ability to access the global symbol object and then |
29 | global-scope symbol access consistency via different mappings |
30 | requested from a static executable. */ |
31 | static int |
32 | do_test (void) |
33 | { |
34 | unsigned int (*initial_getfoo) (void); |
35 | void (*initial_setfoo) (unsigned int); |
36 | unsigned int (*global_getfoo) (void); |
37 | void (*global_setfoo) (unsigned int); |
38 | unsigned int (*local_getfoo) (void); |
39 | void (*local_setfoo) (unsigned int); |
40 | unsigned int *initial_foop; |
41 | unsigned int *global_foop; |
42 | unsigned int *local_foop; |
43 | void *initial_handle; |
44 | void *global_handle; |
45 | void *local_handle; |
46 | unsigned int foo; |
47 | |
48 | /* Try to map self. */ |
49 | initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL); |
50 | if (initial_handle == NULL) |
51 | { |
52 | printf (format: "dlopen [initial] (NULL): %s\n" , dlerror ()); |
53 | return 1; |
54 | } |
55 | |
56 | /* Make sure symbol lookups fail gracefully. */ |
57 | initial_foop = dlsym (handle: initial_handle, name: "foo" ); |
58 | if (initial_foop != NULL) |
59 | { |
60 | printf (format: "dlsym [initial] (foo): got %p, expected NULL\n" , initial_foop); |
61 | return 1; |
62 | } |
63 | |
64 | initial_getfoo = dlsym (handle: initial_handle, name: "getfoo" ); |
65 | if (initial_getfoo != NULL) |
66 | { |
67 | printf (format: "dlsym [initial] (getfoo): got %p, expected NULL\n" , |
68 | initial_getfoo); |
69 | return 1; |
70 | } |
71 | |
72 | initial_setfoo = dlsym (handle: initial_handle, name: "setfoo" ); |
73 | if (initial_setfoo != NULL) |
74 | { |
75 | printf (format: "dlsym [initial] (setfoo): got %p, expected NULL\n" , |
76 | initial_setfoo); |
77 | return 1; |
78 | } |
79 | |
80 | /* Try to map a module into the global scope. */ |
81 | global_handle = dlopen (file: "modstatic3.so" , RTLD_LAZY | RTLD_GLOBAL); |
82 | if (global_handle == NULL) |
83 | { |
84 | printf (format: "dlopen [global] (modstatic3.so): %s\n" , dlerror ()); |
85 | return 1; |
86 | } |
87 | |
88 | /* Get at its symbols. */ |
89 | global_foop = dlsym (handle: global_handle, name: "foo" ); |
90 | if (global_foop == NULL) |
91 | { |
92 | printf (format: "dlsym [global] (foo): %s\n" , dlerror ()); |
93 | return 1; |
94 | } |
95 | |
96 | global_getfoo = dlsym (handle: global_handle, name: "getfoo" ); |
97 | if (global_getfoo == NULL) |
98 | { |
99 | printf (format: "dlsym [global] (getfoo): %s\n" , dlerror ()); |
100 | return 1; |
101 | } |
102 | |
103 | global_setfoo = dlsym (handle: global_handle, name: "setfoo" ); |
104 | if (global_setfoo == NULL) |
105 | { |
106 | printf (format: "dlsym [global] (setfoo): %s\n" , dlerror ()); |
107 | return 1; |
108 | } |
109 | |
110 | /* Try to map self again now. */ |
111 | local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL); |
112 | if (local_handle == NULL) |
113 | { |
114 | printf (format: "dlopen [local] (NULL): %s\n" , dlerror ()); |
115 | return 1; |
116 | } |
117 | |
118 | /* Make sure we can get at the previously loaded module's symbols |
119 | via this handle too. */ |
120 | local_foop = dlsym (handle: local_handle, name: "foo" ); |
121 | if (local_foop == NULL) |
122 | { |
123 | printf (format: "dlsym [local] (foo): %s\n" , dlerror ()); |
124 | return 1; |
125 | } |
126 | |
127 | local_getfoo = dlsym (handle: local_handle, name: "getfoo" ); |
128 | if (local_getfoo == NULL) |
129 | { |
130 | printf (format: "dlsym [local] (getfoo): %s\n" , dlerror ()); |
131 | return 1; |
132 | } |
133 | |
134 | local_setfoo = dlsym (handle: local_handle, name: "setfoo" ); |
135 | if (local_setfoo == NULL) |
136 | { |
137 | printf (format: "dlsym [local] (setfoo): %s\n" , dlerror ()); |
138 | return 1; |
139 | } |
140 | |
141 | /* Make sure we can get at the previously loaded module's symbols |
142 | via a handle that was obtained before the module was loaded too. */ |
143 | initial_foop = dlsym (handle: initial_handle, name: "foo" ); |
144 | if (initial_foop == NULL) |
145 | { |
146 | printf (format: "dlsym [initial] (foo): %s\n" , dlerror ()); |
147 | return 1; |
148 | } |
149 | |
150 | initial_getfoo = dlsym (handle: initial_handle, name: "getfoo" ); |
151 | if (initial_getfoo == NULL) |
152 | { |
153 | printf (format: "dlsym [initial] (getfoo): %s\n" , dlerror ()); |
154 | return 1; |
155 | } |
156 | |
157 | initial_setfoo = dlsym (handle: initial_handle, name: "setfoo" ); |
158 | if (initial_setfoo == NULL) |
159 | { |
160 | printf (format: "dlsym [initial] (setfoo): %s\n" , dlerror ()); |
161 | return 1; |
162 | } |
163 | |
164 | /* Make sure the view of the initial state is consistent. */ |
165 | foo = *initial_foop; |
166 | if (foo != MAGIC0) |
167 | { |
168 | printf (format: "*foop [initial]: got %#x, expected %#x\n" , foo, MAGIC0); |
169 | return 1; |
170 | } |
171 | |
172 | foo = *global_foop; |
173 | if (foo != MAGIC0) |
174 | { |
175 | printf (format: "*foop [global]: got %#x, expected %#x\n" , foo, MAGIC0); |
176 | return 1; |
177 | } |
178 | |
179 | foo = *local_foop; |
180 | if (foo != MAGIC0) |
181 | { |
182 | printf (format: "*foop [local]: got %#x, expected %#x\n" , foo, MAGIC0); |
183 | return 1; |
184 | } |
185 | |
186 | foo = initial_getfoo (); |
187 | if (foo != MAGIC0) |
188 | { |
189 | printf (format: "getfoo [initial]: got %#x, expected %#x\n" , foo, MAGIC0); |
190 | return 1; |
191 | } |
192 | |
193 | foo = global_getfoo (); |
194 | if (foo != MAGIC0) |
195 | { |
196 | printf (format: "getfoo [global]: got %#x, expected %#x\n" , foo, MAGIC0); |
197 | return 1; |
198 | } |
199 | |
200 | foo = local_getfoo (); |
201 | if (foo != MAGIC0) |
202 | { |
203 | printf (format: "getfoo [local]: got %#x, expected %#x\n" , foo, MAGIC0); |
204 | return 1; |
205 | } |
206 | |
207 | /* Likewise with a change to its state made through the first handle. */ |
208 | initial_setfoo (MAGIC1); |
209 | |
210 | foo = *initial_foop; |
211 | if (foo != MAGIC1) |
212 | { |
213 | printf (format: "*foop [initial]: got %#x, expected %#x\n" , foo, MAGIC1); |
214 | return 1; |
215 | } |
216 | |
217 | foo = *global_foop; |
218 | if (foo != MAGIC1) |
219 | { |
220 | printf (format: "*foop [global]: got %#x, expected %#x\n" , foo, MAGIC1); |
221 | return 1; |
222 | } |
223 | |
224 | foo = *local_foop; |
225 | if (foo != MAGIC1) |
226 | { |
227 | printf (format: "*foop [local]: got %#x, expected %#x\n" , foo, MAGIC1); |
228 | return 1; |
229 | } |
230 | |
231 | foo = initial_getfoo (); |
232 | if (foo != MAGIC1) |
233 | { |
234 | printf (format: "getfoo [initial]: got %#x, expected %#x\n" , foo, MAGIC1); |
235 | return 1; |
236 | } |
237 | |
238 | foo = global_getfoo (); |
239 | if (foo != MAGIC1) |
240 | { |
241 | printf (format: "getfoo [global]: got %#x, expected %#x\n" , foo, MAGIC1); |
242 | return 1; |
243 | } |
244 | |
245 | foo = local_getfoo (); |
246 | if (foo != MAGIC1) |
247 | { |
248 | printf (format: "getfoo [local]: got %#x, expected %#x\n" , foo, MAGIC1); |
249 | return 1; |
250 | } |
251 | |
252 | /* Likewise with a change to its state made through the second handle. */ |
253 | global_setfoo (MAGIC2); |
254 | |
255 | foo = *initial_foop; |
256 | if (foo != MAGIC2) |
257 | { |
258 | printf (format: "*foop [initial]: got %#x, expected %#x\n" , foo, MAGIC2); |
259 | return 1; |
260 | } |
261 | |
262 | foo = *global_foop; |
263 | if (foo != MAGIC2) |
264 | { |
265 | printf (format: "*foop [global]: got %#x, expected %#x\n" , foo, MAGIC2); |
266 | return 1; |
267 | } |
268 | |
269 | foo = *local_foop; |
270 | if (foo != MAGIC2) |
271 | { |
272 | printf (format: "*foop [local]: got %#x, expected %#x\n" , foo, MAGIC2); |
273 | return 1; |
274 | } |
275 | |
276 | foo = initial_getfoo (); |
277 | if (foo != MAGIC2) |
278 | { |
279 | printf (format: "getfoo [initial]: got %#x, expected %#x\n" , foo, MAGIC2); |
280 | return 1; |
281 | } |
282 | |
283 | foo = global_getfoo (); |
284 | if (foo != MAGIC2) |
285 | { |
286 | printf (format: "getfoo [global]: got %#x, expected %#x\n" , foo, MAGIC2); |
287 | return 1; |
288 | } |
289 | |
290 | foo = local_getfoo (); |
291 | if (foo != MAGIC2) |
292 | { |
293 | printf (format: "getfoo [local]: got %#x, expected %#x\n" , foo, MAGIC2); |
294 | return 1; |
295 | } |
296 | |
297 | /* Likewise with a change to its state made through the third handle. */ |
298 | local_setfoo (MAGIC3); |
299 | |
300 | foo = *initial_foop; |
301 | if (foo != MAGIC3) |
302 | { |
303 | printf (format: "*foop [initial]: got %#x, expected %#x\n" , foo, MAGIC3); |
304 | return 1; |
305 | } |
306 | |
307 | foo = *global_foop; |
308 | if (foo != MAGIC3) |
309 | { |
310 | printf (format: "*foop [global]: got %#x, expected %#x\n" , foo, MAGIC3); |
311 | return 1; |
312 | } |
313 | |
314 | foo = *local_foop; |
315 | if (foo != MAGIC3) |
316 | { |
317 | printf (format: "*foop [local]: got %#x, expected %#x\n" , foo, MAGIC3); |
318 | return 1; |
319 | } |
320 | |
321 | foo = initial_getfoo (); |
322 | if (foo != MAGIC3) |
323 | { |
324 | printf (format: "getfoo [initial]: got %#x, expected %#x\n" , foo, MAGIC3); |
325 | return 1; |
326 | } |
327 | |
328 | foo = global_getfoo (); |
329 | if (foo != MAGIC3) |
330 | { |
331 | printf (format: "getfoo [global]: got %#x, expected %#x\n" , foo, MAGIC3); |
332 | return 1; |
333 | } |
334 | |
335 | foo = local_getfoo (); |
336 | if (foo != MAGIC3) |
337 | { |
338 | printf (format: "getfoo [local]: got %#x, expected %#x\n" , foo, MAGIC3); |
339 | return 1; |
340 | } |
341 | |
342 | /* All done, clean up. */ |
343 | initial_getfoo = NULL; |
344 | initial_setfoo = NULL; |
345 | initial_foop = NULL; |
346 | |
347 | local_getfoo = NULL; |
348 | local_setfoo = NULL; |
349 | local_foop = NULL; |
350 | dlclose (handle: local_handle); |
351 | |
352 | global_getfoo = NULL; |
353 | global_setfoo = NULL; |
354 | global_foop = NULL; |
355 | dlclose (handle: global_handle); |
356 | |
357 | dlclose (handle: initial_handle); |
358 | |
359 | return 0; |
360 | } |
361 | |
362 | #define TEST_FUNCTION do_test () |
363 | #include "../test-skeleton.c" |
364 | |