• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include <gtest/gtest.h>
16 
17 #include <cstdio>
18 #include <dlfcn.h>
19 #include <cstdint>
20 
21 #include "dfx_maps.h"
22 #include "dfx_symbols.h"
23 #include "dfx_test_util.h"
24 #include "elf_factory_selector.h"
25 #include "unwinder_config.h"
26 
27 using namespace testing;
28 using namespace testing::ext;
29 using namespace std;
30 
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34     constexpr const char* const DUMPCATCHER_ELF_FILE = "/system/bin/dumpcatcher";
35 }
36 class ElfFactoryTest : public testing::Test {
37 public:
SetUpTestCase()38     static void SetUpTestCase() {}
TearDownTestCase()39     static void TearDownTestCase() {}
SetUp()40     void SetUp() {}
TearDown()41     void TearDown() {}
42 };
43 
44 /**
45  * @tc.name: ElfFactoryTest001
46  * @tc.desc: test VdsoElfFactory normal case
47  * @tc.type: FUNC
48  */
49 HWTEST_F(ElfFactoryTest, ElfFactoryTest001, TestSize.Level2)
50 {
51     GTEST_LOG_(INFO) << "ElfFactoryTest001: start.";
52     std::string res = ExecuteCommands("uname");
53     bool linuxKernel = res.find("Linux") != std::string::npos;
54     if (linuxKernel) {
55         ASSERT_TRUE(linuxKernel);
56     } else {
57         pid_t pid = GetProcessPid(FOUNDATION_NAME);
58         auto maps = DfxMaps::Create(pid);
59         std::vector<std::shared_ptr<DfxMap>> shmmMaps;
60         ASSERT_TRUE(maps->FindMapsByName("[shmm]", shmmMaps));
61         std::shared_ptr<DfxMap> shmmMap = nullptr;
62         for (auto map : shmmMaps) {
63             if (map->IsMapExec()) {
64                 shmmMap = map;
65                 break;
66             }
67         }
68         ASSERT_TRUE(shmmMap != nullptr);
69         VdsoElfFactory factory(shmmMap->begin, shmmMap->end - shmmMap->begin, pid);
70         auto shmmElf = factory.Create();
71         ASSERT_TRUE(shmmElf != nullptr);
72         std::vector<DfxSymbol> shmmSyms;
73         DfxSymbols::ParseSymbols(shmmSyms, shmmElf, "");
74         GTEST_LOG_(INFO) << "shmm symbols size" << shmmSyms.size();
75         ASSERT_GT(shmmSyms.size(), 0);
76         for (const auto& sym : shmmSyms) {
77             GTEST_LOG_(INFO) << sym.ToDebugString();
78         }
79         GTEST_LOG_(INFO) << "ElfFactoryTest001 : end.";
80     }
81 }
82 
83 /**
84  * @tc.name: ElfFactoryTest002
85  * @tc.desc: test VdsoElfFactory using not vdso exec map case
86  * @tc.type: FUNC
87  */
88 HWTEST_F(ElfFactoryTest, ElfFactoryTest002, TestSize.Level2)
89 {
90     GTEST_LOG_(INFO) << "ElfFactoryTest002: start.";
91     pid_t pid = GetProcessPid(FOUNDATION_NAME);
92     auto dfxMaps = DfxMaps::Create(pid);
93     std::vector<std::shared_ptr<DfxMap>> maps;
94     ASSERT_TRUE(dfxMaps->FindMapsByName("libunwinder.z.so", maps));
95     for (const auto& map : maps) {
96         if (map->IsMapExec()) {
97             VdsoElfFactory factory(map->begin, map->end - map->begin, pid);
98             auto elf = factory.Create();
99             ASSERT_TRUE(elf == nullptr);
100             break;
101         }
102     }
103     GTEST_LOG_(INFO) << "ElfFactoryTest002 : end.";
104 }
105 
106 /**
107  * @tc.name: ElfFactoryTest003
108  * @tc.desc: test VdsoElfFactory using abnormal param
109  * @tc.type: FUNC
110  */
111 HWTEST_F(ElfFactoryTest, ElfFactoryTest003, TestSize.Level2)
112 {
113     GTEST_LOG_(INFO) << "ElfFactoryTest003: start.";
114     uint64_t begin = 0;
115     size_t size = 0;
116     pid_t pid = 0;
117     VdsoElfFactory factory(begin, size, pid);
118     auto elf = factory.Create();
119     ASSERT_TRUE(elf == nullptr);
120     GTEST_LOG_(INFO) << "ElfFactoryTest003 : end.";
121 }
122 
123 #ifndef __x86_64__
124 /**
125  * @tc.name: ElfFactoryTest004
126  * @tc.desc: test MiniDebugInfoFactory normal case
127  * @tc.type: FUNC
128  */
129 HWTEST_F(ElfFactoryTest, ElfFactoryTest004, TestSize.Level2)
130 {
131     GTEST_LOG_(INFO) << "ElfFactoryTest004: start.";
132     UnwinderConfig::SetEnableMiniDebugInfo(true);
133     RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE);
134     auto elf = regularElfFactory.Create();
135     ASSERT_TRUE(elf->IsValid());
136     auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr();
137     ASSERT_TRUE(gnuDebugDataHdr.size != 0);
138     MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr);
139     elf = miniDebugInfoFactory.Create();
140     ASSERT_TRUE(elf->IsValid());
141     GTEST_LOG_(INFO) << "ElfFactoryTest004: end.";
142 }
143 
144 /**
145  * @tc.name: ElfFactoryTest005
146  * @tc.desc: test MiniDebugInfoFactory normal case with test parsing symbol
147  * @tc.type: FUNC
148  */
149 HWTEST_F(ElfFactoryTest, ElfFactoryTest005, TestSize.Level2)
150 {
151     GTEST_LOG_(INFO) << "ElfFactoryTest005: start.";
152     UnwinderConfig::SetEnableMiniDebugInfo(true);
153     RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE);
154     auto elf = regularElfFactory.Create();
155     ASSERT_TRUE(elf->IsValid());
156     auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr();
157     ASSERT_TRUE(gnuDebugDataHdr.size != 0);
158     MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr);
159     elf = miniDebugInfoFactory.Create();
160     ASSERT_TRUE(elf->IsValid());
161     std::vector<DfxSymbol> symbols;
162     DfxSymbols::ParseSymbols(symbols, elf, "");
163     GTEST_LOG_(INFO) << "symbols size" << symbols.size();
164     ASSERT_GT(symbols.size(), 0);
165     for (const auto& symbol : symbols) {
166         GTEST_LOG_(INFO) << symbol.ToDebugString();
167     }
168     GTEST_LOG_(INFO) << "ElfFactoryTest005: end.";
169 }
170 
171 /**
172  * @tc.name: ElfFactoryTest006
173  * @tc.desc: test MiniDebugInfoFactory disable minidebuginfo case
174  * @tc.type: FUNC
175  */
176 HWTEST_F(ElfFactoryTest, ElfFactoryTest006, TestSize.Level2)
177 {
178     GTEST_LOG_(INFO) << "ElfFactoryTest006: start.";
179     UnwinderConfig::SetEnableMiniDebugInfo(false);
180     RegularElfFactory regularElfFactory(DUMPCATCHER_ELF_FILE);
181     auto elf = regularElfFactory.Create();
182     ASSERT_TRUE(elf->IsValid());
183     auto gnuDebugDataHdr = elf->GetGnuDebugDataHdr();
184     ASSERT_TRUE(gnuDebugDataHdr.size != 0);
185     MiniDebugInfoFactory miniDebugInfoFactory(gnuDebugDataHdr);
186     elf = miniDebugInfoFactory.Create();
187     ASSERT_TRUE(elf == nullptr);
188     GTEST_LOG_(INFO) << "ElfFactoryTest006: end.";
189 }
190 
191 /**
192  * @tc.name: ElfFactoryTest007
193  * @tc.desc: test MiniDebugInfoFactory using abnormal param
194  * @tc.type: FUNC
195  */
196 HWTEST_F(ElfFactoryTest, ElfFactoryTest007, TestSize.Level2)
197 {
198     GTEST_LOG_(INFO) << "ElfFactoryTest007: start.";
199     UnwinderConfig::SetEnableMiniDebugInfo(true);
200     GnuDebugDataHdr hdr;
201     MiniDebugInfoFactory miniDebugInfoFactory(hdr);
202     auto elf = miniDebugInfoFactory.Create();
203     ASSERT_TRUE(elf == nullptr);
204     GTEST_LOG_(INFO) << "ElfFactoryTest007: end.";
205 }
206 
207 /**
208  * @tc.name: ElfFactoryTest008
209  * @tc.desc: test MiniDebugInfoFactory using abnormal param
210  * @tc.type: FUNC
211  */
212 HWTEST_F(ElfFactoryTest, ElfFactoryTest008, TestSize.Level2)
213 {
214     GTEST_LOG_(INFO) << "ElfFactoryTest008: start.";
215     UnwinderConfig::SetEnableMiniDebugInfo(false);
216     GnuDebugDataHdr hdr;
217     MiniDebugInfoFactory miniDebugInfoFactory(hdr);
218     auto elf = miniDebugInfoFactory.Create();
219     ASSERT_TRUE(elf == nullptr);
220     GTEST_LOG_(INFO) << "ElfFactoryTest008: end.";
221 }
222 #endif
223 
224 /**
225  * @tc.name: ElfFactoryTest009
226  * @tc.desc: test ElfFactoryTest with 64 bit ELF
227  * @tc.type: FUNC
228  */
229 HWTEST_F(ElfFactoryTest, ElfFactoryTest009, TestSize.Level2)
230 {
231     GTEST_LOG_(INFO) << "ElfFactoryTest009: start.";
232     const char* elf64File = "/data/test/resource/testdata/elf_test";
233     RegularElfFactory factory(elf64File);
234     auto elf = factory.Create();
235     ASSERT_TRUE(elf->IsValid());
236     GTEST_LOG_(INFO) << "ElfFactoryTest009: end.";
237 }
238 
239 /**
240  * @tc.name: ElfFactoryTest010
241  * @tc.desc: ElfFactoryTest with 32 bit ELF
242  * @tc.type: FUNC
243  */
244 HWTEST_F(ElfFactoryTest, ElfFactoryTest010, TestSize.Level2)
245 {
246     GTEST_LOG_(INFO) << "ElfFactoryTest010: start.";
247     const char* elf32File = "/data/test/resource/testdata/elf32_test";
248     RegularElfFactory factory(elf32File);
249     auto elf = factory.Create();
250     ASSERT_TRUE(elf->IsValid());
251     GTEST_LOG_(INFO) << "ElfFactoryTest010: end.";
252 }
253 
254 /**
255  * @tc.name: ElfFactoryTest011
256  * @tc.desc: test DfxElf functions with empty file path
257  * @tc.type: FUNC
258  */
259 HWTEST_F(ElfFactoryTest, ElfFactoryTest011, TestSize.Level2)
260 {
261     GTEST_LOG_(INFO) << "ElfFactoryTest002: start.";
262     std::string filePath  = "";
263     RegularElfFactory factory(filePath);
264     auto elf = factory.Create();
265     ASSERT_FALSE(elf->IsValid());
266     GTEST_LOG_(INFO) << "ElfFactoryTest011: end.";
267 }
268 
269 /**
270  * @tc.name: ElfFactoryTest012
271  * @tc.desc: test DfxElf functions with invalid filePath
272  * @tc.type: FUNC
273  */
274 HWTEST_F(ElfFactoryTest, ElfFactoryTest012, TestSize.Level2)
275 {
276     GTEST_LOG_(INFO) << "ElfFactoryTest012: start.";
277     std::string filePath  = "[anno:stack:2345]";
278     RegularElfFactory factory(filePath);
279     auto elf = factory.Create();
280     ASSERT_FALSE(elf->IsValid());
281     GTEST_LOG_(INFO) << "ElfFactoryTest012: end.";
282 }
283 
284 /**
285  * @tc.name: ElfFactoryTest013
286  * @tc.desc: ElfFactorySelector in normal case
287  * @tc.type: FUNC
288  */
289 HWTEST_F(ElfFactoryTest, ElfFactoryTest013, TestSize.Level2)
290 {
291     GTEST_LOG_(INFO) << "ElfFactoryTest013: start.";
292     pid_t pid = GetProcessPid(FOUNDATION_NAME);
293     auto dfxMaps = DfxMaps::Create(pid);
294     auto maps = dfxMaps->GetMaps();
295     for (const auto& map : maps) {
296         auto elfFactory = ElfFactorySelector::Select(*(map.get()), pid);
297         auto elf = elfFactory->Create();
298         if (map->IsVdsoMap()) {
299             ASSERT_TRUE(elf->IsValid());
300             GTEST_LOG_(INFO) << elf->GetElfName();
301             ASSERT_TRUE(elf->GetElfName().find("shmm") != std::string::npos ||
302                 elf->GetElfName().find("vdso") != std::string::npos);
303         } else if (DfxMaps::IsLegalMapItem(map->name) && map->IsMapExec()) {
304             ASSERT_TRUE(elf->IsValid()) << map->name;
305         }
306     }
307     GTEST_LOG_(INFO) << "ElfFactoryTest013: end.";
308 }
309 
310 /**
311  * @tc.name: ElfFactoryTest014
312  * @tc.desc: ElfFactorySelector using abnormal param
313  * @tc.type: FUNC
314  */
315 HWTEST_F(ElfFactoryTest, ElfFactoryTest014, TestSize.Level2)
316 {
317     GTEST_LOG_(INFO) << "ElfFactoryTest014: start.";
318     DfxMap map;
319     auto elfFactory = ElfFactorySelector::Select(map);
320     auto elf = elfFactory->Create();
321     ASSERT_FALSE(elf->IsValid());
322 
323     map.begin = 0xc38a6000;
324     map.end = 0xc39450000;
325     map.offset = 0x1d9000;
326     map.prots |= PROT_READ;
327     map.prots |= PROT_EXEC;
328     map.name = "/proc/data/storage/el1/bundle/entry.hap"; // invalid path
329     auto prevMap = std::make_shared<DfxMap>();
330     prevMap->begin = 0xc3840000;
331     prevMap->end = 0xc38a6000;
332     prevMap->offset = 0x174000;
333     prevMap->prots |= PROT_READ;
334     prevMap->name = "/proc/data/storage/el1/bundle/entry.hap"; // invalid path
335     map.prevMap = prevMap;
336     elfFactory = ElfFactorySelector::Select(map);
337     elf = elfFactory->Create();
338     ASSERT_EQ(elf, nullptr);
339     GTEST_LOG_(INFO) << "ElfFactoryTest014: end.";
340 }
341 }
342 }