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 */
HWTEST_F(DfxElfTest, DfxElfTest001, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest002, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest003, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest004, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest005, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest006, TestSize.Level2)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 */
HWTEST_F(DfxElfTest, DfxElfTest007, TestSize.Level2)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