1 | /* Global-scope DSO mapping test 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 | |
27 | /* Mapping a DSO into the global scope used to crash in static |
28 | executables. Check that it succeeds and then that symbols from |
29 | the DSO can be accessed and operate as expected. */ |
30 | static int |
31 | do_test (void) |
32 | { |
33 | unsigned int (*getfoo) (void); |
34 | void (*setfoo) (unsigned int); |
35 | unsigned int *foop; |
36 | unsigned int foo; |
37 | void *handle; |
38 | |
39 | /* Try to map a module into the global scope. */ |
40 | handle = dlopen (file: "modstatic3.so" , RTLD_LAZY | RTLD_GLOBAL); |
41 | if (handle == NULL) |
42 | { |
43 | printf (format: "dlopen (modstatic3.so): %s\n" , dlerror ()); |
44 | return 1; |
45 | } |
46 | |
47 | /* Get at its symbols. */ |
48 | foop = dlsym (handle: handle, name: "foo" ); |
49 | if (foop == NULL) |
50 | { |
51 | printf (format: "dlsym (foo): %s\n" , dlerror ()); |
52 | return 1; |
53 | } |
54 | |
55 | getfoo = dlsym (handle: handle, name: "getfoo" ); |
56 | if (getfoo == NULL) |
57 | { |
58 | printf (format: "dlsym (getfoo): %s\n" , dlerror ()); |
59 | return 1; |
60 | } |
61 | |
62 | setfoo = dlsym (handle: handle, name: "setfoo" ); |
63 | if (setfoo == NULL) |
64 | { |
65 | printf (format: "dlsym (setfoo): %s\n" , dlerror ()); |
66 | return 1; |
67 | } |
68 | |
69 | /* Make sure the view of the initial state is consistent. */ |
70 | foo = *foop; |
71 | if (foo != MAGIC0) |
72 | { |
73 | printf (format: "*foop: got %#x, expected %#x\n" , foo, MAGIC0); |
74 | return 1; |
75 | } |
76 | |
77 | foo = getfoo (); |
78 | if (foo != MAGIC0) |
79 | { |
80 | printf (format: "getfoo: got %#x, expected %#x\n" , foo, MAGIC0); |
81 | return 1; |
82 | } |
83 | |
84 | /* Likewise with one change to its state. */ |
85 | setfoo (MAGIC1); |
86 | |
87 | foo = *foop; |
88 | if (foo != MAGIC1) |
89 | { |
90 | printf (format: "*foop: got %#x, expected %#x\n" , foo, MAGIC1); |
91 | return 1; |
92 | } |
93 | |
94 | foo = getfoo (); |
95 | if (foo != MAGIC1) |
96 | { |
97 | printf (format: "getfoo: got %#x, expected %#x\n" , foo, MAGIC1); |
98 | return 1; |
99 | } |
100 | |
101 | /* And with another. */ |
102 | setfoo (MAGIC2); |
103 | |
104 | foo = *foop; |
105 | if (foo != MAGIC2) |
106 | { |
107 | printf (format: "*foop: got %#x, expected %#x\n" , foo, MAGIC2); |
108 | return 1; |
109 | } |
110 | |
111 | foo = getfoo (); |
112 | if (foo != MAGIC2) |
113 | { |
114 | printf (format: "getfoo: got %#x, expected %#x\n" , foo, MAGIC2); |
115 | return 1; |
116 | } |
117 | |
118 | /* All done, clean up. */ |
119 | getfoo = NULL; |
120 | setfoo = NULL; |
121 | foop = NULL; |
122 | dlclose (handle: handle); |
123 | |
124 | return 0; |
125 | } |
126 | |
127 | #define TEST_FUNCTION do_test () |
128 | #include "../test-skeleton.c" |
129 | |