• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <dlfcn.h>
2 #include <gtest/gtest.h>
3 #include <libgen.h>
4 #include <sys/auxv.h>
5 #include <unistd.h>
6 
7 #include "libs/ldso_gtest_util.h"
8 
9 using namespace testing::ext;
10 
11 #define INIT_ORDER 321
12 #define FINALIZE_ORDER 123
13 
14 typedef int (*FuncTypeRetInt)(void);
15 typedef void (*FuncTypeBool)(bool*);
16 static std::string g_ldsoTestRootPath = "/data/tmp/libcgtest/libs";
17 
18 class LdsoDlopenTest : public testing::Test {
SetUp()19     void SetUp() override {}
TearDown()20     void TearDown() override {}
21 };
22 
23 /**
24  * @tc.name: dlopen_001
25  * @tc.desc: Test the loading order of dynamic link libraries.
26  *           libdlopen_relocation.so(RelocationTest, calls RelocationTestOrder)
27  *            |-----1.so(RelocationTestOrder)->expect value
28  *            |-----2.so(RelocationTestOrder)
29  * @tc.type: FUNC
30  */
31 HWTEST_F(LdsoDlopenTest, dlopen_001, TestSize.Level1)
32 {
33     void* handle = dlopen("libdlopen_relocation.so", RTLD_NOW);
34     ASSERT_NE(handle, nullptr);
35 
36     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "RelocationTest"));
37     ASSERT_NE(fn, nullptr);
38     EXPECT_EQ(EXPECT_RETURN_VALUE_15, fn());
39 
40     dlclose(handle);
41 }
42 
43 /**
44  * @tc.name: dlopen_002
45  * @tc.desc: Test the loading order of dynamic link libraries.
46  *           libdlopen_order_02.so(LoadOrderTest01, calls LoadOrderTest)
47  *            |-----1_2.so
48  *            |-----|-----1.so(LoadOrderTest)
49  *            |     |-----2.so(LoadOrderTest, LoadOrderTest02)->expect value2
50  *            |-----3.so(LoadOrderTest)->expect value1
51  * @tc.type: FUNC
52  */
53 HWTEST_F(LdsoDlopenTest, dlopen_002, TestSize.Level1)
54 {
55     void* handle = dlopen("libdlopen_order_02.so", RTLD_NOW | RTLD_GLOBAL);
56     ASSERT_NE(handle, nullptr);
57 
58     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(RTLD_DEFAULT, "LoadOrderTest01"));
59     ASSERT_NE(fn, nullptr);
60     EXPECT_EQ(EXPECT_RETURN_VALUE_3, fn());
61     fn = reinterpret_cast<FuncTypeRetInt>(dlsym(RTLD_DEFAULT, "LoadOrderTest02"));
62     ASSERT_NE(fn, nullptr);
63     EXPECT_EQ(EXPECT_RETURN_VALUE_12, fn());
64 
65     dlclose(handle);
66 }
67 
68 /**
69  * @tc.name: dlopen_003
70  * @tc.desc: Test the loading order of dynamic link libraries.
71  *           libdlopen_order_003.so
72  *            |-----003_1.so
73  *            |-----|-----003_1_1.so(DlopenOrderTestImpl003)->expect value
74  *            |     |-----003_1_2.so(DlopenOrderTestImpl003)
75  *            |-----003_2.so
76  *            |-----|-----003_2_1.so(DlopenOrderTestImpl003)
77  *            |     |-----003_2_2.so(DlopenOrderTest003, calls DlopenOrderTestImpl003)
78  * @tc.type: FUNC
79  */
80 HWTEST_F(LdsoDlopenTest, dlopen_003, TestSize.Level1)
81 {
82     void* handle = dlopen("libdlopen_order_003.so", RTLD_NOW | RTLD_LOCAL);
83     ASSERT_NE(handle, nullptr);
84 
85     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "DlopenOrderTest003"));
86     ASSERT_NE(fn, nullptr);
87     EXPECT_EQ(EXPECT_RETURN_VALUE_311, fn());
88 
89     dlclose(handle);
90 }
91 
92 /**
93  * @tc.name: dlopen_004
94  * @tc.desc: Test the loading order of dynamic link libraries.
95  *           libdlopen_005.so
96  *            |-----005_1.so
97  *            |-----|-----005_1_1.so(DlopenTestImpl005)->expect value
98  *            |     |-----005_1_2.so(DlopenTestImpl005)
99  *            |-----005_2.so(DlopenTest005, calls DlopenTestImpl005)
100  *            |-----|-----005_2_1.so(DlopenTestImpl005)
101  * @tc.type: FUNC
102  */
103 HWTEST_F(LdsoDlopenTest, dlopen_004, TestSize.Level1)
104 {
105     void* handle = dlopen("libdlopen_005.so", RTLD_NOW | RTLD_LOCAL);
106     ASSERT_NE(handle, nullptr);
107 
108     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "DlopenTest005"));
109     ASSERT_NE(fn, nullptr);
110     EXPECT_EQ(EXPECT_RETURN_VALUE_511, fn());
111 
112     dlclose(handle);
113 }
114 
115 /**
116  * @tc.name: dlopen_005
117  * @tc.desc: Test the loading order of dynamic link libraries.
118  *            libdlopen_test_dependency.so(DlopenTestDependencyImpl)
119  *            |-----libdlopen_test_dependency_1.so(DlopenTestDependency, calls DlopenTestDependencyImpl)
120  *            |-----|-----libdlopen_test_dependency_1_1_invalid.so->soname libdlopen_test_dependency_1_1.so
121  *            |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|----libdlopen_test_dependency_1_1_1.so
122  *            |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|----|----libdlopen_test_dependency_1.so
123  * @tc.type: FUNC
124  */
125 HWTEST_F(LdsoDlopenTest, dlopen_005, TestSize.Level1)
126 {
127     void* handle = dlopen("libdlopen_test_dependency.so", RTLD_NOW);
128     ASSERT_NE(handle, nullptr);
129     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "DlopenTestDependency"));
130     ASSERT_NE(fn, nullptr);
131     EXPECT_EQ(1, fn());
132     dlclose(handle);
133 
134     handle = dlopen("libdlopen_test_dependency.so", RTLD_NOW | RTLD_NOLOAD);
135     EXPECT_TRUE(handle == nullptr);
136 
137     handle = dlopen("libdlopen_test_dependency_1.so", RTLD_NOW | RTLD_NOLOAD);
138     EXPECT_TRUE(handle == nullptr);
139 }
140 
141 /**
142  * @tc.name: dlopen_006
143  * @tc.desc: If the "so" has been loaded, when using the RTLD_NOLOAD to dlopen the "so",
144  *          the same handle of the "so" can still be returned.
145  * @tc.type: FUNC
146  */
147 HWTEST_F(LdsoDlopenTest, dlopen_006, TestSize.Level1)
148 {
149     void* handle = dlopen("libdlopen_common.so", RTLD_NOLOAD);
150     EXPECT_TRUE(handle == nullptr);
151     handle = dlopen("libdlopen_common.so", RTLD_NOW);
152     ASSERT_NE(handle, nullptr);
153     void* handle01 = dlopen("libdlopen_common.so", RTLD_NOLOAD);
154     ASSERT_NE(handle01, nullptr);
155     EXPECT_EQ(handle, handle01);
156 
157     dlclose(handle);
158     dlclose(handle01);
159 }
160 
161 /**
162  * @tc.name: dlopen_007
163  * @tc.desc: Test preloads a dependent "003_1.so" before loading "order_003.so".
164  * @tc.type: FUNC
165  */
166 HWTEST_F(LdsoDlopenTest, dlopen_007, TestSize.Level1)
167 {
168     void* handle01 = dlopen("libdlopen_order_003_1.so", RTLD_NOLOAD);
169     EXPECT_TRUE(handle01 == nullptr);
170     void* handle = dlopen("libdlopen_order_003.so", RTLD_NOLOAD);
171     EXPECT_TRUE(handle == nullptr);
172 
173     handle01 = dlopen("libdlopen_order_003_1.so", RTLD_NOW);
174     ASSERT_NE(handle01, nullptr);
175     handle = dlopen("libdlopen_order_003.so", RTLD_NOW);
176     ASSERT_NE(handle, nullptr);
177 
178     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "DlopenOrderTest003"));
179     ASSERT_NE(fn, nullptr);
180     EXPECT_EQ(EXPECT_RETURN_VALUE_311, fn());
181 
182     dlclose(handle01);
183     dlclose(handle);
184 }
185 
186 /**
187  * @tc.name: dlopen_008
188  * @tc.desc: Test the default mode of dlopen is RTLD_LOCAL.
189  * @tc.type: FUNC
190  */
191 HWTEST_F(LdsoDlopenTest, dlopen_008, TestSize.Level1)
192 {
193     void* handle = dlopen("libdlopen_relocation.so", RTLD_NOW);
194     ASSERT_NE(handle, nullptr);
195     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "RelocationTest"));
196     ASSERT_NE(fn, nullptr);
197     EXPECT_EQ(EXPECT_RETURN_VALUE_15, fn());
198     dlclose(handle);
199 
200     handle = dlopen("libdlopen_relocation.so", RTLD_NOW | RTLD_LOCAL);
201     ASSERT_NE(handle, nullptr);
202     fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "RelocationTest"));
203     ASSERT_NE(fn, nullptr);
204     EXPECT_EQ(EXPECT_RETURN_VALUE_15, fn());
205     dlclose(handle);
206 }
207 
208 /**
209  * @tc.name: dlopen_009
210  * @tc.desc: Test when the mode of dlopen is RTLD_GLOBAL, dlsym can use RTLD_DEFAULT to find symbols.
211  * @tc.type: FUNC
212  */
213 HWTEST_F(LdsoDlopenTest, dlopen_009, TestSize.Level1)
214 {
215     void* handle = dlopen("libdlopen_relocation.so", RTLD_NOW | RTLD_GLOBAL);
216     ASSERT_NE(handle, nullptr);
217     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(RTLD_DEFAULT, "RelocationTest"));
218     ASSERT_NE(fn, nullptr);
219     EXPECT_EQ(EXPECT_RETURN_VALUE_15, fn());
220 
221     void* handle01 = dlopen(nullptr, RTLD_NOW);
222     ASSERT_NE(handle01, nullptr);
223     fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle01, "RelocationTest"));
224     ASSERT_NE(fn, nullptr);
225 
226     dlclose(handle);
227     dlclose(handle01);
228 }
229 
230 /**
231  * @tc.name: dlopen_010
232  * @tc.desc: Test libdlopen_load_so.so depends on libdlopen_load_so_1.so that calls dlopen.
233  * @tc.type: FUNC
234  */
235 HWTEST_F(LdsoDlopenTest, dlopen_010, TestSize.Level1)
236 {
237     void* handle = dlopen("libdlopen_load_so.so", RTLD_NOW);
238     ASSERT_NE(handle, nullptr);
239     dlclose(handle);
240 }
241 
242 /**
243  * @tc.name: dlopen_011
244  * @tc.desc: After using RTLD_NODELETE to load library with dlopen,
245  *          during dlclose, the library is not unloaded.
246  * @tc.type: FUNC
247  */
248 HWTEST_F(LdsoDlopenTest, dlopen_011, TestSize.Level1)
249 {
250     void* handle = dlopen("libdlopen_nodelete.so", RTLD_NOW | RTLD_NODELETE);
251     ASSERT_NE(handle, nullptr);
252     FuncTypeBool fn = reinterpret_cast<FuncTypeBool>(dlsym(handle, "DlopenNodeleteSetIsClosedPtr"));
253     ASSERT_NE(fn, nullptr);
254     bool isClosed = false;
255     fn(&isClosed);
256 
257     int32_t* value = reinterpret_cast<int32_t*>(dlsym(handle, "g_testValue"));
258     ASSERT_NE(value, nullptr);
259     *value = TEST_NUM_20;
260     dlclose(handle);
261 
262     value = reinterpret_cast<int32_t*>(dlsym(handle, "g_testValue"));
263     ASSERT_NE(value, nullptr);
264     EXPECT_EQ(*value, TEST_NUM_20);
265     EXPECT_FALSE(isClosed);
266 }
267 
268 /**
269  * @tc.name: dlopen_012
270  * @tc.desc: Test invalid library.
271  * @tc.type: FUNC
272  */
273 HWTEST_F(LdsoDlopenTest, dlopen_012, TestSize.Level1)
274 {
275     void* handle = dlopen("libdlopen_invalid.so", RTLD_NOW);
276     EXPECT_TRUE(handle == nullptr);
277 }
278 
279 static int32_t g_finalizeOrder;
280 
FinalizeCallback(int32_t order)281 static void FinalizeCallback(int32_t order)
282 {
283     g_finalizeOrder = g_finalizeOrder * TEST_NUM_10 + order;
284 }
285 
286 /**
287  * @tc.name: dlopen_013
288  * @tc.desc: Test the construction and deconstruction order of libraries.
289  * @tc.type: FUNC
290  */
291 HWTEST_F(LdsoDlopenTest, dlopen_013, TestSize.Level1)
292 {
293     void* handle = dlopen("libdlopen_init_finalize.so", RTLD_NOW);
294     ASSERT_NE(handle, nullptr);
295     int32_t* initOrder = reinterpret_cast<int32_t*>(dlsym(handle, "g_initOrder"));
296     ASSERT_NE(initOrder, nullptr);
297     EXPECT_EQ(INIT_ORDER, *initOrder);
298 
299     void (*finalizeCb)(void (*callback)(int32_t order));
300     finalizeCb = reinterpret_cast<void (*)(void (*callback)(int32_t order))>(dlsym(handle, "SetFinalizeCallback"));
301     ASSERT_NE(finalizeCb, nullptr);
302     finalizeCb(FinalizeCallback);
303     dlclose(handle);
304     EXPECT_EQ(FINALIZE_ORDER, g_finalizeOrder);
305 }
306 
307 /**
308  * @tc.name: dlopen_014
309  * @tc.desc: Test that library with global flags can be dlopened.
310  * @tc.type: FUNC
311  */
312 HWTEST_F(LdsoDlopenTest, dlopen_014, TestSize.Level1)
313 {
314     void* handle = dlopen("libdlopen_global.so", RTLD_NOW);
315     ASSERT_NE(handle, nullptr);
316     dlclose(handle);
317 }
318 
319 /**
320  * @tc.name: dlopen_015
321  * @tc.desc: Test that library with rpath can be dlopened.
322  * @tc.type: FUNC
323  */
324 HWTEST_F(LdsoDlopenTest, dlopen_015, TestSize.Level1)
325 {
326     void* handle = dlopen("libdlopen_rpath.so", RTLD_NOW);
327     ASSERT_NE(handle, nullptr);
328 
329     void* fn = dlsym(handle, "Dlopen005");
330     ASSERT_NE(fn, nullptr);
331     dlclose(handle);
332 }
333 
334 /**
335  * @tc.name: dlopen_016
336  * @tc.desc: Test that dlopen successfully by using rpath's absolute path.
337  * @tc.type: FUNC
338  */
339 HWTEST_F(LdsoDlopenTest, dlopen_016, TestSize.Level1)
340 {
341     void* handle = dlopen((g_ldsoTestRootPath + "/libdlopen_rpath.so").c_str(), RTLD_NOW);
342     ASSERT_NE(handle, nullptr);
343 
344     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "DlopenTestImpl005"));
345     ASSERT_NE(fn, nullptr);
346     EXPECT_EQ(fn(), EXPECT_RETURN_VALUE_511);
347 
348     dlclose(handle);
349 }
350 
351 /**
352  * @tc.name: dlopen_017
353  * @tc.desc: Test that dlopen successfully by using absolute path.
354  * @tc.type: FUNC
355  */
356 HWTEST_F(LdsoDlopenTest, dlopen_017, TestSize.Level1)
357 {
358     void* handle = dlopen("libdlopen_common.so", RTLD_NOW);
359     ASSERT_NE(handle, nullptr);
360 
361     void* fn = dlsym(handle, "DlopenCommon");
362     ASSERT_NE(fn, nullptr);
363     Dl_info dlInfo;
364     int ret = dladdr(fn, &dlInfo);
365     EXPECT_TRUE(ret);
366     const char* fileName = "dlopen_common";
367     const char* result = strstr(dlInfo.dli_fname, fileName);
368     EXPECT_TRUE(result != nullptr);
369 
370     void* handle01 = dlopen(dlInfo.dli_fname, RTLD_NOW);
371     ASSERT_NE(handle01, nullptr);
372     EXPECT_TRUE(handle == handle01);
373 
374     dlclose(handle);
375     dlclose(handle01);
376 }
377 
378 /**
379  * @tc.name: dlopen_018
380  * @tc.desc: Test the ability to use symbolic link dlopen libraries.
381  * @tc.type: FUNC
382  */
383 HWTEST_F(LdsoDlopenTest, dlopen_018, TestSize.Level1)
384 {
385     void* handle = dlopen("libdlopen_common.so", RTLD_NOW);
386     ASSERT_NE(handle, nullptr);
387 
388     void* fn = dlsym(handle, "DlopenCommon");
389     ASSERT_NE(fn, nullptr);
390     Dl_info dlInfo;
391     int ret = dladdr(fn, &dlInfo);
392     EXPECT_TRUE(ret);
393     const char* fileName = "dlopen_common";
394     const char* result = strstr(dlInfo.dli_fname, fileName);
395     EXPECT_TRUE(result != nullptr);
396 
397     // create symlink
398     std::string path = dlInfo.dli_fname;
399     char* dir = dirname(const_cast<char*>(path.c_str()));
400     std::string dirStr = dir;
401     std::string linkPath = dirStr + "/" + "libctest_dlopen_common_link" + ".so";
402     EXPECT_TRUE(!symlink(dlInfo.dli_fname, linkPath.c_str()));
403 
404     // dlopen symlink
405     std::string linkFile = "libctest_dlopen_common_link.so";
406     void* handle01 = dlopen(linkFile.c_str(), RTLD_NOW);
407     ASSERT_NE(handle01, nullptr);
408     EXPECT_TRUE(handle == handle01);
409 
410     EXPECT_TRUE(!unlink(linkPath.c_str()));
411     dlclose(handle);
412     dlclose(handle01);
413 }
414 
415 /**
416  * @tc.name: dlopen_019
417  * @tc.desc: Test the ability to load virtual dynamic shared libraries.
418  * @tc.type: FUNC
419  */
420 HWTEST_F(LdsoDlopenTest, dlopen_019, TestSize.Level1)
421 {
422     unsigned long int result = getauxval(AT_SYSINFO_EHDR);
423     if (!result) {
424         return;
425     }
426     void* handle = dlopen("linux-gate.so.1", RTLD_NOW);
427     bool isloaded = (handle != nullptr);
428 
429     handle = dlopen("linux-vdso.so.1", RTLD_NOW);
430     isloaded |= (handle != nullptr);
431 
432     ASSERT_TRUE(isloaded);
433     dlclose(handle);
434 }
435 
436 /**
437  * @tc.name: dlopen_020
438  * @tc.desc: Test RTLD_DEFAULT searches for symbols in the default shared target search order.
439  * @tc.type: FUNC
440  */
441 HWTEST_F(LdsoDlopenTest, dlopen_020, TestSize.Level1)
442 {
443     void* handle = dlopen("libdlopen_relocation.so", RTLD_NOW);
444     ASSERT_NE(handle, nullptr);
445 
446     FuncTypeRetInt fn = reinterpret_cast<FuncTypeRetInt>(dlsym(RTLD_DEFAULT, "RelocationTest"));
447     EXPECT_TRUE(fn == nullptr);
448 
449     fn = reinterpret_cast<FuncTypeRetInt>(dlsym(handle, "RelocationTest"));
450     ASSERT_NE(fn, nullptr);
451     EXPECT_EQ(EXPECT_RETURN_VALUE_15, fn());
452 
453     dlclose(handle);
454 }
455