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