• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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