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