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"
7 const char* dllName = "libdlopen_ns_dso.so";
8 const char* dllName2 = "libdlopen_dso.so";
9 const char* errPath_ns = "/src/common";
10 const char* ndk_so = "libdlopen_ns_dso_ndk.so";
11 const char* system_so = "libdlopen_ns_dso_sys.so";
12 typedef void*(*CALL_DLOPEN_PTR)(const char *);
13 
14 // Test whether it is ok for main to dlopen ndk so.
main_dlopen_ndk_sonull15 void 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.
system_so_dlopen_ndk_sonull25 void 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.
ndk_so_dlopen_default_ns_sonull42 void 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.
dlopen_same_so_twice_by_same_ns(char * dllPath_ns)61 void 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.
dlopen_same_so_by_different_ns(char * dllPath_ns)86 void 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.
dlopen_same_so_by_different_inherit_ns(char * dllPath_ns)115 void 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 
dlopen_seperated(char * dllPath_ns)144 void 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 
dlopen_inherit(char* dllPath_ns)176 void 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 
dlopen_inherit_check_can_pass(char* dllPath_ns)212 void 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 
dlopen_test_dlns_create2null248 void 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 
main(int argc, char *argv[])267 int 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 }