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