1 /* 2 * Copyright (c) 2025 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 #include <gtest/gtest.h> 16 17 #include <cstdio> 18 #include <dlfcn.h> 19 #include <cstdint> 20 21 #include "dfx_maps.h" 22 #include "dfx_symbols.h" 23 #include "dfx_test_util.h" 24 #include "elf_factory_selector.h" 25 #include "unwinder_config.h" 26 27 using namespace testing; 28 using namespace testing::ext; 29 using namespace std; 30 31 namespace OHOS { 32 namespace HiviewDFX { 33 namespace { 34 constexpr const char* const DUMPCATCHER_ELF_FILE = "/system/bin/dumpcatcher"; 35 } 36 class ElfFactoryTest : public testing::Test { 37 public: SetUpTestCase()38 static void SetUpTestCase() {} TearDownTestCase()39 static void TearDownTestCase() {} SetUp()40 void SetUp() {} TearDown()41 void TearDown() {} 42 }; 43 44 /** 45 * @tc.name: ElfFactoryTest001 46 * @tc.desc: test VdsoElfFactory normal case 47 * @tc.type: FUNC 48 */ 49 HWTEST_F(ElfFactoryTest, ElfFactoryTest001, TestSize.Level2) 50 { 51 GTEST_LOG_(INFO) << "ElfFactoryTest001: start."; 52 std::string res = ExecuteCommands("uname"); 53 bool linuxKernel = res.find("Linux") != std::string::npos; 54 if (linuxKernel) { 55 ASSERT_TRUE(linuxKernel); 56 } else { 57 pid_t pid = GetProcessPid(FOUNDATION_NAME); 58 auto maps = DfxMaps::Create(pid); 59 std::vector<std::shared_ptr<DfxMap>> shmmMaps; 60 ASSERT_TRUE(maps->FindMapsByName("[shmm]", shmmMaps)); 61 std::shared_ptr<DfxMap> shmmMap = nullptr; 62 for (auto map : shmmMaps) { 63 if (map->IsMapExec()) { 64 shmmMap = map; 65 break; 66 } 67 } 68 ASSERT_TRUE(shmmMap != nullptr); 69 VdsoElfFactory factory(shmmMap->begin, shmmMap->end - shmmMap->begin, pid); 70 auto shmmElf = factory.Create(); 71 ASSERT_TRUE(shmmElf != nullptr); 72 std::vector<DfxSymbol> shmmSyms; 73 DfxSymbols::ParseSymbols(shmmSyms, shmmElf, ""); 74 GTEST_LOG_(INFO) << "shmm symbols size" << shmmSyms.size(); 75 ASSERT_GT(shmmSyms.size(), 0); 76 for (const auto& sym : shmmSyms) { 77 GTEST_LOG_(INFO) << sym.ToDebugString(); 78 } 79 GTEST_LOG_(INFO) << "ElfFactoryTest001 : end."; 80 } 81 } 82 83 /** 84 * @tc.name: ElfFactoryTest002 85 * @tc.desc: test VdsoElfFactory using not vdso exec map case 86 * @tc.type: FUNC 87 */ 88 HWTEST_F(ElfFactoryTest, ElfFactoryTest002, TestSize.Level2) 89 { 90 GTEST_LOG_(INFO) << "ElfFactoryTest002: start."; 91 pid_t pid = GetProcessPid(FOUNDATION_NAME); 92 auto dfxMaps = DfxMaps::Create(pid); 93 std::vector<std::shared_ptr<DfxMap>> maps; 94 ASSERT_TRUE(dfxMaps->FindMapsByName("libunwinder.z.so", maps)); 95 for (const auto& map : maps) { 96 if (map->IsMapExec()) { 97 VdsoElfFactory factory(map->begin, map->end - map->begin, pid); 98 auto elf = factory.Create(); 99 ASSERT_TRUE(elf == nullptr); 100 break; 101 } 102 } 103 GTEST_LOG_(INFO) << "ElfFactoryTest002 : end."; 104 } 105 106 /** 107 * @tc.name: ElfFactoryTest003 108 * @tc.desc: test VdsoElfFactory using abnormal param 109 * @tc.type: FUNC 110 */ 111 HWTEST_F(ElfFactoryTest, ElfFactoryTest003, TestSize.Level2) 112 { 113 GTEST_LOG_(INFO) << "ElfFactoryTest003: start."; 114 uint64_t begin = 0; 115 size_t size = 0; 116 pid_t pid = 0; 117 VdsoElfFactory factory(begin, size, pid); 118 auto elf = factory.Create(); 119 ASSERT_TRUE(elf == nullptr); 120 GTEST_LOG_(INFO) << "ElfFactoryTest003 : end."; 121 } 122 123 #ifndef __x86_64__ 124 /** 125 * @tc.name: ElfFactoryTest004 126 * @tc.desc: test MiniDebugInfoFactory normal case 127 * @tc.type: FUNC 128 */ 129 HWTEST_F(ElfFactoryTest, ElfFactoryTest004, TestSize.Level2) 130 { 131 GTEST_LOG_(INFO) << "ElfFactoryTest004: start."; 132 UnwinderConfig::SetEnableMiniDebugInfo(true); 133 RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE); 134 auto elf = regularElfFactory.Create(); 135 ASSERT_TRUE(elf->IsValid()); 136 auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr(); 137 ASSERT_TRUE(gnuDebugDataHdr.size != 0); 138 MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr); 139 elf = miniDebugInfoFactory.Create(); 140 ASSERT_TRUE(elf->IsValid()); 141 GTEST_LOG_(INFO) << "ElfFactoryTest004: end."; 142 } 143 144 /** 145 * @tc.name: ElfFactoryTest005 146 * @tc.desc: test MiniDebugInfoFactory normal case with test parsing symbol 147 * @tc.type: FUNC 148 */ 149 HWTEST_F(ElfFactoryTest, ElfFactoryTest005, TestSize.Level2) 150 { 151 GTEST_LOG_(INFO) << "ElfFactoryTest005: start."; 152 UnwinderConfig::SetEnableMiniDebugInfo(true); 153 RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE); 154 auto elf = regularElfFactory.Create(); 155 ASSERT_TRUE(elf->IsValid()); 156 auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr(); 157 ASSERT_TRUE(gnuDebugDataHdr.size != 0); 158 MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr); 159 elf = miniDebugInfoFactory.Create(); 160 ASSERT_TRUE(elf->IsValid()); 161 std::vector<DfxSymbol> symbols; 162 DfxSymbols::ParseSymbols(symbols, elf, ""); 163 GTEST_LOG_(INFO) << "symbols size" << symbols.size(); 164 ASSERT_GT(symbols.size(), 0); 165 for (const auto& symbol : symbols) { 166 GTEST_LOG_(INFO) << symbol.ToDebugString(); 167 } 168 GTEST_LOG_(INFO) << "ElfFactoryTest005: end."; 169 } 170 171 /** 172 * @tc.name: ElfFactoryTest006 173 * @tc.desc: test MiniDebugInfoFactory disable minidebuginfo case 174 * @tc.type: FUNC 175 */ 176 HWTEST_F(ElfFactoryTest, ElfFactoryTest006, TestSize.Level2) 177 { 178 GTEST_LOG_(INFO) << "ElfFactoryTest006: start."; 179 UnwinderConfig::SetEnableMiniDebugInfo(false); 180 RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE); 181 auto elf = regularElfFactory.Create(); 182 ASSERT_TRUE(elf->IsValid()); 183 auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr(); 184 ASSERT_TRUE(gnuDebugDataHdr.size != 0); 185 MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr); 186 elf = miniDebugInfoFactory.Create(); 187 ASSERT_TRUE(elf == nullptr); 188 GTEST_LOG_(INFO) << "ElfFactoryTest006: end."; 189 } 190 191 /** 192 * @tc.name: ElfFactoryTest007 193 * @tc.desc: test MiniDebugInfoFactory using abnormal param 194 * @tc.type: FUNC 195 */ 196 HWTEST_F(ElfFactoryTest, ElfFactoryTest007, TestSize.Level2) 197 { 198 GTEST_LOG_(INFO) << "ElfFactoryTest007: start."; 199 UnwinderConfig::SetEnableMiniDebugInfo(true); 200 GnuDebugDataHdr hdr; 201 MiniDebugInfoFactory miniDebugInfoFactory(hdr); 202 auto elf = miniDebugInfoFactory.Create(); 203 ASSERT_TRUE(elf == nullptr); 204 GTEST_LOG_(INFO) << "ElfFactoryTest007: end."; 205 } 206 207 /** 208 * @tc.name: ElfFactoryTest008 209 * @tc.desc: test MiniDebugInfoFactory using abnormal param 210 * @tc.type: FUNC 211 */ 212 HWTEST_F(ElfFactoryTest, ElfFactoryTest008, TestSize.Level2) 213 { 214 GTEST_LOG_(INFO) << "ElfFactoryTest008: start."; 215 UnwinderConfig::SetEnableMiniDebugInfo(false); 216 GnuDebugDataHdr hdr; 217 MiniDebugInfoFactory miniDebugInfoFactory(hdr); 218 auto elf = miniDebugInfoFactory.Create(); 219 ASSERT_TRUE(elf == nullptr); 220 GTEST_LOG_(INFO) << "ElfFactoryTest008: end."; 221 } 222 #endif 223 224 /** 225 * @tc.name: ElfFactoryTest009 226 * @tc.desc: test ElfFactoryTest with 64 bit ELF 227 * @tc.type: FUNC 228 */ 229 HWTEST_F(ElfFactoryTest, ElfFactoryTest009, TestSize.Level2) 230 { 231 GTEST_LOG_(INFO) << "ElfFactoryTest009: start."; 232 const char* elf64File = "/data/test/resource/testdata/elf_test"; 233 RegularElfFactory factory(elf64File); 234 auto elf = factory.Create(); 235 ASSERT_TRUE(elf->IsValid()); 236 GTEST_LOG_(INFO) << "ElfFactoryTest009: end."; 237 } 238 239 /** 240 * @tc.name: ElfFactoryTest010 241 * @tc.desc: ElfFactoryTest with 32 bit ELF 242 * @tc.type: FUNC 243 */ 244 HWTEST_F(ElfFactoryTest, ElfFactoryTest010, TestSize.Level2) 245 { 246 GTEST_LOG_(INFO) << "ElfFactoryTest010: start."; 247 const char* elf32File = "/data/test/resource/testdata/elf32_test"; 248 RegularElfFactory factory(elf32File); 249 auto elf = factory.Create(); 250 ASSERT_TRUE(elf->IsValid()); 251 GTEST_LOG_(INFO) << "ElfFactoryTest010: end."; 252 } 253 254 /** 255 * @tc.name: ElfFactoryTest011 256 * @tc.desc: test DfxElf functions with empty file path 257 * @tc.type: FUNC 258 */ 259 HWTEST_F(ElfFactoryTest, ElfFactoryTest011, TestSize.Level2) 260 { 261 GTEST_LOG_(INFO) << "ElfFactoryTest002: start."; 262 std::string filePath = ""; 263 RegularElfFactory factory(filePath); 264 auto elf = factory.Create(); 265 ASSERT_FALSE(elf->IsValid()); 266 GTEST_LOG_(INFO) << "ElfFactoryTest011: end."; 267 } 268 269 /** 270 * @tc.name: ElfFactoryTest012 271 * @tc.desc: test DfxElf functions with invalid filePath 272 * @tc.type: FUNC 273 */ 274 HWTEST_F(ElfFactoryTest, ElfFactoryTest012, TestSize.Level2) 275 { 276 GTEST_LOG_(INFO) << "ElfFactoryTest012: start."; 277 std::string filePath = "[anno:stack:2345]"; 278 RegularElfFactory factory(filePath); 279 auto elf = factory.Create(); 280 ASSERT_FALSE(elf->IsValid()); 281 GTEST_LOG_(INFO) << "ElfFactoryTest012: end."; 282 } 283 284 /** 285 * @tc.name: ElfFactoryTest013 286 * @tc.desc: ElfFactorySelector in normal case 287 * @tc.type: FUNC 288 */ 289 HWTEST_F(ElfFactoryTest, ElfFactoryTest013, TestSize.Level2) 290 { 291 GTEST_LOG_(INFO) << "ElfFactoryTest013: start."; 292 pid_t pid = GetProcessPid(FOUNDATION_NAME); 293 auto dfxMaps = DfxMaps::Create(pid); 294 auto maps = dfxMaps->GetMaps(); 295 for (const auto& map : maps) { 296 auto elfFactory = ElfFactorySelector::Select(*(map.get()), pid); 297 auto elf = elfFactory->Create(); 298 if (map->IsVdsoMap()) { 299 ASSERT_TRUE(elf->IsValid()); 300 GTEST_LOG_(INFO) << elf->GetElfName(); 301 ASSERT_TRUE(elf->GetElfName().find("shmm") != std::string::npos || 302 elf->GetElfName().find("vdso") != std::string::npos); 303 } else if (DfxMaps::IsLegalMapItem(map->name) && map->IsMapExec()) { 304 ASSERT_TRUE(elf->IsValid()) << map->name; 305 } 306 } 307 GTEST_LOG_(INFO) << "ElfFactoryTest013: end."; 308 } 309 310 /** 311 * @tc.name: ElfFactoryTest014 312 * @tc.desc: ElfFactorySelector using abnormal param 313 * @tc.type: FUNC 314 */ 315 HWTEST_F(ElfFactoryTest, ElfFactoryTest014, TestSize.Level2) 316 { 317 GTEST_LOG_(INFO) << "ElfFactoryTest014: start."; 318 DfxMap map; 319 auto elfFactory = ElfFactorySelector::Select(map); 320 auto elf = elfFactory->Create(); 321 ASSERT_FALSE(elf->IsValid()); 322 323 map.begin = 0xc38a6000; 324 map.end = 0xc39450000; 325 map.offset = 0x1d9000; 326 map.prots |= PROT_READ; 327 map.prots |= PROT_EXEC; 328 map.name = "/proc/data/storage/el1/bundle/entry.hap"; // invalid path 329 auto prevMap = std::make_shared<DfxMap>(); 330 prevMap->begin = 0xc3840000; 331 prevMap->end = 0xc38a6000; 332 prevMap->offset = 0x174000; 333 prevMap->prots |= PROT_READ; 334 prevMap->name = "/proc/data/storage/el1/bundle/entry.hap"; // invalid path 335 map.prevMap = prevMap; 336 elfFactory = ElfFactorySelector::Select(map); 337 elf = elfFactory->Create(); 338 ASSERT_EQ(elf, nullptr); 339 GTEST_LOG_(INFO) << "ElfFactoryTest014: end."; 340 } 341 } 342 }