1 /* 2 * Copyright (c) 2022-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 16 #include <gtest/gtest.h> 17 #include <ctime> 18 #include <securec.h> 19 #include <string> 20 #include <vector> 21 #include <iostream> 22 #include "dfx_elf.h" 23 #include "elf_imitate.h" 24 #include "elf_factory.h" 25 #include "unwinder_config.h" 26 27 using namespace OHOS::HiviewDFX; 28 using namespace testing::ext; 29 using namespace std; 30 31 #define ELF32_FILE "/data/test/resource/testdata/elf32_test" 32 #define ELF64_FILE "/data/test/resource/testdata/elf_test" 33 #define DUMPCATCHER_ELF_FILE "/system/bin/dumpcatcher" 34 #define PT_LOAD_OFFSET 0x001000 35 #define PT_LOAD_OFFSET64 0x0000000000002000 36 37 namespace OHOS { 38 namespace HiviewDFX { 39 class DfxElfTest : public testing::Test { 40 public: SetUpTestCase(void)41 static void SetUpTestCase(void) {} TearDownTestCase(void)42 static void TearDownTestCase(void) {} SetUp()43 void SetUp() {} TearDown()44 void TearDown() {} 45 }; 46 47 std::vector<std::string> interestedSections = { ".dynsym", ".eh_frame_hdr", ".eh_frame", ".symtab" }; 48 /** 49 * @tc.name: DfxElfTest001 50 * @tc.desc: test DfxElf functions with 32 bit ELF 51 * @tc.type: FUNC 52 */ 53 HWTEST_F(DfxElfTest, DfxElfTest001, TestSize.Level2) 54 { 55 GTEST_LOG_(INFO) << "DfxElfTest001: start."; 56 RegularElfFactory factory(ELF32_FILE); 57 auto elf = factory.Create(); 58 ASSERT_TRUE(elf != nullptr); 59 ElfImitate elfImitate; 60 ShdrInfo shdr; 61 ShdrInfo shdrImitate; 62 bool ret = elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF32); 63 ASSERT_TRUE(ret); 64 for (size_t i = 0; i < interestedSections.size(); i++) { 65 elf->GetSectionInfo(shdr, interestedSections[i]); 66 elfImitate.GetSectionInfo(shdrImitate, interestedSections[i]); 67 GTEST_LOG_(INFO) << interestedSections[i]; 68 ASSERT_EQ(shdr.addr, shdrImitate.addr); 69 ASSERT_EQ(shdr.offset, shdrImitate.offset); 70 ASSERT_EQ(shdr.size, shdrImitate.size); 71 std::vector<uint8_t> sectionBuffer(shdr.size); 72 ASSERT_TRUE(elf->GetSectionData(sectionBuffer.data(), shdr.size, interestedSections[i])); 73 } 74 ASSERT_EQ(elf->GetArchType(), elfImitate.GetArchType()); 75 ASSERT_EQ(elf->GetElfSize(), elfImitate.GetElfSize()); 76 ASSERT_EQ(elf->GetLoadBias(), elfImitate.GetLoadBias()); 77 78 auto load = elf->GetPtLoads(); 79 auto loadImitate = elfImitate.GetPtLoads(); 80 ASSERT_EQ(load[PT_LOAD_OFFSET].offset, loadImitate[PT_LOAD_OFFSET].offset); 81 ASSERT_EQ(load[PT_LOAD_OFFSET].tableSize, loadImitate[PT_LOAD_OFFSET].tableSize); 82 ASSERT_EQ(load[PT_LOAD_OFFSET].tableVaddr, loadImitate[PT_LOAD_OFFSET].tableVaddr); 83 84 ASSERT_EQ(elf->GetClassType(), elfImitate.GetClassType()); 85 ASSERT_EQ(elf->GetLoadBase(0xf78c0000, 0), elfImitate.GetLoadBase(0xf78c0000, 0)); 86 ASSERT_EQ(elf->GetStartPc(), elfImitate.GetStartPc()); 87 ASSERT_EQ(elf->GetEndPc(), elfImitate.GetEndPc()); 88 ASSERT_EQ(elf->GetRelPc(0xf78c00f0, 0xf78c0000, 0), elfImitate.GetRelPc(0xf78c00f0, 0xf78c0000, 0)); 89 ASSERT_EQ(elf->GetBuildId(), "8e5a30338be326934ff93c998dcd0d22fe345870"); 90 EXPECT_NE(elf->GetGlobalPointer(), 0); 91 EXPECT_FALSE(elf->GetFuncSymbols().empty()); 92 EXPECT_GT(elf->GetMmapSize(), 0); 93 GTEST_LOG_(INFO) << elf->GetElfName(); 94 GTEST_LOG_(INFO) << "DfxElfTest001: end."; 95 } 96 97 /** 98 * @tc.name: DfxElfTest002 99 * @tc.desc: test DfxElf functions with 64 bit ELF 100 * @tc.type: FUNC 101 */ 102 HWTEST_F(DfxElfTest, DfxElfTest002, TestSize.Level2) 103 { 104 GTEST_LOG_(INFO) << "DfxElfTest002: start."; 105 RegularElfFactory factory(ELF64_FILE); 106 auto elf = factory.Create(); 107 ASSERT_TRUE(elf != nullptr); 108 ElfImitate elfImitate; 109 ShdrInfo shdr; 110 ShdrInfo shdrImitate; 111 bool ret = elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF64); 112 ASSERT_TRUE(ret); 113 for (size_t i = 0; i < interestedSections.size(); i++) { 114 GTEST_LOG_(INFO) << interestedSections[i]; 115 elf->GetSectionInfo(shdr, interestedSections[i]); 116 elfImitate.GetSectionInfo(shdrImitate, interestedSections[i]); 117 ASSERT_EQ(shdr.addr, shdrImitate.addr); 118 ASSERT_EQ(shdr.offset, shdrImitate.offset); 119 ASSERT_EQ(shdr.size, shdrImitate.size); 120 std::vector<uint8_t> sectionBuffer(shdr.size); 121 ASSERT_TRUE(elf->GetSectionData(sectionBuffer.data(), shdr.size, interestedSections[i])); 122 ASSERT_FALSE(elf->GetSectionData(sectionBuffer.data(), shdr.size, "invalid section name")); 123 } 124 ASSERT_EQ(elf->GetArchType(), elfImitate.GetArchType()); 125 ASSERT_EQ(elf->GetElfSize(), elfImitate.GetElfSize()); 126 ASSERT_EQ(elf->GetLoadBias(), elfImitate.GetLoadBias()); 127 128 auto load = elf->GetPtLoads(); 129 auto loadImitate = elfImitate.GetPtLoads(); 130 ASSERT_EQ(load[PT_LOAD_OFFSET64].offset, loadImitate[PT_LOAD_OFFSET64].offset); 131 ASSERT_EQ(load[PT_LOAD_OFFSET64].tableSize, loadImitate[PT_LOAD_OFFSET64].tableSize); 132 ASSERT_EQ(load[PT_LOAD_OFFSET64].tableVaddr, loadImitate[PT_LOAD_OFFSET64].tableVaddr); 133 134 ASSERT_EQ(elf->GetClassType(), elfImitate.GetClassType()); 135 ASSERT_EQ(elf->GetLoadBase(0xf78c0000, 0), elfImitate.GetLoadBase(0xf78c0000, 0)); 136 ASSERT_EQ(elf->GetStartPc(), elfImitate.GetStartPc()); 137 ASSERT_EQ(elf->GetEndPc(), elfImitate.GetEndPc()); 138 ASSERT_EQ(elf->GetRelPc(0xf78c00f0, 0xf78c0000, 0), elfImitate.GetRelPc(0xf78c00f0, 0xf78c0000, 0)); 139 ASSERT_EQ(elf->GetBuildId(), "24c55dccc5baaaa140da0083207abcb8d523e248"); 140 EXPECT_NE(elf->GetGlobalPointer(), 0); 141 EXPECT_FALSE(elf->GetFuncSymbols().empty()); 142 EXPECT_GT(elf->GetMmapSize(), 0); 143 GTEST_LOG_(INFO) << elf->GetElfName(); 144 GTEST_LOG_(INFO) << "DfxElfTest002: end."; 145 } 146 147 /** 148 * @tc.name: DfxElfTest003 149 * @tc.desc: test DfxElf functions with using error 150 * @tc.type: FUNC 151 */ 152 HWTEST_F(DfxElfTest, DfxElfTest003, TestSize.Level2) 153 { 154 GTEST_LOG_(INFO) << "DfxElfTest003: start."; 155 DfxElf elf(nullptr); 156 ASSERT_FALSE(elf.IsValid()); 157 ASSERT_EQ(elf.GetClassType(), ELFCLASSNONE); 158 ASSERT_EQ(elf.GetElfSize(), 0); 159 ASSERT_TRUE(elf.GetBuildId().empty()); 160 EXPECT_EQ(elf.GetGlobalPointer(), 0); 161 ShdrInfo shdrInfo; 162 EXPECT_FALSE(elf.GetSectionInfo(shdrInfo, "")); 163 EXPECT_EQ(elf.GetMmapSize(), 0); 164 GTEST_LOG_(INFO) << "DfxElfTest003: end."; 165 } 166 167 #if !is_emulator 168 /** 169 * @tc.name: DfxElfTest004 170 * @tc.desc: test DfxElf class functions with minidebugInfo 171 * @tc.type: FUNC 172 */ 173 HWTEST_F(DfxElfTest, DfxElfTest004, TestSize.Level2) 174 { 175 GTEST_LOG_(INFO) << "DfxElfTest004: start."; 176 UnwinderConfig::SetEnableMiniDebugInfo(true); 177 RegularElfFactory factory(DUMPCATCHER_ELF_FILE); 178 auto elf = factory.Create(); 179 ASSERT_TRUE(elf->IsValid()); 180 auto symbols = elf->GetFuncSymbols(); 181 GTEST_LOG_(INFO) << "DfxElfTest004: symbols1 size:" << symbols.size(); 182 183 UnwinderConfig::SetEnableMiniDebugInfo(false); 184 auto regularElf = factory.Create(); 185 ASSERT_TRUE(regularElf->IsValid()); 186 auto regularSymbols = regularElf->GetFuncSymbols(); 187 GTEST_LOG_(INFO) << "DfxElfTest004: symbols2 size:" << regularSymbols.size(); 188 ASSERT_GE(regularSymbols.size(), 0); 189 ASSERT_GE(symbols.size(), regularSymbols.size()); 190 GTEST_LOG_(INFO) << "DfxElfTest004: end."; 191 } 192 #endif 193 194 /** 195 * @tc.name: DfxElfTest005 196 * @tc.desc: test GetBuildId function when input empty elf file path 197 * @tc.type: FUNC 198 */ 199 HWTEST_F(DfxElfTest, DfxElfTest005, TestSize.Level2) 200 { 201 auto elfFile = std::make_shared<DfxElf>(nullptr); 202 ASSERT_NE(elfFile, nullptr); 203 EXPECT_STREQ(elfFile->GetBuildId().c_str(), ""); 204 } 205 206 /** 207 * @tc.name: DfxElfTest006 208 * @tc.desc: test SetBaseOffset function and GetBaseOffset function 209 * @tc.type: FUNC 210 */ 211 HWTEST_F(DfxElfTest, DfxElfTest006, TestSize.Level2) 212 { 213 auto elf = std::make_shared<DfxElf>(nullptr); 214 ASSERT_EQ(elf->GetBaseOffset(), 0); 215 elf->SetBaseOffset(1); 216 ASSERT_EQ(elf->GetBaseOffset(), 1); 217 } 218 219 /** 220 * @tc.name: DfxElfTest007 221 * @tc.desc: test DfxMmap abnormal case 222 * @tc.type: FUNC 223 */ 224 HWTEST_F(DfxElfTest, DfxElfTest007, TestSize.Level2) 225 { 226 auto mMap = std::make_shared<DfxMmap>(); 227 ASSERT_FALSE(mMap->Init(-1, 0U, 0)); 228 uintptr_t invalidAddr = 0; 229 ASSERT_EQ(mMap->Read(invalidAddr, nullptr, 0U, true), 0); 230 } 231 232 /** 233 * @tc.name: DfxElfTest008 234 * @tc.desc: test scenario function 235 * @tc.type: FUNC 236 */ 237 HWTEST_F(DfxElfTest, DfxElfTest008, TestSize.Level2) 238 { 239 auto elfParse = std::unique_ptr<ElfParser>(std::make_unique<ElfParser32>(nullptr)); 240 std::string str = ""; 241 elfParse->GetSectionNameByIndex(str, 0); 242 elfParse->sectionNames_ = "test"; 243 const size_t num = 10; 244 elfParse->GetSectionNameByIndex(str, num); 245 unsigned char buf[num] = {0}; 246 elfParse->GetSectionData(buf, num, str); 247 std::string buildId = elfParse->ToReadableBuildId(str); 248 elfParse->GetElfName(); 249 uint64_t addr = 0; 250 ElfSymbol elfSymbol; 251 elfParse->GetFuncSymbolByAddr(addr, elfSymbol); 252 ASSERT_EQ(buildId, ""); 253 } 254 255 /** 256 * @tc.name: DfxElfTest009 257 * @tc.desc: test scenario function 258 * @tc.type: FUNC 259 */ 260 HWTEST_F(DfxElfTest, DfxElfTest009, TestSize.Level2) 261 { 262 auto elf = std::make_shared<DfxElf>(nullptr); 263 elf->GetEndVaddr(); 264 std::string buildId = "test"; 265 elf->SetBuildId(buildId); 266 const size_t num = 10; 267 unsigned char buf[num] = {0}; 268 elf->GetSectionData(buf, num, ""); 269 struct UnwindTableInfo uti; 270 ShdrInfo shdr; 271 bool cur = elf->FillUnwindTableByExidx(shdr, 0, nullptr); 272 ASSERT_FALSE(cur); 273 cur = elf->FillUnwindTableByExidx(shdr, 0, &uti); 274 ASSERT_TRUE(cur); 275 } 276 277 /** 278 * @tc.name: DfxElfTest010 279 * @tc.desc: test scenario function 280 * @tc.type: FUNC 281 */ 282 HWTEST_F(DfxElfTest, DfxElfTest010, TestSize.Level2) 283 { 284 auto elf = std::make_shared<DfxElf>(nullptr); 285 struct dl_phdr_info info; 286 int cur = elf->DlPhdrCb(nullptr, 0, nullptr); 287 ASSERT_EQ(cur, -1); 288 cur = elf->DlPhdrCb(&info, 0, nullptr); 289 ASSERT_EQ(cur, -1); 290 elf->GetMmapPtr(); 291 bool isvalid = elf->IsValidElf(nullptr, 0); 292 ASSERT_FALSE(isvalid); 293 } 294 } // namespace HiviewDFX 295 } // namespace OHOS 296 297