1 | #include <assert.h>
|
---|
2 | #include <dlfcn.h>
|
---|
3 | #include <errno.h>
|
---|
4 | #include <error.h>
|
---|
5 | #include <mcheck.h>
|
---|
6 | #include <stdio.h>
|
---|
7 | #include <stdlib.h>
|
---|
8 | #include <string.h>
|
---|
9 |
|
---|
10 |
|
---|
11 | /* How many load/unload operations do we do. */
|
---|
12 | #define TEST_ROUNDS 1000
|
---|
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 },
|
---|
26 | { "testobj4.so", NULL },
|
---|
27 | { "testobj5.so", NULL },
|
---|
28 | { "testobj6.so", NULL },
|
---|
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 },
|
---|
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 },
|
---|
67 | };
|
---|
68 | #define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
---|
69 |
|
---|
70 |
|
---|
71 | #include <include/link.h>
|
---|
72 |
|
---|
73 | #define OUT \
|
---|
74 | for (map = _r_debug.r_map; map != NULL; map = map->l_next) \
|
---|
75 | if (map->l_type == lt_loaded) \
|
---|
76 | printf ("name = \"%s\", direct_opencount = %d\n", \
|
---|
77 | map->l_name, (int) map->l_direct_opencount); \
|
---|
78 | fflush (stdout)
|
---|
79 |
|
---|
80 |
|
---|
81 | int
|
---|
82 | main (int argc, char *argv[])
|
---|
83 | {
|
---|
84 | int debug = argc > 1 && argv[1][0] != '\0';
|
---|
85 | int count = TEST_ROUNDS;
|
---|
86 | int result = 0;
|
---|
87 | struct link_map *map;
|
---|
88 |
|
---|
89 | mtrace ();
|
---|
90 |
|
---|
91 | /* Just a seed. */
|
---|
92 | srandom (TEST_ROUNDS);
|
---|
93 |
|
---|
94 | if (debug)
|
---|
95 | {
|
---|
96 | puts ("in the beginning");
|
---|
97 | OUT;
|
---|
98 | }
|
---|
99 |
|
---|
100 | while (count--)
|
---|
101 | {
|
---|
102 | int nr = random () % NTESTS;
|
---|
103 | int index = tests[nr].index;
|
---|
104 |
|
---|
105 | printf ("%4d: %4d: ", count + 1, nr);
|
---|
106 | fflush (stdout);
|
---|
107 |
|
---|
108 | if (testobjs[index].handle == NULL)
|
---|
109 | {
|
---|
110 | int (*fct) (int);
|
---|
111 |
|
---|
112 | /* Load the object. */
|
---|
113 | testobjs[index].handle = dlopen (testobjs[index].name,
|
---|
114 | tests[nr].options);
|
---|
115 | if (testobjs[index].handle == NULL)
|
---|
116 | error (EXIT_FAILURE, 0, "cannot load `%s': %s",
|
---|
117 | testobjs[index].name, dlerror ());
|
---|
118 |
|
---|
119 | /* Test the function call. */
|
---|
120 | fct = dlsym (testobjs[index].handle, tests[nr].fname);
|
---|
121 | if (fct == NULL)
|
---|
122 | error (EXIT_FAILURE, 0,
|
---|
123 | "cannot get function `%s' from shared object `%s': %s",
|
---|
124 | tests[nr].fname, testobjs[index].name, dlerror ());
|
---|
125 |
|
---|
126 | fct (10);
|
---|
127 |
|
---|
128 | printf ("successfully loaded `%s', handle %p\n",
|
---|
129 | testobjs[index].name, testobjs[index].handle);
|
---|
130 | }
|
---|
131 | else
|
---|
132 | {
|
---|
133 | if (dlclose (testobjs[index].handle) != 0)
|
---|
134 | {
|
---|
135 | printf ("failed to close %s\n", testobjs[index].name);
|
---|
136 | result = 1;
|
---|
137 | }
|
---|
138 | else
|
---|
139 | printf ("successfully unloaded `%s', handle %p\n",
|
---|
140 | testobjs[index].name, testobjs[index].handle);
|
---|
141 |
|
---|
142 | testobjs[index].handle = NULL;
|
---|
143 |
|
---|
144 | if (testobjs[0].handle == NULL
|
---|
145 | && testobjs[1].handle == NULL
|
---|
146 | && testobjs[5].handle == NULL)
|
---|
147 | {
|
---|
148 | /* In this case none of the objects above should be
|
---|
149 | present. */
|
---|
150 | for (map = _r_debug.r_map; map != NULL; map = map->l_next)
|
---|
151 | if (map->l_type == lt_loaded
|
---|
152 | && (strstr (map->l_name, testobjs[0].name) != NULL
|
---|
153 | || strstr (map->l_name, testobjs[1].name) != NULL
|
---|
154 | || strstr (map->l_name, testobjs[5].name) != NULL))
|
---|
155 | {
|
---|
156 | printf ("`%s' is still loaded\n", map->l_name);
|
---|
157 | result = 1;
|
---|
158 | }
|
---|
159 | }
|
---|
160 | }
|
---|
161 |
|
---|
162 | if (debug)
|
---|
163 | OUT;
|
---|
164 | }
|
---|
165 |
|
---|
166 | /* Unload all loaded modules. */
|
---|
167 | for (count = 0; count < (int) NOBJS; ++count)
|
---|
168 | if (testobjs[count].handle != NULL)
|
---|
169 | {
|
---|
170 | printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
|
---|
171 | testobjs[count].name,
|
---|
172 | ((struct link_map *) testobjs[count].handle)->l_initfini,
|
---|
173 | ((struct link_map *) testobjs[count].handle)->l_versions);
|
---|
174 |
|
---|
175 | if (dlclose (testobjs[count].handle) != 0)
|
---|
176 | {
|
---|
177 | printf ("failed to close %s\n", testobjs[count].name);
|
---|
178 | result = 1;
|
---|
179 | }
|
---|
180 | }
|
---|
181 |
|
---|
182 | /* Check whether all files are unloaded. */
|
---|
183 | for (map = _r_debug.r_map; map != NULL; map = map->l_next)
|
---|
184 | if (map->l_type == lt_loaded)
|
---|
185 | {
|
---|
186 | printf ("name = \"%s\", direct_opencount = %d\n",
|
---|
187 | map->l_name, (int) map->l_direct_opencount);
|
---|
188 | result = 1;
|
---|
189 | }
|
---|
190 |
|
---|
191 | return result;
|
---|
192 | }
|
---|
193 |
|
---|
194 |
|
---|
195 | extern int foo (int a);
|
---|
196 | int
|
---|
197 | foo (int a)
|
---|
198 | {
|
---|
199 | return a - 1;
|
---|
200 | }
|
---|