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:
12: #define TEST_ROUNDS 1000
13:
14:
15: static struct
16: {
17:
18: const char *name;
19:
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:
36: const char *fname;
37:
38: int index;
39:
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 MAPS ((struct link_map *) _r_debug.r_map)
74:
75: #define OUT \
76: for (map = MAPS; map != NULL; map = map->l_next) \
77: if (map->l_type == lt_loaded) \
78: printf ("name = \"%s\", direct_opencount = %d\n", \
79: map->l_name, (int) map->l_direct_opencount); \
80: fflush (stdout)
81:
82:
83: int
84: main (int argc, char *argv[])
85: {
86: int debug = argc > 1 && argv[1][0] != '\0';
87: int count = TEST_ROUNDS;
88: int result = 0;
89: struct link_map *map;
90:
91: mtrace ();
92:
93:
94: srandom (TEST_ROUNDS);
95:
96: if (debug)
97: {
98: puts ("in the beginning");
99: OUT;
100: }
101:
102: while (count--)
103: {
104: int nr = random () % NTESTS;
105: int index = tests[nr].index;
106:
107: printf ("%4d: %4d: ", count + 1, nr);
108: fflush (stdout);
109:
110: if (testobjs[index].handle == NULL)
111: {
112: int (*fct) (int);
113:
114:
115: testobjs[index].handle = dlopen (testobjs[index].name,
116: tests[nr].options);
117: if (testobjs[index].handle == NULL)
118: error (EXIT_FAILURE, 0, "cannot load `%s': %s",
119: testobjs[index].name, dlerror ());
120:
121:
122: fct = dlsym (testobjs[index].handle, tests[nr].fname);
123: if (fct == NULL)
124: error (EXIT_FAILURE, 0,
125: "cannot get function `%s' from shared object `%s': %s",
126: tests[nr].fname, testobjs[index].name, dlerror ());
127:
128: fct (10);
129:
130: printf ("successfully loaded `%s', handle %p\n",
131: testobjs[index].name, testobjs[index].handle);
132: }
133: else
134: {
135: if (dlclose (testobjs[index].handle) != 0)
136: {
137: printf ("failed to close %s\n", testobjs[index].name);
138: result = 1;
139: }
140: else
141: printf ("successfully unloaded `%s', handle %p\n",
142: testobjs[index].name, testobjs[index].handle);
143:
144: testobjs[index].handle = NULL;
145:
146: if (testobjs[0].handle == NULL
147: && testobjs[1].handle == NULL
148: && testobjs[5].handle == NULL)
149: {
150:
151:
152: for (map = MAPS; map != NULL; map = map->l_next)
153: if (map->l_type == lt_loaded
154: && (strstr (map->l_name, testobjs[0].name) != NULL
155: || strstr (map->l_name, testobjs[1].name) != NULL
156: || strstr (map->l_name, testobjs[5].name) != NULL))
157: {
158: printf ("`%s' is still loaded\n", map->l_name);
159: result = 1;
160: }
161: }
162: }
163:
164: if (debug)
165: OUT;
166: }
167:
168:
169: for (count = 0; count < (int) NOBJS; ++count)
170: if (testobjs[count].handle != NULL)
171: {
172: printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
173: testobjs[count].name,
174: ((struct link_map *) testobjs[count].handle)->l_initfini,
175: ((struct link_map *) testobjs[count].handle)->l_versions);
176:
177: if (dlclose (testobjs[count].handle) != 0)
178: {
179: printf ("failed to close %s\n", testobjs[count].name);
180: result = 1;
181: }
182: }
183:
184:
185: for (map = MAPS; map != NULL; map = map->l_next)
186: if (map->l_type == lt_loaded)
187: {
188: printf ("name = \"%s\", direct_opencount = %d\n",
189: map->l_name, (int) map->l_direct_opencount);
190: result = 1;
191: }
192:
193: return result;
194: }
195:
196:
197: extern int foo (int a);
198: int
199: foo (int a)
200: {
201: return a - 1;
202: }