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 namespace OHOS {
34 namespace HiviewDFX {
35 class DfxSymbolsTest : public testing::Test {
36 public:
SetUpTestCase(void)37     static void SetUpTestCase(void) {}
TearDownTestCase(void)38     static void TearDownTestCase(void) {}
SetUp()39     void SetUp() {}
TearDown()40     void TearDown() {}
41 };
42 
43 
44 /**
45  * @tc.name: DfxSymbolsTest001
46  * @tc.desc: test DfxSymbols functions with 32 bit ELF
47  * @tc.type: FUNC
48  */
49 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest001, TestSize.Level2)
50 {
51     GTEST_LOG_(INFO) << "DfxSymbolsTest001: start.";
52     std::shared_ptr<DfxElf> elf = make_shared<DfxElf>(ELF32_FILE);
53     ASSERT_TRUE(elf->IsValid());
54     ElfImitate elfImitate;
55     elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF32);
56     std::vector<DfxSymbol> symbols;
57     std::vector<DfxSymbol> symbolsImitate;
58     DfxSymbols::ParseSymbols(symbols, elf, ELF32_FILE);
59     elfImitate.ParseSymbols(symbolsImitate, ELF32_FILE);
60     ASSERT_EQ(symbols.size(), symbolsImitate.size());
61     for (size_t i = 0; i < symbolsImitate.size(); ++i) {
62         symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_;
63         symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_;
64         symbols[i].name_ = symbolsImitate[i].name_;
65         symbols[i].demangle_ = symbolsImitate[i].demangle_;
66         symbols[i].module_ = symbolsImitate[i].module_;
67     }
68 
69     DfxSymbols::AddSymbolsByPlt(symbols, elf, ELF32_FILE);
70     elfImitate.AddSymbolsByPlt(symbolsImitate, ELF32_FILE);
71     ASSERT_EQ(symbols.size(), symbolsImitate.size());
72     for (size_t i = 0; i < symbolsImitate.size(); ++i) {
73         symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_;
74         symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_;
75         symbols[i].name_ = symbolsImitate[i].name_;
76         symbols[i].demangle_ = symbolsImitate[i].demangle_;
77         symbols[i].module_ = symbolsImitate[i].module_;
78     }
79     std::string funcName;
80     uint64_t funcOffset;
81     ASSERT_TRUE(DfxSymbols::GetFuncNameAndOffsetByPc(0x00001786, elf, funcName, funcOffset));
82     GTEST_LOG_(INFO) << "DfxSymbolsTest001: end.";
83 }
84 
85 /**
86  * @tc.name: DfxSymbolsTest002
87  * @tc.desc: test DfxSymbols functions with 64 bit ELF
88  * @tc.type: FUNC
89  */
90 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest002, TestSize.Level2)
91 {
92     GTEST_LOG_(INFO) << "DfxSymbolsTest002: start.";
93     std::shared_ptr<DfxElf> elf = make_shared<DfxElf>(ELF64_FILE);
94     ASSERT_TRUE(elf->IsValid());
95     ElfImitate elfImitate;
96     elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF64);
97     std::vector<DfxSymbol> symbols;
98     std::vector<DfxSymbol> symbolsImitate;
99     DfxSymbols::ParseSymbols(symbols, elf, ELF64_FILE);
100     elfImitate.ParseSymbols(symbolsImitate, ELF64_FILE);
101     ASSERT_EQ(symbols.size(), symbolsImitate.size());
102     for (size_t i = 0; i < symbolsImitate.size(); ++i) {
103         symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_;
104         symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_;
105         symbols[i].name_ = symbolsImitate[i].name_;
106         symbols[i].demangle_ = symbolsImitate[i].demangle_;
107         symbols[i].module_ = symbolsImitate[i].module_;
108     }
109 
110     DfxSymbols::AddSymbolsByPlt(symbols, elf, ELF64_FILE);
111     elfImitate.AddSymbolsByPlt(symbolsImitate, ELF64_FILE);
112     ASSERT_EQ(symbols.size(), symbolsImitate.size());
113     for (size_t i = 0; i < symbolsImitate.size(); ++i) {
114         symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_;
115         symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_;
116         symbols[i].name_ = symbolsImitate[i].name_;
117         symbols[i].demangle_ = symbolsImitate[i].demangle_;
118         symbols[i].module_ = symbolsImitate[i].module_;
119     }
120     std::string funcName;
121     uint64_t funcOffset;
122     ASSERT_TRUE(DfxSymbols::GetFuncNameAndOffsetByPc(0x00002a08, elf, funcName, funcOffset));
123 
124     GTEST_LOG_(INFO) << "DfxSymbolsTest002: end.";
125 }
126 
127 #if defined(ENABLE_MINIDEBUGINFO)
128 /**
129  * @tc.name: DfxSymbolsTest003
130  * @tc.desc: test DfxSymbols functions with minidebuginfo elf
131  * @tc.type: FUNC
132  */
133 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest003, TestSize.Level2)
134 {
135     GTEST_LOG_(INFO) << "DfxSymbolsTest003: start.";
136     UnwinderConfig::SetEnableMiniDebugInfo(true);
137     std::vector<DfxSymbol> dfxSymbols;
138     std::shared_ptr<DfxElf> elf = make_shared<DfxElf>(DUMPCATCHER_ELF_FILE);
139     ASSERT_TRUE(elf->IsValid());
140     ASSERT_TRUE(elf->IsEmbeddedElfValid());
141     DfxSymbols::ParseSymbols(dfxSymbols, elf, DUMPCATCHER_ELF_FILE);
142     GTEST_LOG_(INFO) << "DfxSymbolsTest003: symbols size:" << dfxSymbols.size();
143     ASSERT_GE(dfxSymbols.size(), 0);
144     for (auto dfxSymbol : dfxSymbols) {
145         GTEST_LOG_(INFO) << "DfxSymbolsTest003: dfxSymbol.demangle_: "<< dfxSymbol.demangle_;
146     }
147     GTEST_LOG_(INFO) << "DfxSymbolsTest003: end.";
148 }
149 #endif
150 
151 /**
152  * @tc.name: DfxDemangleTest001
153  * @tc.desc: test DfxSymbols demangle functions
154  * @tc.type: FUNC
155  */
156 HWTEST_F(DfxSymbolsTest, DfxDemangleTest001, TestSize.Level2)
157 {
158     GTEST_LOG_(INFO) << "DfxDemangleTest001: start.";
159     EXPECT_EQ("", DfxSymbols::Demangle(""));
160     EXPECT_EQ("a", DfxSymbols::Demangle("a"));
161     EXPECT_EQ("_", DfxSymbols::Demangle("_"));
162     EXPECT_EQ("ab", DfxSymbols::Demangle("ab"));
163     EXPECT_EQ("abc", DfxSymbols::Demangle("abc"));
164     EXPECT_EQ("_R", DfxSymbols::Demangle("_R"));
165     EXPECT_EQ("_Z", DfxSymbols::Demangle("_Z"));
166     GTEST_LOG_(INFO) << "DfxDemangleTest001: end.";
167 }
168 
169 /**
170  * @tc.name: DfxDemangleTest002
171  * @tc.desc: test DfxSymbols demangle functions with cxx
172  * @tc.type: FUNC
173  */
174 HWTEST_F(DfxSymbolsTest, DfxDemangleTest002, TestSize.Level2)
175 {
176     GTEST_LOG_(INFO) << "DfxDemangleTest002: start.";
177     EXPECT_EQ("fake(bool)", DfxSymbols::Demangle("_Z4fakeb"));
178     EXPECT_EQ("demangle(int)", DfxSymbols::Demangle("_Z8demanglei"));
179     GTEST_LOG_(INFO) << "DfxDemangleTest002: end.";
180 }
181 
182 /**
183  * @tc.name: DfxDemangleTest003
184  * @tc.desc: test DfxSymbols demangle functions with rust
185  * @tc.type: FUNC
186  */
187 HWTEST_F(DfxSymbolsTest, DfxDemangleTest003, TestSize.Level2)
188 {
189     GTEST_LOG_(INFO) << "DfxDemangleTest003: start.";
190     EXPECT_EQ("std::rt::lang_start_internal",
191         DfxSymbols::Demangle("_RNvNtCs2WRBrrl1bb1_3std2rt19lang_start_internal"));
192     EXPECT_EQ("profcollectd::main", DfxSymbols::Demangle("_RNvCs4VPobU5SDH_12profcollectd4main"));
193     GTEST_LOG_(INFO) << "DfxDemangleTest003: end.";
194 }
195 } // namespace HiviewDFX
196 } // namespace OHOS
197 
198