]>
Commit | Line | Data |
---|---|---|
482eec0d UD |
1 | #include <assert.h> |
2 | #include <dlfcn.h> | |
3 | #include <errno.h> | |
4 | #include <error.h> | |
752a2a50 | 5 | #include <mcheck.h> |
482eec0d UD |
6 | #include <stdio.h> |
7 | #include <stdlib.h> | |
c4bb124a | 8 | #include <string.h> |
482eec0d UD |
9 | |
10 | ||
11 | /* How many load/unload operations do we do. */ | |
3d91edb2 | 12 | #define TEST_ROUNDS 1000 |
482eec0d UD |
13 | |
14 | ||
15 | static struct | |
16 | { | |
17 | /* Name of the module. */ | |
18 | const char *name; | |
19 | /* The handle. */ | |
20 | void *handle; | |
21 | } testobjs[] = | |
22 | { | |
23 | { "testobj1.so", NULL }, | |
24 | { "testobj2.so", NULL }, | |
25 | { "testobj3.so", NULL }, | |
3d91edb2 UD |
26 | { "testobj4.so", NULL }, |
27 | { "testobj5.so", NULL }, | |
28 | { "testobj6.so", NULL }, | |
482eec0d UD |
29 | }; |
30 | #define NOBJS (sizeof (testobjs) / sizeof (testobjs[0])) | |
31 | ||
32 | ||
33 | static const struct | |
34 | { | |
35 | /* Name of a function to call. */ | |
36 | const char *fname; | |
37 | /* Index in status and handle array. */ | |
38 | int index; | |
39 | /* Options while loading the module. */ | |
40 | int options; | |
41 | } tests[] = | |
42 | { | |
43 | { "obj1func2", 0, RTLD_LAZY }, | |
44 | { "obj1func1", 0, RTLD_LAZY | RTLD_GLOBAL }, | |
45 | { "obj1func1", 0, RTLD_NOW, }, | |
46 | { "obj1func2", 0, RTLD_NOW | RTLD_GLOBAL }, | |
47 | { "obj2func2", 1, RTLD_LAZY }, | |
48 | { "obj2func1", 1, RTLD_LAZY | RTLD_GLOBAL, }, | |
49 | { "obj2func1", 1, RTLD_NOW, }, | |
50 | { "obj2func2", 1, RTLD_NOW | RTLD_GLOBAL }, | |
51 | { "obj3func2", 2, RTLD_LAZY }, | |
52 | { "obj3func1", 2, RTLD_LAZY | RTLD_GLOBAL }, | |
53 | { "obj3func1", 2, RTLD_NOW }, | |
54 | { "obj3func2", 2, RTLD_NOW | RTLD_GLOBAL }, | |
3d91edb2 UD |
55 | { "obj4func2", 3, RTLD_LAZY }, |
56 | { "obj4func1", 3, RTLD_LAZY | RTLD_GLOBAL }, | |
57 | { "obj4func1", 3, RTLD_NOW }, | |
58 | { "obj4func2", 3, RTLD_NOW | RTLD_GLOBAL }, | |
59 | { "obj5func2", 4, RTLD_LAZY }, | |
60 | { "obj5func1", 4, RTLD_LAZY | RTLD_GLOBAL }, | |
61 | { "obj5func1", 4, RTLD_NOW }, | |
62 | { "obj5func2", 4, RTLD_NOW | RTLD_GLOBAL }, | |
63 | { "obj6func2", 5, RTLD_LAZY }, | |
64 | { "obj6func1", 5, RTLD_LAZY | RTLD_GLOBAL }, | |
65 | { "obj6func1", 5, RTLD_NOW }, | |
66 | { "obj6func2", 5, RTLD_NOW | RTLD_GLOBAL }, | |
482eec0d UD |
67 | }; |
68 | #define NTESTS (sizeof (tests) / sizeof (tests[0])) | |
69 | ||
70 | ||
752a2a50 UD |
71 | #include <include/link.h> |
72 | ||
d78efd9f RM |
73 | #define MAPS ((struct link_map *) _r_debug.r_map) |
74 | ||
ac782f9e JM |
75 | #define OUT \ |
76 | do \ | |
77 | { \ | |
78 | for (map = MAPS; map != NULL; map = map->l_next) \ | |
79 | if (map->l_type == lt_loaded) \ | |
80 | printf ("name = \"%s\", direct_opencount = %d\n", \ | |
81 | map->l_name, (int) map->l_direct_opencount); \ | |
82 | fflush (stdout); \ | |
83 | } \ | |
84 | while (0) | |
8699e7b1 | 85 | |
752a2a50 | 86 | |
482eec0d | 87 | int |
8699e7b1 | 88 | main (int argc, char *argv[]) |
482eec0d | 89 | { |
8699e7b1 | 90 | int debug = argc > 1 && argv[1][0] != '\0'; |
482eec0d | 91 | int count = TEST_ROUNDS; |
752a2a50 | 92 | int result = 0; |
42c4f32a | 93 | struct link_map *map; |
752a2a50 UD |
94 | |
95 | mtrace (); | |
482eec0d UD |
96 | |
97 | /* Just a seed. */ | |
98 | srandom (TEST_ROUNDS); | |
99 | ||
42c4f32a UD |
100 | if (debug) |
101 | { | |
102 | puts ("in the beginning"); | |
103 | OUT; | |
104 | } | |
105 | ||
482eec0d UD |
106 | while (count--) |
107 | { | |
108 | int nr = random () % NTESTS; | |
109 | int index = tests[nr].index; | |
110 | ||
111 | printf ("%4d: %4d: ", count + 1, nr); | |
112 | fflush (stdout); | |
113 | ||
114 | if (testobjs[index].handle == NULL) | |
115 | { | |
116 | int (*fct) (int); | |
117 | ||
118 | /* Load the object. */ | |
119 | testobjs[index].handle = dlopen (testobjs[index].name, | |
120 | tests[nr].options); | |
121 | if (testobjs[index].handle == NULL) | |
122 | error (EXIT_FAILURE, 0, "cannot load `%s': %s", | |
123 | testobjs[index].name, dlerror ()); | |
124 | ||
125 | /* Test the function call. */ | |
126 | fct = dlsym (testobjs[index].handle, tests[nr].fname); | |
127 | if (fct == NULL) | |
128 | error (EXIT_FAILURE, 0, | |
129 | "cannot get function `%s' from shared object `%s': %s", | |
130 | tests[nr].fname, testobjs[index].name, dlerror ()); | |
131 | ||
132 | fct (10); | |
133 | ||
752a2a50 UD |
134 | printf ("successfully loaded `%s', handle %p\n", |
135 | testobjs[index].name, testobjs[index].handle); | |
482eec0d UD |
136 | } |
137 | else | |
138 | { | |
752a2a50 UD |
139 | if (dlclose (testobjs[index].handle) != 0) |
140 | { | |
141 | printf ("failed to close %s\n", testobjs[index].name); | |
142 | result = 1; | |
143 | } | |
144 | else | |
145 | printf ("successfully unloaded `%s', handle %p\n", | |
146 | testobjs[index].name, testobjs[index].handle); | |
482eec0d | 147 | |
752a2a50 | 148 | testobjs[index].handle = NULL; |
c4bb124a UD |
149 | |
150 | if (testobjs[0].handle == NULL | |
151 | && testobjs[1].handle == NULL | |
152 | && testobjs[5].handle == NULL) | |
153 | { | |
154 | /* In this case none of the objects above should be | |
155 | present. */ | |
d78efd9f | 156 | for (map = MAPS; map != NULL; map = map->l_next) |
c4bb124a UD |
157 | if (map->l_type == lt_loaded |
158 | && (strstr (map->l_name, testobjs[0].name) != NULL | |
159 | || strstr (map->l_name, testobjs[1].name) != NULL | |
160 | || strstr (map->l_name, testobjs[5].name) != NULL)) | |
161 | { | |
162 | printf ("`%s' is still loaded\n", map->l_name); | |
163 | result = 1; | |
164 | } | |
165 | } | |
482eec0d | 166 | } |
8699e7b1 UD |
167 | |
168 | if (debug) | |
169 | OUT; | |
482eec0d UD |
170 | } |
171 | ||
172 | /* Unload all loaded modules. */ | |
a850e77f | 173 | for (count = 0; count < (int) NOBJS; ++count) |
482eec0d | 174 | if (testobjs[count].handle != NULL) |
e30f2b98 UD |
175 | { |
176 | printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n", | |
177 | testobjs[count].name, | |
c4bb124a UD |
178 | ((struct link_map *) testobjs[count].handle)->l_initfini, |
179 | ((struct link_map *) testobjs[count].handle)->l_versions); | |
e30f2b98 UD |
180 | |
181 | if (dlclose (testobjs[count].handle) != 0) | |
182 | { | |
183 | printf ("failed to close %s\n", testobjs[count].name); | |
184 | result = 1; | |
185 | } | |
186 | } | |
187 | ||
188 | /* Check whether all files are unloaded. */ | |
d78efd9f | 189 | for (map = MAPS; map != NULL; map = map->l_next) |
e30f2b98 UD |
190 | if (map->l_type == lt_loaded) |
191 | { | |
20fe49b9 UD |
192 | printf ("name = \"%s\", direct_opencount = %d\n", |
193 | map->l_name, (int) map->l_direct_opencount); | |
e30f2b98 UD |
194 | result = 1; |
195 | } | |
482eec0d | 196 | |
752a2a50 | 197 | return result; |
482eec0d UD |
198 | } |
199 | ||
200 | ||
a850e77f | 201 | extern int foo (int a); |
482eec0d UD |
202 | int |
203 | foo (int a) | |
204 | { | |
205 | return a - 1; | |
206 | } |