1#include <dlfcn.h>
2#include <stdio.h>
3#include <string.h>
4#include "test.h"
5
6#define SO_HAS_DEPENDENCES "libdlopen_so_dep_dlopen_ns_dso.so"
7const char* dllName = "libdlopen_ns_dso.so";
8const char* dllName2 = "libdlopen_dso.so";
9const char* errPath_ns = "/src/common";
10const char* ndk_so = "libdlopen_ns_dso_ndk.so";
11const char* system_so = "libdlopen_ns_dso_sys.so";
12typedef void*(*CALL_DLOPEN_PTR)(const char *);
13
14// Test whether it is ok for main to dlopen ndk so.
15void main_dlopen_ndk_so()
16{
17    void *handle = dlopen(ndk_so, RTLD_NOW);
18    if (!handle)
19        t_error("main dlopen ndk so %s failed: %s\n", ndk_so, dlerror());
20    if (dlclose(handle))
21        t_error("dlclose %s failed : %s \n", ndk_so, dlerror());
22}
23
24// Test whether it is ok for system so to dlopen ndk so.
25void system_so_dlopen_ndk_so()
26{
27    void *handle = dlopen(system_so, RTLD_NOW);
28    if (!handle) {
29        t_error("dlopen %s failed : %s \n", system_so, dlerror());
30    }
31    CALL_DLOPEN_PTR call_dlopen = dlsym(handle, "call_dlopen");
32    if (!call_dlopen) {
33        t_error("dlsym %s failed : %s \n", "call_dlopen", dlerror());
34    }
35    void *res = call_dlopen(ndk_so);
36    if (!res) {
37        t_error("default ns so(%s) can't dlopen ndk so(%s)", system_so, ndk_so);
38    }
39}
40
41// Test whether it is ok for ndk so to dlopen system so.
42void ndk_so_dlopen_default_ns_so()
43{
44    Dl_namespace dlns;
45    dlns_init(&dlns, "ndk");
46    void *handle = dlopen_ns(&dlns, ndk_so, RTLD_NOW);
47    if (!handle) {
48        t_error("dlopen_ns(ns=%s, so=%s) failed : %s \n", "ndk", ndk_so, dlerror());
49    }
50    CALL_DLOPEN_PTR call_dlopen = dlsym(handle, "call_dlopen");
51    if (!call_dlopen) {
52        t_error("dlsym %s failed : %s \n", "call_dlopen", dlerror());
53    }
54    void *res = call_dlopen(system_so);
55    if (!res) {
56        t_error("ndk so(%s) can't dlopen system so(%s)", ndk_so, system_so);
57    }
58}
59
60// Test whether dlopen same so twice by same ns to get same handle.
61void dlopen_same_so_twice_by_same_ns(char * dllPath_ns)
62{
63    Dl_namespace dlns1;
64    dlns_init(&dlns1, "ns_for_dlopen_same_so_twice_by_same_ns");
65    dlns_create(&dlns1, dllPath_ns);
66
67    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
68    if(!handle1)
69        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
70
71    void* handle2 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
72    if(!handle2)
73        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
74
75    if (handle1 != handle2)
76        t_error("dlopen same so(%s) by same ns but handle is different %s \n", dllName);
77
78    if(dlclose(handle1))
79        t_error("dlclose %s failed : %s \n", dllName, dlerror());
80
81    if(dlclose(handle2))
82        t_error("dlclose %s failed : %s \n", dllName, dlerror());
83}
84
85// Test whether dlopen same so by different ns to get different handle.
86void dlopen_same_so_by_different_ns(char * dllPath_ns)
87{
88    Dl_namespace dlns1;
89    dlns_init(&dlns1, "ns_for_dlopen_same_so_by_different_ns_1");
90    dlns_create(&dlns1, dllPath_ns);
91
92    Dl_namespace dlns2;
93    dlns_init(&dlns2, "ns_for_dlopen_same_so_by_different_ns_2");
94    dlns_create(&dlns2, dllPath_ns);
95
96    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
97    if(!handle1)
98        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
99
100    void* handle2 = dlopen_ns(&dlns2, dllName, RTLD_NOW);
101    if(!handle2)
102        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns2.name, dllName, dlerror());
103
104    if (handle1 == handle2)
105        t_error("dlopen same so(%s) by same ns but handle is different %s \n", dllName);
106
107    if(dlclose(handle1))
108        t_error("dlclose %s failed : %s \n", dllName, dlerror());
109
110    if(dlclose(handle2))
111        t_error("dlclose %s failed : %s \n", dllName, dlerror());
112}
113
114// Test whether dlopen same so by inherit ns to get same handle.
115void dlopen_same_so_by_different_inherit_ns(char * dllPath_ns)
116{
117    Dl_namespace dlns1;
118    dlns_init(&dlns1, "ns_for_dlopen_same_so_by_different_inherit_ns_1");
119    dlns_create(&dlns1, dllPath_ns);
120
121    Dl_namespace dlns2;
122    dlns_init(&dlns2, "ns_for_dlopen_same_so_by_different_inherit_ns_2");
123    dlns_create2(&dlns2, errPath_ns, 0);
124    dlns_inherit(&dlns2, &dlns1, dllName);
125
126    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
127    if(!handle1)
128        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
129
130    void* handle2 = dlopen_ns(&dlns2, dllName, RTLD_NOW);
131    if(!handle2)
132        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns2.name, dllName, dlerror());
133
134    if (handle1 != handle2)
135        t_error("dlopen same so(%s) by inherit ns but handle is different %s \n", dllName);
136
137    if(dlclose(handle1))
138        t_error("dlclose %s failed : %s \n", dllName, dlerror());
139
140    if(dlclose(handle2))
141        t_error("dlclose %s failed : %s \n", dllName, dlerror());
142}
143
144void dlopen_seperated(char * dllPath_ns)
145{
146    Dl_namespace dlns_default;
147    dlns_get(NULL, &dlns_default);
148    Dl_namespace dlns1;
149    dlns_init(&dlns1, "ns_for_no_seperated");
150    dlns_create2(&dlns1, errPath_ns, 0);
151    dlns_inherit(&dlns1, &dlns_default, "libc++.so");
152    void* handle = NULL;
153    // current ns can't load this so.
154    handle = dlopen_ns(&dlns1, dllName, RTLD_NOW);
155    if(handle)
156        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
157
158    // current ns can load the so by absolute path.
159    char absolute_path_1[512];
160    snprintf(absolute_path_1, sizeof(absolute_path_1), "%s/%s", dllPath_ns, dllName);
161    handle = dlopen_ns(&dlns1, absolute_path_1, RTLD_NOW);
162    if (!handle)
163        t_error("%s can load %s by absolute path but failed : %s \n", dlns1.name, absolute_path_1, dlerror());
164
165    if(dlclose(handle))
166        t_error("dlclose %s failed : %s \n", absolute_path_1, dlerror());
167
168    // current ns can't load the so by absolute path if it has inaccessible dependent so.
169    char absolute_path_2[512];
170    snprintf(absolute_path_2, sizeof(absolute_path_2), "%s/%s", dllPath_ns, SO_HAS_DEPENDENCES);
171    handle = dlopen_ns(&dlns1, absolute_path_2, RTLD_NOW);
172    if (handle)
173        t_error("%s can't load %s by absolute path because but it has inaccessible dependent so but succeed : %s \n", dlns1.name, absolute_path_2, dlerror());
174}
175
176void dlopen_inherit(char* dllPath_ns)
177{
178    Dl_namespace dlns_default;
179    dlns_get(NULL, &dlns_default);
180    Dl_namespace inherit_A, inherit_B;
181    dlns_init(&inherit_A, "inherir_error_lib_A");
182    dlns_init(&inherit_B, "inherir_error_lib_B");
183    dlns_create2(&inherit_A, NULL, 0);
184    dlns_create2(&inherit_B, dllPath_ns, 0);
185    dlns_inherit(&inherit_B, &dlns_default, "libc++.so");
186
187    // inherit_A can't load the so because search path is NULL.
188    void* handle1 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
189    if(handle1){
190        t_error("dlopen_ns_by_ini_no_inherit handle %s should not open successfully \n", dllName);
191        dlclose(handle1);
192    }
193
194    // inherit_A can load the so by inherit_B.
195    dlns_inherit(&inherit_A, &inherit_B, dllName);
196    void* handle2 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
197    if(!handle2)
198        t_error("dlopen_ns_by_dlns_inherir handle get error %s open failed : %s \n", dllName, dlerror());
199
200    if(dlclose(handle2))
201        t_error("dlclose_by_dlns_inherir handle %s close failed : %s\n", dllName, dlerror());
202
203    // inherit_A can't load the so by inherit ns if the so isn't in shared libs.
204    dlns_inherit(&inherit_A, &inherit_B, dllName2);
205    void* handle3 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
206    if(handle3){
207        t_error("dlopen_ns_by_ini_no_inherit handle2 %s should not open successfully \n", dllName);
208        dlclose(handle3);
209    }
210}
211
212void dlopen_inherit_check_can_pass(char* dllPath_ns)
213{
214    Dl_namespace dlns_default;
215    dlns_get(NULL, &dlns_default);
216    Dl_namespace transitivity_A, transitivity_B, transitivity_C;
217    dlns_init(&transitivity_A, "transitivity_A");
218    dlns_init(&transitivity_B, "transitivity_B");
219    dlns_init(&transitivity_C, "transitivity_C");
220    dlns_create2(&transitivity_A, NULL, 0);
221    dlns_create2(&transitivity_B, NULL, 0);
222    dlns_create2(&transitivity_C, dllPath_ns, 0);
223    dlns_inherit(&transitivity_A, &transitivity_B, NULL);
224    dlns_inherit(&transitivity_B, &transitivity_C, dllName);
225    dlns_inherit(&transitivity_C, &dlns_default, "libc++.so");
226
227    void* handleB = dlopen_ns(&transitivity_B, dllName, RTLD_LAZY);
228    if(!handleB)
229        t_error("dlopen_ns_by_inherit_transitivity handleB get error %s open failed : %s \n", dllName, dlerror());
230
231    void* handleC = dlopen_ns(&transitivity_C, dllName, RTLD_LAZY);
232    if(!handleC)
233        t_error("dlopen_ns_by_inherit_transitivity handleC get error %s open failed : %s \n", dllName, dlerror());
234
235    if(dlclose(handleC))
236        t_error("dlclose_by_inherit_transitivity handleC %s close failed : %s\n", dllName, dlerror());
237    if(dlclose(handleB))
238        t_error("dlclose_by_inherit_transitivity handleB %s close failed : %s\n", dllName, dlerror());
239
240    // transitivity_A can't load so because inherit can't pass.
241    void* handleA = dlopen_ns(&transitivity_A, dllName, RTLD_LAZY);
242    if(handleA){
243        t_error("dlopen_ns_by_inherit_transitivity handleA %s should not open successfully \n", dllName);
244        dlclose(handleA);
245    }
246}
247
248void dlopen_test_dlns_create2()
249{
250    Dl_namespace dlns;
251    dlns_init(&dlns, "ns_for_create2");
252    // ns_for_create2 doesn't exist, it will use default ns to search so.
253    void* handle = dlopen_ns(&dlns, dllName, RTLD_LAZY);
254    if(!handle)
255        t_error("dlopen_ns %s use a non-existent ns failed: %s\n", dllName, dlerror());
256
257    if(dlclose(handle))
258        t_error("dlclose %s failed : %s \n", dllName, dlerror());
259
260    // 0: ns_for_create2 doesn't inherit default ns.
261    dlns_create2(&dlns, errPath_ns, 0);
262    void* handle2 = dlopen_ns(&dlns, dllName, RTLD_LAZY);
263    if(handle2)
264        t_error("%s namespace can't see %s but dlopen succee.\n", "ns_for_create2", dllName);
265}
266
267int main(int argc, char *argv[])
268{
269    char buf[512],path[512];
270    char* i;
271    //带so的路径
272    if (!t_pathrel(buf, sizeof buf, argv[0], "libdlopen_ns_dso.so")) {
273        t_error("failed to obtain relative path to libdlopen_ns_dso.so\n");
274        return 1;
275	}
276    //包含so的路径
277    if (!t_pathrel(path, sizeof path, argv[0], "")) {
278        t_error("failed to obtain relative path to path\n");
279        return 1;
280	}
281    path[strlen (path) -1 ] ='\0';
282    main_dlopen_ndk_so();
283    system_so_dlopen_ndk_so();
284    ndk_so_dlopen_default_ns_so();
285    dlopen_same_so_twice_by_same_ns(path);
286    dlopen_same_so_by_different_ns(path);
287    dlopen_same_so_by_different_inherit_ns(path);
288    dlopen_seperated(path);
289    dlopen_test_dlns_create2();
290    dlopen_inherit(path);
291    dlopen_inherit_check_can_pass(path);
292
293    return t_status;
294}