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 | static int |
10 | do_test (void) |
11 | { |
12 | void *handle = dlopen (file: "modstatic2-nonexistent.so" , RTLD_LAZY); |
13 | if (handle == NULL) |
14 | printf (format: "nonexistent: %s\n" , dlerror ()); |
15 | else |
16 | exit (1); |
17 | |
18 | handle = dlopen (file: "modstatic2.so" , RTLD_LAZY); |
19 | if (handle == NULL) |
20 | { |
21 | printf (format: "%s\n" , dlerror ()); |
22 | exit (1); |
23 | } |
24 | |
25 | int (*test) (FILE *, int); |
26 | test = dlsym (handle: handle, name: "test" ); |
27 | if (test == NULL) |
28 | { |
29 | printf (format: "%s\n" , dlerror ()); |
30 | exit (1); |
31 | } |
32 | |
33 | Dl_info info; |
34 | int res = dladdr (address: test, info: &info); |
35 | if (res == 0) |
36 | { |
37 | puts (s: "dladdr returned 0" ); |
38 | exit (1); |
39 | } |
40 | else |
41 | { |
42 | if (strstr (info.dli_fname, "modstatic2.so" ) == NULL |
43 | || strcmp (info.dli_sname, "test" ) != 0) |
44 | { |
45 | printf (format: "fname %s sname %s\n" , info.dli_fname, info.dli_sname); |
46 | exit (1); |
47 | } |
48 | if (info.dli_saddr != (void *) test) |
49 | { |
50 | printf (format: "saddr %p != test %p\n" , info.dli_saddr, test); |
51 | exit (1); |
52 | } |
53 | } |
54 | |
55 | ElfW(Sym) *sym; |
56 | void *symp; |
57 | res = dladdr1 (address: test, info: &info, extra_info: &symp, flags: RTLD_DL_SYMENT); |
58 | if (res == 0) |
59 | { |
60 | puts (s: "dladdr1 returned 0" ); |
61 | exit (1); |
62 | } |
63 | else |
64 | { |
65 | if (strstr (info.dli_fname, "modstatic2.so" ) == NULL |
66 | || strcmp (info.dli_sname, "test" ) != 0) |
67 | { |
68 | printf (format: "fname %s sname %s\n" , info.dli_fname, info.dli_sname); |
69 | exit (1); |
70 | } |
71 | if (info.dli_saddr != (void *) test) |
72 | { |
73 | printf (format: "saddr %p != test %p\n" , info.dli_saddr, test); |
74 | exit (1); |
75 | } |
76 | sym = symp; |
77 | if (sym == NULL) |
78 | { |
79 | puts (s: "sym == NULL\n" ); |
80 | exit (1); |
81 | } |
82 | if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL |
83 | || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) |
84 | { |
85 | printf (format: "bind %d visibility %d\n" , |
86 | (int) ELF32_ST_BIND (sym->st_info), |
87 | (int) ELF32_ST_VISIBILITY (sym->st_other)); |
88 | exit (1); |
89 | } |
90 | } |
91 | |
92 | Lmid_t lmid; |
93 | res = dlinfo (handle: handle, request: RTLD_DI_LMID, arg: &lmid); |
94 | if (res != 0) |
95 | { |
96 | printf (format: "dlinfo returned %d %s\n" , res, dlerror ()); |
97 | exit (1); |
98 | } |
99 | else if (lmid != LM_ID_BASE) |
100 | { |
101 | printf (format: "lmid %d != %d\n" , (int) lmid, (int) LM_ID_BASE); |
102 | exit (1); |
103 | } |
104 | |
105 | res = test (stdout, 2); |
106 | if (res != 4) |
107 | { |
108 | printf (format: "Got %i, expected 4\n" , res); |
109 | exit (1); |
110 | } |
111 | |
112 | void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY); |
113 | if (handle2 == NULL) |
114 | { |
115 | printf (format: "libdl.so: %s\n" , dlerror ()); |
116 | exit (1); |
117 | } |
118 | |
119 | /* _exit is very unlikely to receive a second symbol version. */ |
120 | void *exit_ptr = dlvsym (handle: handle2, name: "_exit" , FIRST_VERSION_libc__exit_STRING); |
121 | if (exit_ptr == NULL) |
122 | { |
123 | printf (format: "dlvsym: %s\n" , dlerror ()); |
124 | exit (1); |
125 | } |
126 | if (exit_ptr != dlsym (handle: handle2, name: "_exit" )) |
127 | { |
128 | printf (format: "dlvsym for _exit does not match dlsym\n" ); |
129 | exit (1); |
130 | } |
131 | |
132 | void *(*dlsymfn) (void *, const char *); |
133 | dlsymfn = dlsym (handle: handle2, name: "dlsym" ); |
134 | if (dlsymfn == NULL) |
135 | { |
136 | printf (format: "dlsym \"dlsym\": %s\n" , dlerror ()); |
137 | exit (1); |
138 | } |
139 | void *test2 = dlsymfn (handle, "test" ); |
140 | if (test2 == NULL) |
141 | { |
142 | printf (format: "%s\n" , dlerror ()); |
143 | exit (1); |
144 | } |
145 | else if (test2 != (void *) test) |
146 | { |
147 | printf (format: "test %p != test2 %p\n" , test, test2); |
148 | exit (1); |
149 | } |
150 | |
151 | dlclose (handle: handle2); |
152 | dlclose (handle: handle); |
153 | |
154 | handle = dlmopen (LM_ID_BASE, file: "modstatic2.so" , RTLD_LAZY); |
155 | if (handle == NULL) |
156 | { |
157 | printf (format: "%s\n" , dlerror ()); |
158 | exit (1); |
159 | } |
160 | dlclose (handle: handle); |
161 | |
162 | handle = dlmopen (LM_ID_NEWLM, file: "modstatic2.so" , RTLD_LAZY); |
163 | if (handle == NULL) |
164 | printf (format: "LM_ID_NEWLM: %s\n" , dlerror ()); |
165 | else |
166 | { |
167 | puts (s: "LM_ID_NEWLM unexpectedly succeeded" ); |
168 | exit (1); |
169 | } |
170 | |
171 | return 0; |
172 | } |
173 | |
174 | #define TEST_FUNCTION do_test () |
175 | #include "../test-skeleton.c" |
176 | |