1 /*
2  * Copyright (c) 2022 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 "unwinder_config.h"
25 
26 using namespace OHOS::HiviewDFX;
27 using namespace testing::ext;
28 using namespace std;
29 
30 #define ELF32_FILE "/data/test/resource/testdata/elf32_test"
31 #define ELF64_FILE "/data/test/resource/testdata/elf_test"
32 #define DUMPCATCHER_ELF_FILE "/system/bin/dumpcatcher"
33 #define PT_LOAD_OFFSET 0x001000
34 #define PT_LOAD_OFFSET64 0x0000000000002000
35 
36 namespace OHOS {
37 namespace HiviewDFX {
38 class DfxElfTest : public testing::Test {
39 public:
SetUpTestCase(void)40     static void SetUpTestCase(void) {}
TearDownTestCase(void)41     static void TearDownTestCase(void) {}
SetUp()42     void SetUp() {}
TearDown()43     void TearDown() {}
44 };
45 
46 std::vector<std::string> interestedSections = { ".dynsym", ".eh_frame_hdr", ".eh_frame", ".symtab" };
47  /**
48  * @tc.name: DfxElfTest001
49  * @tc.desc: test DfxElf functions with 32 bit ELF
50  * @tc.type: FUNC
51  */
52 HWTEST_F(DfxElfTest, DfxElfTest001, TestSize.Level2)
53 {
54     GTEST_LOG_(INFO) << "DfxElfTest001: start.";
55     DfxElf elf(ELF32_FILE);
56     ASSERT_TRUE(elf.IsValid());
57     ElfImitate elfImitate;
58     ShdrInfo shdr;
59     ShdrInfo shdrImitate;
60     bool ret = elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF32);
61     ASSERT_TRUE(ret);
62     for (size_t i = 0; i < interestedSections.size(); i++) {
63         elf.GetSectionInfo(shdr, interestedSections[i]);
64         elfImitate.GetSectionInfo(shdrImitate, interestedSections[i]);
65         GTEST_LOG_(INFO) << interestedSections[i];
66         ASSERT_EQ(shdr.addr, shdrImitate.addr);
67         ASSERT_EQ(shdr.offset, shdrImitate.offset);
68         ASSERT_EQ(shdr.size, shdrImitate.size);
69     }
70     ASSERT_EQ(elf.GetArchType(), elfImitate.GetArchType());
71     ASSERT_EQ(elf.GetElfSize(), elfImitate.GetElfSize());
72     ASSERT_EQ(elf.GetLoadBias(), elfImitate.GetLoadBias());
73 
74     auto load = elf.GetPtLoads();
75     auto loadImitate = elfImitate.GetPtLoads();
76     ASSERT_EQ(load[PT_LOAD_OFFSET].offset, loadImitate[PT_LOAD_OFFSET].offset);
77     ASSERT_EQ(load[PT_LOAD_OFFSET].tableSize, loadImitate[PT_LOAD_OFFSET].tableSize);
78     ASSERT_EQ(load[PT_LOAD_OFFSET].tableVaddr, loadImitate[PT_LOAD_OFFSET].tableVaddr);
79 
80     ASSERT_EQ(elf.GetClassType(), elfImitate.GetClassType());
81     ASSERT_EQ(elf.GetLoadBase(0xf78c0000, 0), elfImitate.GetLoadBase(0xf78c0000, 0));
82     ASSERT_EQ(elf.GetStartPc(), elfImitate.GetStartPc());
83     ASSERT_EQ(elf.GetEndPc(), elfImitate.GetEndPc());
84     ASSERT_EQ(elf.GetRelPc(0xf78c00f0, 0xf78c0000, 0), elfImitate.GetRelPc(0xf78c00f0, 0xf78c0000, 0));
85     ASSERT_EQ(elf.GetBuildId(), "8e5a30338be326934ff93c998dcd0d22fe345870");
86     EXPECT_NE(DfxElf::Create(ELF32_FILE), nullptr);
87     EXPECT_NE(elf.GetGlobalPointer(), 0);
88     EXPECT_FALSE(elf.GetElfSymbols().empty());
89     EXPECT_GT(elf.GetMmapSize(), 0);
90     GTEST_LOG_(INFO) << "DfxElfTest001: end.";
91 }
92 
93 /**
94  * @tc.name: DfxElfTest002
95  * @tc.desc: test DfxElf functions with 64 bit ELF
96  * @tc.type: FUNC
97  */
98 HWTEST_F(DfxElfTest, DfxElfTest002, TestSize.Level2)
99 {
100     GTEST_LOG_(INFO) << "DfxElfTest002: start.";
101     DfxElf elf(ELF64_FILE);
102     ASSERT_TRUE(elf.IsValid());
103     ElfImitate elfImitate;
104     ShdrInfo shdr;
105     ShdrInfo shdrImitate;
106     bool ret = elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF64);
107     ASSERT_TRUE(ret);
108     for (size_t i = 0; i < interestedSections.size(); i++) {
109         GTEST_LOG_(INFO) << interestedSections[i];
110         elf.GetSectionInfo(shdr, interestedSections[i]);
111         elfImitate.GetSectionInfo(shdrImitate, interestedSections[i]);
112         ASSERT_EQ(shdr.addr, shdrImitate.addr);
113         ASSERT_EQ(shdr.offset, shdrImitate.offset);
114         ASSERT_EQ(shdr.size, shdrImitate.size);
115     }
116     ASSERT_EQ(elf.GetArchType(), elfImitate.GetArchType());
117     ASSERT_EQ(elf.GetElfSize(), elfImitate.GetElfSize());
118     ASSERT_EQ(elf.GetLoadBias(), elfImitate.GetLoadBias());
119 
120     auto load = elf.GetPtLoads();
121     auto loadImitate = elfImitate.GetPtLoads();
122     ASSERT_EQ(load[PT_LOAD_OFFSET64].offset, loadImitate[PT_LOAD_OFFSET64].offset);
123     ASSERT_EQ(load[PT_LOAD_OFFSET64].tableSize, loadImitate[PT_LOAD_OFFSET64].tableSize);
124     ASSERT_EQ(load[PT_LOAD_OFFSET64].tableVaddr, loadImitate[PT_LOAD_OFFSET64].tableVaddr);
125 
126     ASSERT_EQ(elf.GetClassType(), elfImitate.GetClassType());
127     ASSERT_EQ(elf.GetLoadBase(0xf78c0000, 0), elfImitate.GetLoadBase(0xf78c0000, 0));
128     ASSERT_EQ(elf.GetStartPc(), elfImitate.GetStartPc());
129     ASSERT_EQ(elf.GetEndPc(), elfImitate.GetEndPc());
130     ASSERT_EQ(elf.GetRelPc(0xf78c00f0, 0xf78c0000, 0), elfImitate.GetRelPc(0xf78c00f0, 0xf78c0000, 0));
131     ASSERT_EQ(elf.GetBuildId(), "24c55dccc5baaaa140da0083207abcb8d523e248");
132     EXPECT_NE(elf.GetGlobalPointer(), 0);
133     EXPECT_FALSE(elf.GetElfSymbols().empty());
134     EXPECT_GT(elf.GetMmapSize(), 0);
135     GTEST_LOG_(INFO) << "DfxElfTest002: end.";
136 }
137 
138 /**
139  * @tc.name: DfxElfTest003
140  * @tc.desc: test DfxElf functions with using error
141  * @tc.type: FUNC
142  */
143 HWTEST_F(DfxElfTest, DfxElfTest003, TestSize.Level2)
144 {
145     GTEST_LOG_(INFO) << "DfxElfTest003: start.";
146     DfxElf elf("");
147     ASSERT_FALSE(elf.IsValid());
148     ASSERT_EQ(elf.GetClassType(), ELFCLASSNONE);
149     ASSERT_EQ(elf.GetElfSize(), 0);
150     ASSERT_TRUE(elf.GetBuildId().empty());
151     EXPECT_EQ(DfxElf::Create("123"), nullptr);
152     ASSERT_TRUE(DfxElf::ToReadableBuildId("").empty());
153     EXPECT_EQ(elf.GetGlobalPointer(), 0);
154     ShdrInfo shdrInfo;
155     EXPECT_FALSE(elf.GetSectionInfo(shdrInfo, ""));
156     EXPECT_EQ(elf.GetMmapSize(), 0);
157     GTEST_LOG_(INFO) << "DfxElfTest003: end.";
158 }
159 
160 /**
161  * @tc.name: DfxElfTest004
162  * @tc.desc: test DfxElf class functions with minidebugInfo
163  * @tc.type: FUNC
164  */
165 HWTEST_F(DfxElfTest, DfxElfTest004, TestSize.Level2)
166 {
167     GTEST_LOG_(INFO) << "DfxElfTest004: start.";
168     UnwinderConfig::SetEnableMiniDebugInfo(true);
169     DfxElf elf(DUMPCATCHER_ELF_FILE);
170     ASSERT_TRUE(elf.IsValid());
171     ASSERT_TRUE(elf.IsEmbeddedElfValid());
172     auto symbols1 = elf.GetFuncSymbols();
173     GTEST_LOG_(INFO) << "DfxElfTest004: symbols1 size:" << symbols1.size();
174     auto symbols2 = elf.GetEmbeddedElf()->GetFuncSymbols();
175     GTEST_LOG_(INFO) << "DfxElfTest004: symbols2 size:" << symbols2.size();
176     ASSERT_GE(symbols2.size(), 0);
177     ASSERT_GE(symbols1.size(), symbols2.size());
178     GTEST_LOG_(INFO) << "DfxElfTest004: end.";
179 }
180 
181 /**
182  * @tc.name: DfxElfTest005
183  * @tc.desc: test GetBuildId function when input empty elf file path
184  * @tc.type: FUNC
185  */
186 HWTEST_F(DfxElfTest, DfxElfTest005, TestSize.Level2)
187 {
188     auto elfFile = std::make_shared<DfxElf>("");
189     ASSERT_NE(elfFile, nullptr);
190     EXPECT_STREQ(elfFile->GetBuildId().c_str(), "");
191 }
192 
193 /**
194  * @tc.name: DfxElfTest006
195  * @tc.desc: test GetBuildId function when input illegal elf file path
196  * @tc.type: FUNC
197  */
198 HWTEST_F(DfxElfTest, DfxElfTest006, TestSize.Level2)
199 {
200     auto elfFile = std::make_shared<DfxElf>("/proc/illegal");
201     ASSERT_NE(elfFile, nullptr);
202     EXPECT_STREQ(elfFile->GetBuildId().c_str(), "");
203 }
204 
205 /**
206  * @tc.name: DfxElfTest007
207  * @tc.desc: test SetBaseOffset function and GetBaseOffset function
208  * @tc.type: FUNC
209  */
210 HWTEST_F(DfxElfTest, DfxElfTest007, TestSize.Level2)
211 {
212     auto elf = std::make_shared<DfxElf>("");
213     ASSERT_EQ(elf->GetBaseOffset(), 0);
214     elf->SetBaseOffset(1);
215     ASSERT_EQ(elf->GetBaseOffset(), 1);
216 }
217 } // namespace HiviewDFX
218 } // namespace OHOS
219 
220