1 | #include <dlfcn.h> |
2 | #include <link.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <string.h> |
6 | #include <gnu/lib-names.h> |
7 | #include <first-versions.h> |
8 | |
9 | int test (FILE *out, int a); |
10 | |
11 | int |
12 | test (FILE *out, int a) |
13 | { |
14 | fputs ("in modstatic2.c (test)\n" , out); |
15 | |
16 | void *handle = dlopen (file: "modstatic2-nonexistent.so" , RTLD_LAZY); |
17 | if (handle == NULL) |
18 | fprintf (out, "nonexistent: %s\n" , dlerror ()); |
19 | else |
20 | exit (1); |
21 | |
22 | handle = dlopen (file: "modstatic2.so" , RTLD_LAZY); |
23 | if (handle == NULL) |
24 | { |
25 | fprintf (out, "%s\n" , dlerror ()); |
26 | exit (1); |
27 | } |
28 | |
29 | int (*test2) (FILE *, int); |
30 | test2 = dlsym (handle: handle, name: "test" ); |
31 | if (test2 == NULL) |
32 | { |
33 | fprintf (out, "%s\n" , dlerror ()); |
34 | exit (1); |
35 | } |
36 | if (test2 != test) |
37 | { |
38 | fprintf (out, "test %p != test2 %p\n" , test, test2); |
39 | exit (1); |
40 | } |
41 | |
42 | Dl_info info; |
43 | int res = dladdr (address: test2, info: &info); |
44 | if (res == 0) |
45 | { |
46 | fputs ("dladdr returned 0\n" , out); |
47 | exit (1); |
48 | } |
49 | else |
50 | { |
51 | if (strstr (info.dli_fname, "modstatic2.so" ) == NULL |
52 | || strcmp (info.dli_sname, "test" ) != 0) |
53 | { |
54 | fprintf (out, "fname %s sname %s\n" , info.dli_fname, info.dli_sname); |
55 | exit (1); |
56 | } |
57 | if (info.dli_saddr != (void *) test2) |
58 | { |
59 | fprintf (out, "saddr %p != test %p\n" , info.dli_saddr, test2); |
60 | exit (1); |
61 | } |
62 | } |
63 | |
64 | ElfW(Sym) *sym; |
65 | void *symp; |
66 | res = dladdr1 (address: test2, info: &info, extra_info: &symp, flags: RTLD_DL_SYMENT); |
67 | if (res == 0) |
68 | { |
69 | fputs ("dladdr1 returned 0\n" , out); |
70 | exit (1); |
71 | } |
72 | else |
73 | { |
74 | if (strstr (info.dli_fname, "modstatic2.so" ) == NULL |
75 | || strcmp (info.dli_sname, "test" ) != 0) |
76 | { |
77 | fprintf (out, "fname %s sname %s\n" , info.dli_fname, info.dli_sname); |
78 | exit (1); |
79 | } |
80 | if (info.dli_saddr != (void *) test2) |
81 | { |
82 | fprintf (out, "saddr %p != test %p\n" , info.dli_saddr, test2); |
83 | exit (1); |
84 | } |
85 | sym = symp; |
86 | if (sym == NULL) |
87 | { |
88 | fputs ("sym == NULL\n" , out); |
89 | exit (1); |
90 | } |
91 | if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL |
92 | || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) |
93 | { |
94 | fprintf (out, "bind %d visibility %d\n" , |
95 | (int) ELF32_ST_BIND (sym->st_info), |
96 | (int) ELF32_ST_VISIBILITY (sym->st_other)); |
97 | exit (1); |
98 | } |
99 | } |
100 | |
101 | Lmid_t lmid; |
102 | res = dlinfo (handle: handle, request: RTLD_DI_LMID, arg: &lmid); |
103 | if (res != 0) |
104 | { |
105 | fprintf (out, "dlinfo returned %d %s\n" , res, dlerror ()); |
106 | exit (1); |
107 | } |
108 | else if (lmid != LM_ID_BASE) |
109 | { |
110 | fprintf (out, "lmid %d != %d\n" , (int) lmid, (int) LM_ID_BASE); |
111 | exit (1); |
112 | } |
113 | |
114 | void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY); |
115 | if (handle2 == NULL) |
116 | { |
117 | fprintf (out, "libdl.so: %s\n" , dlerror ()); |
118 | exit (1); |
119 | } |
120 | |
121 | /* _exit is very unlikely to receive a second symbol version. */ |
122 | void *exit_ptr = dlvsym (handle: handle2, name: "_exit" , FIRST_VERSION_libc__exit_STRING); |
123 | if (exit_ptr == NULL) |
124 | { |
125 | fprintf (out, "dlvsym: %s\n" , dlerror ()); |
126 | exit (1); |
127 | } |
128 | if (exit_ptr != dlsym (handle: handle2, name: "_exit" )) |
129 | { |
130 | fprintf (out, "dlvsym for _exit does not match dlsym\n" ); |
131 | exit (1); |
132 | } |
133 | |
134 | void *(*dlsymfn) (void *, const char *); |
135 | dlsymfn = dlsym (handle: handle2, name: "dlsym" ); |
136 | if (dlsymfn == NULL) |
137 | { |
138 | fprintf (out, "dlsym \"dlsym\": %s\n" , dlerror ()); |
139 | exit (1); |
140 | } |
141 | void *test3 = dlsymfn (handle, "test" ); |
142 | if (test3 == NULL) |
143 | { |
144 | fprintf (out, "%s\n" , dlerror ()); |
145 | exit (1); |
146 | } |
147 | else if (test3 != (void *) test2) |
148 | { |
149 | fprintf (out, "test2 %p != test3 %p\n" , test2, test3); |
150 | exit (1); |
151 | } |
152 | |
153 | dlclose (handle: handle2); |
154 | dlclose (handle: handle); |
155 | |
156 | handle = dlmopen (LM_ID_BASE, file: "modstatic2.so" , RTLD_LAZY); |
157 | if (handle == NULL) |
158 | { |
159 | fprintf (out, "%s\n" , dlerror ()); |
160 | exit (1); |
161 | } |
162 | dlclose (handle: handle); |
163 | |
164 | handle = dlmopen (LM_ID_NEWLM, file: "modstatic2.so" , RTLD_LAZY); |
165 | if (handle == NULL) |
166 | fprintf (out, "LM_ID_NEWLM: %s\n" , dlerror ()); |
167 | else |
168 | { |
169 | fputs ("LM_ID_NEWLM unexpectedly succeeded\n" , out); |
170 | exit (1); |
171 | } |
172 | |
173 | handle = dlopen (file: "modstatic.so" , RTLD_LAZY); |
174 | if (handle == NULL) |
175 | { |
176 | fprintf (out, "%s\n" , dlerror ()); |
177 | exit (1); |
178 | } |
179 | |
180 | int (*test4) (int); |
181 | test4 = dlsym (handle: handle, name: "test" ); |
182 | if (test4 == NULL) |
183 | { |
184 | fprintf (out, "%s\n" , dlerror ()); |
185 | exit (1); |
186 | } |
187 | |
188 | res = test4 (16); |
189 | if (res != 16 + 16) |
190 | { |
191 | fprintf (out, "modstatic.so (test) returned %d\n" , res); |
192 | exit (1); |
193 | } |
194 | |
195 | res = dladdr1 (address: test4, info: &info, extra_info: &symp, flags: RTLD_DL_SYMENT); |
196 | if (res == 0) |
197 | { |
198 | fputs ("dladdr1 returned 0\n" , out); |
199 | exit (1); |
200 | } |
201 | else |
202 | { |
203 | if (strstr (info.dli_fname, "modstatic.so" ) == NULL |
204 | || strcmp (info.dli_sname, "test" ) != 0) |
205 | { |
206 | fprintf (out, "fname %s sname %s\n" , info.dli_fname, info.dli_sname); |
207 | exit (1); |
208 | } |
209 | if (info.dli_saddr != (void *) test4) |
210 | { |
211 | fprintf (out, "saddr %p != test %p\n" , info.dli_saddr, test4); |
212 | exit (1); |
213 | } |
214 | sym = symp; |
215 | if (sym == NULL) |
216 | { |
217 | fputs ("sym == NULL\n" , out); |
218 | exit (1); |
219 | } |
220 | if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL |
221 | || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) |
222 | { |
223 | fprintf (out, "bind %d visibility %d\n" , |
224 | (int) ELF32_ST_BIND (sym->st_info), |
225 | (int) ELF32_ST_VISIBILITY (sym->st_other)); |
226 | exit (1); |
227 | } |
228 | } |
229 | |
230 | dlclose (handle: handle); |
231 | |
232 | fputs ("leaving modstatic2.c (test)\n" , out); |
233 | return a + a; |
234 | } |
235 | |