• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <dlfcn.h>
17 #include <gtest/gtest.h>
18 #include "log.h"
19 #include "utils.h"
20 #include "libfs.h"
21 #include "KernelConstants.h"
22 
23 using namespace testing::ext;
24 
25 class DlopenTest : public testing::Test {
26 };
27 
28 #define RES_DIR_DYLOAD RES_DIR_KERNEL "dyload/"
29 #define DYLOAD_TEST_DIR "/storage/data/"
30 
31 /**
32  * @tc.number   SUB_KERNEL_DL_SO_0100
33  * @tc.name     the elf does not depend on any user-so, dlopen a full path so
34  * @tc.desc     [C- SOFTWARE -0200]
35  */
36 HWTEST_F(DlopenTest, testDlopenFullPathSo, Function | MediumTest | Level1)
37 {
38     char* resSO = RES_DIR_DYLOAD "libdso1.so";
39     char* newSO = DYLOAD_TEST_DIR "libdso1.so";
40 
41     // test SetUp
42     ASSERT_EQ(CopyFile(resSO, newSO), 0);
43     LOG("SetUp ok");
44 
45     // test in child process
46     pid_t pid = fork();
47     ASSERT_TRUE(pid >= 0) << "======== Fork Error! =========";
48     if (pid == 0) { // child
49         LOG("newSO: %s", newSO);
50         void* h = dlopen(newSO, RTLD_NOW);
51         if (!h) {
52             PANIC("dlopen %s failed: %s\n", newSO, dlerror());
53         }
54         LOG("dlopen '%s' ok", newSO);
55         int* i = (int*) dlsym(h, "g_int");
56         if (!i) {
57             PANIC("dlsym g_int failed: %s", dlerror());
58         }
59         if (*i != 1) {
60             PANIC("so initialization failed: want i=1 got i=%d", *i);
61         }
62 
63         int (*f)(void) = (int (*)(void))dlsym(h, "inc_i");
64         if (!f) {
65             PANIC("dlsym func 'inc_i' failed: %s", dlerror());
66         }
67         f();
68         if (*i != 2) {
69             PANIC("inc_i call failed: want i=2 got i=%d", *i);
70         }
71         exit(0);
72     } else { // parent
73         Msleep(100);
74         WaitProcExitedOK(pid);
75     }
76 
77     // test TearDown
78     ASSERT_EQ(RemoveFile(newSO), 0);
79     LOG("TearDown ok ");
80 }
81 
82 /**
83  * @tc.number   SUB_KERNEL_DL_SO_0200
84  * @tc.name     the elf doesn't depend on any user-so, dlopen a relative-path so, twice
85  * @tc.desc     [C- SOFTWARE -0200]
86  */
87 HWTEST_F(DlopenTest, testDlopenRelativePathSo, Function | MediumTest | Level1)
88 {
89     char* resSO = RES_DIR_DYLOAD "libdso1.so";
90     char* testDir = DYLOAD_TEST_DIR "target";
91     char* testSo = DYLOAD_TEST_DIR "target/libdso1.so";
92     // test SetUp
93     char* curPath = GetCurrentPath();
94     ASSERT_NE(MakeDir(testDir), -1);
95     ASSERT_EQ(CopyFile(resSO, testSo), 0);
96     EXPECT_EQ(chdir(DYLOAD_TEST_DIR), 0);
97     LOG("SetUp ok");
98 
99     // test in child process, so that this load-so will not effect other test
100     pid_t pid = fork();
101     ASSERT_TRUE(pid >= 0) << "======== Fork Error! =========";
102     if (pid == 0) { // child
103         void* h = dlopen("./target/libdso1.so", RTLD_NOW);
104         if (!h) {
105             PANIC("dlopen './target/libdso1.so' failed: %s", dlerror());
106         }
107         int* i = (int*) dlsym(h, "g_int");
108         if (!i) {
109             PANIC("dlsym g_int failed: %s", dlerror());
110         }
111         if (*i != 1) {
112             PANIC("so initialization failed: want i=1 got i=%d", *i);
113         }
114         if (dlclose(h)) {
115             PANIC("dlclose failed: %s", dlerror());
116         }
117 
118         void* g = dlopen("../data/target/libdso1.so", RTLD_NOW);
119         if (!g) {
120             PANIC("dlopen so again failed: %s",  dlerror());
121         }
122         if (h != g) {
123             PANIC("dlopen same so return diff handle");
124         }
125         int (*f)(void) = (int (*)(void))dlsym(h, "inc_i");
126         if (!f) {
127             PANIC("dlsym func 'inc_i' failed: %s", dlerror());
128         }
129         f();
130         if (*i != 2) {
131             PANIC("inc_i call failed: want i=2 got i=%d", *i);
132         }
133         if (dlclose(h)) {
134             PANIC("dlclose failed: %s", dlerror());
135         }
136         LOG("Pass\n");
137         exit(0);
138     } else { // parent
139         Msleep(100);
140         WaitProcExitedOK(pid);
141     }
142 
143     // test TearDown
144     EXPECT_EQ(chdir(curPath), 0);
145     ASSERT_EQ(RemoveFile(testSo), 0);
146     LOG("TearDown ok ");
147 }
148 
149 /**
150  * @tc.number   SUB_KERNEL_DL_SO_0400
151  * @tc.name     the elf doesn't depend on any user-so. dlopen a not exist so.
152  * @tc.desc     [C- SOFTWARE -0200]
153  */
154 HWTEST_F(DlopenTest, testDlopenNotExistSo, Function | MediumTest | Level3)
155 {
156     dlerror(); // clear any old error message
157     char* errMsg = dlerror();
158     if (errMsg) {
159         LOG("dlerror should return NULL when called twice.");
160         FAIL();
161     }
162 
163     void* h = dlopen("not_exist_dso1.so", RTLD_NOW);
164     if (h) {
165         LOG("dlopen a non-exist-so should return NULL!");
166         FAIL();
167     }
168     errMsg = dlerror();
169     if (!errMsg) {
170         LOG("dlerror return NULL!");
171         FAIL();
172     }
173     char* p = strcasestr(errMsg, "No such file");
174     if (!p) {
175         LOG("dlerror msg invalid, should include 'No such file', actual msg=%s", errMsg);
176         FAIL();
177     }
178 }
179 
180 /**
181  * @tc.number   SUB_KERNEL_DL_SO_0500
182  * @tc.name     the elf doesn't depend on any user-so, and dlopen continuously loads a same so
183  * @tc.desc     [C- SOFTWARE -0200]
184  */
185 HWTEST_F(DlopenTest, testDlopenSameSo, Function | MediumTest | Level2)
186 {
187     char* resSO = RES_DIR_DYLOAD "libdso1.so";
188     char* newSO = DYLOAD_TEST_DIR "libdso1.so";
189 
190     // test SetUp
191     ASSERT_EQ(CopyFile(resSO, newSO), 0);
192     LOG("SetUp ok");
193 
194     // test in child process
195     pid_t pid = fork();
196     ASSERT_TRUE(pid >= 0) << "======== Fork Error! =========";
197     if (pid == 0) { // child
198         void* h1 = dlopen(newSO, RTLD_NOW);
199         if (!h1) {
200             PANIC("dlopen %s failed: %s\n", newSO, dlerror());
201         }
202         void* h2 = dlopen(newSO, RTLD_NOW);
203         if (!h2) {
204             PANIC("dlopen %s failed: %s\n", newSO, dlerror());
205         }
206         if (h1 != h2) {
207             PANIC("dlopen same so return diff handle");
208         }
209         if (dlclose(h1)) {
210             PANIC("dlclose failed: %s", dlerror());
211         }
212         if (dlclose(h2)) {
213             PANIC("dlclose second handle failed: %s", dlerror());
214         }
215         exit(0);
216     } else { // parent
217         Msleep(100);
218         WaitProcExitedOK(pid);
219     }
220 
221     // test TearDown
222     ASSERT_EQ(RemoveFile(newSO), 0);
223     LOG("TearDown ok ");
224 }
225 
226 /**
227  * @tc.number   SUB_KERNEL_DL_SO_0800
228  * @tc.name     The tested elf depends on full-rpath so, and test same-symbol behaviour.
229  *              and three so's have a same symbol
230  * @tc.desc     [C- SOFTWARE -0200]
231  */
232 HWTEST_F(DlopenTest, testDlopenSameSymbolSo, Function | MediumTest | Level2)
233 {
234     char* testELF = RES_DIR_DYLOAD "dyload_rpath_full";
235     char* resSO1  = RES_DIR_DYLOAD "libdso1.so";
236     char* resSO2  = RES_DIR_DYLOAD "libdso2.so";
237     char* resSO3  = RES_DIR_DYLOAD "libdso3.so";
238     char* newSO1 = DYLOAD_TEST_DIR "libdso1.so";
239     char* newSO2 = DYLOAD_TEST_DIR "libdso2.so";
240     char* newSO3 = DYLOAD_TEST_DIR "libdso3.so";
241 
242     // test SetUp
243     EXPECT_EQ(CopyFile(resSO1, newSO1), 0);
244     EXPECT_EQ(CopyFile(resSO2, newSO2), 0);
245     EXPECT_EQ(CopyFile(resSO3, newSO3), 0);
246     LOG("SetUp ok");
247 
248     // test
249     int rt = RunElf(testELF, NULL, NULL);
250     EXPECT_EQ(rt, 0) << "same-symbol test failed! exitcode=" << rt;
251 
252     // test TearDown
253     EXPECT_EQ(RemoveFile(newSO1), 0);
254     EXPECT_EQ(RemoveFile(newSO2), 0);
255     EXPECT_EQ(RemoveFile(newSO3), 0);
256     LOG("TearDown ok ");
257 }
258 
259 /**
260  * @tc.number   SUB_KERNEL_DL_SO_1000
261  * @tc.name     the test elf compiled with rpath, and the depended-so is in that path
262  * @tc.desc     [C- SOFTWARE -0200]
263  */
264 HWTEST_F(DlopenTest, testDlopenSoInRelativeRpath, Function | MediumTest | Level2)
265 {
266     char* testELF = RES_DIR_DYLOAD "dyload_rpath_relative";
267     char* resSO = RES_DIR_DYLOAD "libdso1.so";
268     char* newSO = "./lib/libdso1.so";
269 
270     // test SetUp
271     ASSERT_NE(MakeDir("./lib"), -1);
272     ASSERT_EQ(CopyFile(resSO, newSO), 0);
273     LOG("SetUp ok");
274     Msleep(5000);
275 
276     // test
277     int rt = RunElf(testELF, NULL, NULL);
278     EXPECT_EQ(rt, 0) << "dyload_rpath_relative failed! exitcode=" << rt;
279 
280     // test TearDown
281     ASSERT_EQ(RemoveFile(newSO), 0);
282     LOG("TearDown ok ");
283 }
284 
285