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
26using namespace OHOS::HiviewDFX;
27using namespace testing::ext;
28using 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
36namespace OHOS {
37namespace HiviewDFX {
38class DfxElfTest : public testing::Test {
39public:
40    static void SetUpTestCase(void) {}
41    static void TearDownTestCase(void) {}
42    void SetUp() {}
43    void TearDown() {}
44};
45
46std::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 */
52HWTEST_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 */
98HWTEST_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 */
143HWTEST_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 */
165HWTEST_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 */
186HWTEST_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 */
198HWTEST_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 */
210HWTEST_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