• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 
18 #include <cstdio>
19 #include <hilog/log.h>
20 #include <malloc.h>
21 #include <map>
22 #include <securec.h>
23 #include <thread>
24 #include <unistd.h>
25 
26 #include "dfx_config.h"
27 #include "dfx_frame_formatter.h"
28 #include "dfx_ptrace.h"
29 #include "dfx_regs_get.h"
30 #include "dfx_test_util.h"
31 #include "elapsed_time.h"
32 #include "unwinder.h"
33 
34 using namespace testing;
35 using namespace testing::ext;
36 
37 namespace OHOS {
38 namespace HiviewDFX {
39 #undef LOG_DOMAIN
40 #undef LOG_TAG
41 #define LOG_TAG "DfxUnwinderTest"
42 #define LOG_DOMAIN 0xD002D11
43 #define TIME_SLEEP 3
44 
45 class UnwinderTest : public testing::Test {
46 public:
SetUpTestCase()47     static void SetUpTestCase() {}
TearDownTestCase()48     static void TearDownTestCase() {}
SetUp()49     void SetUp() {}
TearDown()50     void TearDown() {}
51 
52     std::map<int, std::shared_ptr<Unwinder>> unwinders_;
53 };
54 
55 /**
56  * @tc.name: GetStackRangeTest001
57  * @tc.desc: test unwinder GetStackRange interface in pid == tid
58  * @tc.type: FUNC
59  */
60 HWTEST_F(UnwinderTest, GetStackRangeTest001, TestSize.Level2)
61 {
62     GTEST_LOG_(INFO) << "GetStackRangeTest001: start.";
63     auto unwinder = std::make_shared<Unwinder>();
64     uintptr_t stackBottom = 1;
65     uintptr_t stackTop = static_cast<uintptr_t>(-1);
66     GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, GetStackRange(stackBottom, stackTop) is true";
67     ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
68     // When the param is less than -1, maps_ = null when method Unwinder is constructed
69     auto unwinderNegative = std::make_shared<Unwinder>(-2);
70     GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, GetStackRange(stackBottom, stackTop) is false";
71     ASSERT_FALSE(unwinderNegative->GetStackRange(stackBottom, stackTop));
72     GTEST_LOG_(INFO) << "GetStackRangeTest001: end.";
73 }
74 
75 /**
76  * @tc.name: GetStackRangeTest002
77  * @tc.desc: test unwinder GetStackRange interface in pid != tid
78  * @tc.type: FUNC
79  */
80 HWTEST_F(UnwinderTest, GetStackRangeTest002, TestSize.Level2)
81 {
82     GTEST_LOG_(INFO) << "GetStackRangeTest002: start.";
83     auto unwinder = std::make_shared<Unwinder>();
84     uintptr_t stackBottom = 1;
85     uintptr_t stackTop = static_cast<uintptr_t>(-1);
86     bool result = false;
87     GTEST_LOG_(INFO) << "Run the function with thread will get pid != tid, "
88                         "GetStackRange(stackBottom, stackTop) is true";
__anon77cca69e0102null89     std::thread* thread = new std::thread([&]{result = unwinder->GetStackRange(stackBottom, stackTop);});
90     thread->join();
91     ASSERT_TRUE(result);
92     GTEST_LOG_(INFO) << "GetStackRangeTest002: end.";
93 }
94 
95 /**
96  * @tc.name: UnwinderLocalTest001
97  * @tc.desc: test unwinder local unwind
98  * @tc.type: FUNC
99  */
100 HWTEST_F(UnwinderTest, UnwinderLocalTest001, TestSize.Level2)
101 {
102     GTEST_LOG_(INFO) << "UnwinderLocalTest001: start.";
103     auto unwinder = std::make_shared<Unwinder>();
104     ElapsedTime counter;
105     MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
106     time_t elapsed1 = counter.Elapsed();
107     EXPECT_EQ(true, unwRet) << "UnwinderLocalTest001: Unwind:" << unwRet;
108     auto frames = unwinder->GetFrames();
109     ASSERT_GT(frames.size(), 1);
110     time_t elapsed2 = counter.Elapsed();
111     GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
112     GTEST_LOG_(INFO) << "UnwinderLocalTest001: frames:\n" << Unwinder::GetFramesStr(frames);
113     GTEST_LOG_(INFO) << "UnwinderLocalTest001: end.";
114 }
115 
116 /**
117  * @tc.name: UnwinderLocalTest002
118  * @tc.desc: test unwinder local unwind n counts
119  * @tc.type: FUNC
120  */
121 HWTEST_F(UnwinderTest, UnwinderLocalTest002, TestSize.Level2)
122 {
123     GTEST_LOG_(INFO) << "UnwinderLocalTest002: start.";
124     unwinders_.clear();
125     std::shared_ptr<Unwinder> unwinder = nullptr;
126     pid_t pid = getpid();
127     GTEST_LOG_(INFO) << "pid: " << pid;
128     for (int i = 0; i < 10; ++i) {
129         auto it = unwinders_.find(pid);
130         if (it != unwinders_.end()) {
131             unwinder = it->second;
132         } else {
133             unwinder = std::make_shared<Unwinder>();
134         }
135         ElapsedTime counter;
136         MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
137         time_t elapsed1 = counter.Elapsed();
138         EXPECT_EQ(true, unwRet) << "UnwinderLocalTest002: Unwind:" << unwRet;
139         auto frames = unwinder->GetFrames();
140         ASSERT_GT(frames.size(), 1);
141         time_t elapsed2 = counter.Elapsed();
142         GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
143         GTEST_LOG_(INFO) << "UnwinderLocalTest002: frames:\n" << Unwinder::GetFramesStr(frames);
144         unwinders_[pid] = unwinder;
145         sleep(1);
146     };
147     GTEST_LOG_(INFO) << "UnwinderLocalTest002: end.";
148 }
149 
150 /**
151  * @tc.name: UnwinderLocalTest003
152  * @tc.desc: test unwinder UnwinderLocal interface GetStackRange == false or GetStackRange == true
153  * @tc.type: FUNC
154  */
155 HWTEST_F(UnwinderTest, UnwinderLocalTest003, TestSize.Level2)
156 {
157     GTEST_LOG_(INFO) << "UnwinderLocalTest003: start.";
158     // When the param is less than -1, maps_ = null when method Unwinder is constructed
159     auto unwinderNegative = std::make_shared<Unwinder>(-2);
160     GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, "
161                          "UnwindLocal(maxFrameNum, skipFrameNum) is false";
162     ASSERT_FALSE(unwinderNegative->UnwindLocal());
163     auto unwinder = std::make_shared<Unwinder>();
164     GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, "
165                         "UnwindLocal(maxFrameNum, skipFrameNum) is true";
166     ASSERT_TRUE(unwinder->UnwindLocal());
167     GTEST_LOG_(INFO) << "UnwinderLocalTest003: end.";
168 }
169 
170 /**
171  * @tc.name: UnwinderRemoteTest001
172  * @tc.desc: test unwinder remote unwind
173  * @tc.type: FUNC
174  */
175 HWTEST_F(UnwinderTest, UnwinderRemoteTest001, TestSize.Level2)
176 {
177     GTEST_LOG_(INFO) << "UnwinderRemoteTest001: start.";
178     pid_t child = fork();
179     if (child == 0) {
180         sleep(TIME_SLEEP);
181         _exit(0);
182     }
183 
184     GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
185     auto unwinder = std::make_shared<Unwinder>(child);
186     bool unwRet = DfxPtrace::Attach(child);
187     EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: Attach:" << unwRet;
188     ElapsedTime counter;
189     unwRet = unwinder->UnwindRemote(child);
190     time_t elapsed1 = counter.Elapsed();
191     EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: unwRet:" << unwRet;
192     auto frames = unwinder->GetFrames();
193     ASSERT_GT(frames.size(), 1);
194     time_t elapsed2 = counter.Elapsed();
195     GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
196     GTEST_LOG_(INFO) << "UnwinderRemoteTest001: frames:\n" << Unwinder::GetFramesStr(frames);
197     DfxPtrace::Detach(child);
198     GTEST_LOG_(INFO) << "UnwinderRemoteTest001: end.";
199 }
200 
201 /**
202  * @tc.name: UnwinderRemoteTest002
203  * @tc.desc: test unwinder remote unwind n counts
204  * @tc.type: FUNC
205  */
206 HWTEST_F(UnwinderTest, UnwinderRemoteTest002, TestSize.Level2)
207 {
208     GTEST_LOG_(INFO) << "UnwinderRemoteTest002: start.";
209     pid_t child = fork();
210     if (child == 0) {
211         sleep(TIME_SLEEP);
212         _exit(0);
213     }
214 
215     GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
216     unwinders_.clear();
217     std::shared_ptr<Unwinder> unwinder = nullptr;
218     bool unwRet = DfxPtrace::Attach(child);
219     EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Attach:" << unwRet;
220     for (int i = 0; i < 10; ++i) {
221         auto it = unwinders_.find(child);
222         if (it != unwinders_.end()) {
223             unwinder = it->second;
224         } else {
225             unwinder = std::make_shared<Unwinder>(child);
226         }
227         ElapsedTime counter;
228         unwRet = unwinder->UnwindRemote(child);
229         time_t elapsed1 = counter.Elapsed();
230         EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Unwind:" << unwRet;
231         auto frames = unwinder->GetFrames();
232         ASSERT_GT(frames.size(), 1);
233         time_t elapsed2 = counter.Elapsed();
234         GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
235         GTEST_LOG_(INFO) << "UnwinderRemoteTest002: frames:\n" << Unwinder::GetFramesStr(frames);
236         unwinders_[child] = unwinder;
237         sleep(1);
238     }
239     DfxPtrace::Detach(child);
240     GTEST_LOG_(INFO) << "UnwinderRemoteTest002: end.";
241 }
242 
243 /**
244  * @tc.name: UnwinderRemoteTest003
245  * @tc.desc: test unwinder UnwinderRemote interface GetStackRange == false or GetStackRange == true
246  * @tc.type: FUNC
247  */
248 HWTEST_F(UnwinderTest, UnwinderRemoteTest003, TestSize.Level2)
249 {
250     GTEST_LOG_(INFO) << "UnwinderRemoteTest003: start.";
251     // When the param is less than -1, pid_ < 0 when method Unwinder is constructed
252     auto unwinderNegative = std::make_shared<Unwinder>(-2);
253     size_t maxFrameNum = 64;
254     size_t skipFrameNum = 0;
255     GTEST_LOG_(INFO) << "when pid <= 0, UnwindLocal(maxFrameNum, skipFrameNum) is false";
256     ASSERT_FALSE(unwinderNegative->UnwindRemote(-2, maxFrameNum, skipFrameNum));
257     GTEST_LOG_(INFO) << "UnwinderRemoteTest003: end.";
258 }
259 
260 /**
261  * @tc.name: UnwindTest001
262  * @tc.desc: test unwinder unwind interface in remote case
263  * @tc.type: FUNC
264  */
265 HWTEST_F(UnwinderTest, UnwindTest001, TestSize.Level2)
266 {
267     GTEST_LOG_(INFO) << "UnwindTest001: start.";
268     pid_t child = fork();
269     if (child == 0) {
270         sleep(TIME_SLEEP);
271         _exit(0);
272     }
273 
274     GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
275     auto unwinder = std::make_shared<Unwinder>(child);
276     bool unwRet = DfxPtrace::Attach(child);
277     EXPECT_EQ(true, unwRet) << "UnwindTest001: Attach:" << unwRet;
278     auto regs = DfxRegs::CreateRemoteRegs(child);
279     unwinder->SetRegs(regs);
280     UnwindContext context;
281     context.pid = child;
282     context.regs = regs;
283     ElapsedTime counter;
284     unwRet = unwinder->Unwind(&context);
285     time_t elapsed1 = counter.Elapsed();
286     EXPECT_EQ(true, unwRet) << "UnwindTest001: Unwind:" << unwRet;
287     auto frames = unwinder->GetFrames();
288     ASSERT_GT(frames.size(), 1);
289     time_t elapsed2 = counter.Elapsed();
290     GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
291     GTEST_LOG_(INFO) << "UnwindTest001: frames:\n" << Unwinder::GetFramesStr(frames);
292     DfxPtrace::Detach(child);
293     GTEST_LOG_(INFO) << "UnwindTest001: end.";
294 }
295 
296 /**
297  * @tc.name: UnwindTest002
298  * @tc.desc: test unwinder unwind interface in local case
299  * @tc.type: FUNC
300  */
301 HWTEST_F(UnwinderTest, UnwindTest002, TestSize.Level2)
302 {
303     GTEST_LOG_(INFO) << "UnwindTest002: start.";
304     auto unwinder = std::make_shared<Unwinder>();
305     uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
306     ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
307     GTEST_LOG_(INFO) << "UnwindTest002: GetStackRange.";
308     UnwindContext context;
309     context.stackCheck = false;
310     context.stackBottom = stackBottom;
311     context.stackTop = stackTop;
312 
313     auto regs = DfxRegs::Create();
314     auto regsData = regs->RawData();
315     GetLocalRegs(regsData);
316     unwinder->SetRegs(regs);
317     context.pid = UNWIND_TYPE_LOCAL;
318     context.regs = regs;
319     bool unwRet = unwinder->Unwind(&context);
320     EXPECT_EQ(true, unwRet) << "UnwindTest002: unwRet:" << unwRet;
321     auto frames = unwinder->GetFrames();
322     ASSERT_GT(frames.size(), 1);
323     GTEST_LOG_(INFO) << "UnwindTest002:frames:\n" << Unwinder::GetFramesStr(frames);
324     GTEST_LOG_(INFO) << "UnwindTest002: end.";
325 }
326 
327 /**
328  * @tc.name: UnwindTest003
329  * @tc.desc: test GetPcs GetLastErrorCode GetLastErrorAddr GetFramesByPcs functions
330  *  in local case
331  * @tc.type: FUNC
332  */
333 HWTEST_F(UnwinderTest, UnwindTest003, TestSize.Level2)
334 {
335     GTEST_LOG_(INFO) << "UnwindTest003: start.";
336 
337     auto unwinder = std::make_shared<Unwinder>();
338     MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
339     EXPECT_EQ(true, unwRet) << "UnwindTest003: Unwind ret:" << unwRet;
340     auto pcs = unwinder->GetPcs();
341     ASSERT_GT(pcs.size(), 0);
342     GTEST_LOG_(INFO) << "pcs.size() > 0\n";
343 
344     uint16_t errorCode = unwinder->GetLastErrorCode();
345     uint64_t errorAddr = unwinder->GetLastErrorAddr();
346     GTEST_LOG_(INFO) << "errorCode:" << errorCode;
347     GTEST_LOG_(INFO) << "errorAddr:" << errorAddr;
348 
349     std::vector<DfxFrame> frames;
350     std::shared_ptr<DfxMaps> maps = unwinder->GetMaps();
351     unwinder->GetFramesByPcs(frames, pcs, maps);
352     ASSERT_GT(frames.size(), 1);
353     GTEST_LOG_(INFO) << "UnwindTest003: frames:\n" << Unwinder::GetFramesStr(frames);
354     GTEST_LOG_(INFO) << "UnwindTest003: end.";
355 }
356 
357 /**
358  * @tc.name: UnwindTest004
359  * @tc.desc: test unwinder local unwind for
360  * GetFramesStr(const std::vector<std::shared_ptr<DfxFrame>>& frames)
361  * @tc.type: FUNC
362  */
363 HWTEST_F(UnwinderTest, UnwindTest004, TestSize.Level2)
364 {
365     GTEST_LOG_(INFO) << "UnwindTest004: start.";
366 
367     auto unwinder = std::make_shared<Unwinder>();
368     ElapsedTime counter;
369     MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
370     ASSERT_EQ(true, unwRet) << "UnwindTest004: Unwind:" << unwRet;
371     auto frames = unwinder->GetFrames();
372     ASSERT_GT(frames.size(), 1);
373 
374     auto framesVec = DfxFrameFormatter::ConvertFrames(frames);
375     std::string framesStr = DfxFrameFormatter::GetFramesStr(framesVec);
376     GTEST_LOG_(INFO) << "UnwindTest004: frames:\n" << framesStr;
377 
378     string log[] = {"pc", "test_unwind", "#00", "#01", "#02"};
379     int len = sizeof(log) / sizeof(log[0]);
380     int count = GetKeywordsNum(framesStr, log, len);
381     ASSERT_EQ(count, len) << "UnwindTest004 Failed";
382     GTEST_LOG_(INFO) << "UnwindTest004: end.";
383 }
384 
385 /**
386  * @tc.name: StepTest001
387  * @tc.desc: test unwinder Step interface in remote case
388  * @tc.type: FUNC
389  */
390 HWTEST_F(UnwinderTest, StepTest001, TestSize.Level2)
391 {
392     GTEST_LOG_(INFO) << "StepTest001: start.";
393     pid_t child = fork();
394     if (child == 0) {
395         sleep(TIME_SLEEP);
396         _exit(0);
397     }
398 
399     GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
400     auto unwinder = std::make_shared<Unwinder>(child);
401     bool unwRet = DfxPtrace::Attach(child);
402     EXPECT_EQ(true, unwRet) << "StepTest001: Attach:" << unwRet;
403     auto regs = DfxRegs::CreateRemoteRegs(child);
404     std::shared_ptr<DfxMaps> maps = DfxMaps::Create(child);
405     unwinder->SetRegs(regs);
406     UnwindContext context;
407     context.pid = child;
408     context.regs = regs;
409     uintptr_t pc, sp;
410     pc = regs->GetPc();
411     sp = regs->GetSp();
412     std::shared_ptr<DfxMap> map = nullptr;
413     ASSERT_TRUE(maps->FindMapByAddr(pc, map));
414     context.map = map;
415     unwRet = unwinder->Step(pc, sp, &context);
416     ASSERT_TRUE(unwRet) << "StepTest001: Unwind:" << unwRet;
417     DfxPtrace::Detach(child);
418     GTEST_LOG_(INFO) << "StepTest001: end.";
419 }
420 
421 /**
422  * @tc.name: StepTest002
423  * @tc.desc: test unwinder Step interface in local case
424  * @tc.type: FUNC
425  */
426 HWTEST_F(UnwinderTest, StepTest002, TestSize.Level2)
427 {
428     GTEST_LOG_(INFO) << "StepTest002: start.";
429     auto unwinder = std::make_shared<Unwinder>();
430     uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
431     ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
432     GTEST_LOG_(INFO) << "StepTest002: GetStackRange.";
433     UnwindContext context;
434     context.pid = UNWIND_TYPE_LOCAL;
435     context.stackCheck = false;
436     context.stackBottom = stackBottom;
437     context.stackTop = stackTop;
438 
439     auto regs = DfxRegs::Create();
440     auto regsData = regs->RawData();
441     GetLocalRegs(regsData);
442     unwinder->SetRegs(regs);
443     context.regs = regs;
444 
445     uintptr_t pc, sp;
446     pc = regs->GetPc();
447     sp = regs->GetSp();
448     bool unwRet = unwinder->Step(pc, sp, &context);
449     ASSERT_TRUE(unwRet) << "StepTest002: unwRet:" << unwRet;
450     GTEST_LOG_(INFO) << "StepTest002: end.";
451 }
452 
453 #if defined(__aarch64__)
454 /**
455  * @tc.name: StepTest003
456  * @tc.desc: test unwinder FpStep interface in remote case
457  * @tc.type: FUNC
458  */
459 HWTEST_F(UnwinderTest, StepTest003, TestSize.Level2)
460 {
461     GTEST_LOG_(INFO) << "StepTest003: start.";
462     pid_t child = fork();
463     if (child == 0) {
464         sleep(TIME_SLEEP);
465         _exit(0);
466     }
467 
468     GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
469     auto unwinder = std::make_shared<Unwinder>(child);
470     bool unwRet = DfxPtrace::Attach(child);
471     EXPECT_EQ(true, unwRet) << "StepTest003: Attach:" << unwRet;
472     auto regs = DfxRegs::CreateRemoteRegs(child);
473     std::shared_ptr<DfxMaps> maps = DfxMaps::Create(child);
474     unwinder->SetRegs(regs);
475     UnwindContext context;
476     context.pid = child;
477     ElapsedTime counter;
478     unwRet = unwinder->UnwindByFp(&context);
479     ASSERT_TRUE(unwRet) << "StepTest003: unwind:" << unwRet;
480     DfxPtrace::Detach(child);
481     time_t elapsed = counter.Elapsed();
482     GTEST_LOG_(INFO) << "StepTest003: Elapsed: " << elapsed;
483     GTEST_LOG_(INFO) << "StepTest003: end.";
484 }
485 
486 /**
487  * @tc.name: StepTest004
488  * @tc.desc: test unwinder FpStep interface in local case
489  * @tc.type: FUNC
490  */
491 HWTEST_F(UnwinderTest, StepTest004, TestSize.Level2)
492 {
493     GTEST_LOG_(INFO) << "StepTest004: start.";
494     auto unwinder = std::make_shared<Unwinder>();
495     ElapsedTime counter;
496     uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
497     ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
498     GTEST_LOG_(INFO) << "StepTest004: GetStackRange.";
499 
500     auto regs = DfxRegs::Create();
501     auto regsData = regs->RawData();
502     GetLocalRegs(regsData);
503     UnwindContext context;
504     context.pid = UNWIND_TYPE_LOCAL;
505     context.stackCheck = false;
506     context.stackBottom = stackBottom;
507     context.stackTop = stackTop;
508     unwinder->SetRegs(regs);
509 
510     bool unwRet = unwinder->UnwindByFp(&context);
511     ASSERT_TRUE(unwRet) << "StepTest004: unwRet:" << unwRet;
512     size_t unwSize = unwinder->GetPcs().size();
513     GTEST_LOG_(INFO) << "StepTest004: unwSize: " << unwSize;
514 
515     uintptr_t miniRegs[FP_MINI_REGS_SIZE] = {0};
516     GetFramePointerMiniRegs(miniRegs);
517     regs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, miniRegs);
518     unwinder->SetRegs(regs);
519     size_t idx = 0;
520     uintptr_t pc, fp;
521     while (true) {
522         pc = regs->GetPc();
523         fp = regs->GetFp();
524         idx++;
525         if (!unwinder->FpStep(fp, pc, &context) || (pc == 0)) {
526             break;
527         }
528     };
529     ASSERT_EQ(idx, unwSize) << "StepTest004: idx:" << idx;
530     time_t elapsed = counter.Elapsed();
531     GTEST_LOG_(INFO) << "StepTest004: Elapsed: " << elapsed;
532     GTEST_LOG_(INFO) << "StepTest004: end.";
533 }
534 #endif
535 
536 /**
537  * @tc.name: DfxConfigTest001
538  * @tc.desc: test DfxConfig class functions
539  * @tc.type: FUNC
540  */
541 HWTEST_F(UnwinderTest, DfxConfigTest001, TestSize.Level2)
542 {
543     GTEST_LOG_(INFO) << "DfxConfigTest001: start.";
544     ASSERT_EQ(DfxConfig::GetConfig().logPersist, false);
545     ASSERT_EQ(DfxConfig::GetConfig().displayRegister, true);
546     ASSERT_EQ(DfxConfig::GetConfig().displayBacktrace, true);
547     ASSERT_EQ(DfxConfig::GetConfig().displayMaps, true);
548     ASSERT_EQ(DfxConfig::GetConfig().displayFaultStack, true);
549     ASSERT_EQ(DfxConfig::GetConfig().dumpOtherThreads, true);
550     ASSERT_EQ(DfxConfig::GetConfig().highAddressStep, 512);
551     ASSERT_EQ(DfxConfig::GetConfig().lowAddressStep, 16);
552     ASSERT_EQ(DfxConfig::GetConfig().maxFrameNums, 256);
553     GTEST_LOG_(INFO) << "DfxConfigTest001: end.";
554 }
555 
556 /**
557  * @tc.name: FillFrameTest001
558  * @tc.desc: test unwinder FillFrame interface
559  *  in local case
560  * @tc.type: FUNC
561  */
562 HWTEST_F(UnwinderTest, FillFrameTest001, TestSize.Level2)
563 {
564     GTEST_LOG_(INFO) << "FillFrameTest001: start.";
565     auto unwinder = std::make_shared<Unwinder>();
566     DfxFrame frame;
567     unwinder->FillFrame(frame);
568     GTEST_LOG_(INFO) << " when DfxFrame::map is null, frame.buildId.size() is 0";
569     ASSERT_EQ(frame.buildId.size(), 0);
570     string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so.noexit";
571     auto map = DfxMap::Create(testMap, sizeof(testMap));
572     frame.map = map;
573     unwinder->FillFrame(frame);
574     GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file not exist, frame.buildId.size() is 0";
575     ASSERT_EQ(frame.buildId.size(), 0);
576 #ifdef __arm__
577     testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so";
578 #else
579     testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so";
580 #endif
581     map = DfxMap::Create(testMap, sizeof(testMap));
582     frame.map = map;
583     unwinder->FillFrame(frame);
584     GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file exist, frame.buildId.size() is bigger than 0";
585     ASSERT_EQ(frame.buildId.size() == 0, false);
586     GTEST_LOG_(INFO) << "FillFrameTest001: end.";
587 }
588 
589 /**
590  * @tc.name: FillFramesTest001
591  * @tc.desc: test unwinder FillFrames interface
592  *  in local case
593  * @tc.type: FUNC
594  */
595 HWTEST_F(UnwinderTest, FillFramesTest001, TestSize.Level2)
596 {
597     GTEST_LOG_(INFO) << "FillFramesTest001: start.";
598 #ifdef __arm__
599     const string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so";
600 #else
601     const string testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so";
602 #endif
603     auto unwinder = std::make_shared<Unwinder>();
604     std::vector<DfxFrame> frames;
605     DfxFrame frame;
606     auto map = DfxMap::Create(testMap, sizeof(testMap));
607     frame.map = map;
608     frames.push_back(frame);
609     ASSERT_EQ(frames[0].buildId.size(), 0);
610     unwinder->FillFrames(frames);
611     ASSERT_EQ(frames[0].buildId.size() == 0, false);
612     GTEST_LOG_(INFO) << "FillFramesTest001: end.";
613 }
614 
615 #if defined(__arm__) || defined(__aarch64__)
616 /**
617  * @tc.name: UnwindLocalWithContextTest001
618  * @tc.desc: test unwinder UnwindLocalWithContext interface
619  *  in local case
620  * @tc.type: FUNC
621  */
622 HWTEST_F(UnwinderTest, UnwindLocalWithContextTest001, TestSize.Level2)
623 {
624     GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: start.";
625     auto regs = DfxRegs::Create();
626     auto regsData = regs->RawData();
627     GetLocalRegs(regsData);
628     ucontext_t context;
629     (void)memset_s(&context, sizeof(context), 0, sizeof(context));
630 #ifdef __arm__
631     context.uc_mcontext.arm_r0 = *(regs->GetReg(REG_ARM_R0));
632     context.uc_mcontext.arm_r1 = *(regs->GetReg(REG_ARM_R1));
633     context.uc_mcontext.arm_r2 = *(regs->GetReg(REG_ARM_R2));
634     context.uc_mcontext.arm_r3 = *(regs->GetReg(REG_ARM_R3));
635     context.uc_mcontext.arm_r4 = *(regs->GetReg(REG_ARM_R4));
636     context.uc_mcontext.arm_r5 = *(regs->GetReg(REG_ARM_R5));
637     context.uc_mcontext.arm_r6 = *(regs->GetReg(REG_ARM_R6));
638     context.uc_mcontext.arm_r7 = *(regs->GetReg(REG_ARM_R7));
639     context.uc_mcontext.arm_r8 = *(regs->GetReg(REG_ARM_R8));
640     context.uc_mcontext.arm_r9 = *(regs->GetReg(REG_ARM_R9));
641     context.uc_mcontext.arm_r10 = *(regs->GetReg(REG_ARM_R10));
642     context.uc_mcontext.arm_fp = *(regs->GetReg(REG_ARM_R11));
643     context.uc_mcontext.arm_ip = *(regs->GetReg(REG_ARM_R12));
644     context.uc_mcontext.arm_sp = *(regs->GetReg(REG_ARM_R13));
645     context.uc_mcontext.arm_lr = *(regs->GetReg(REG_ARM_R14));
646     context.uc_mcontext.arm_pc = *(regs->GetReg(REG_ARM_R15));
647 #else
648     for (int i = 0; i < REG_LAST; ++i) {
649         context.uc_mcontext.regs[i] = *(regs->GetReg(i));
650     }
651 #endif
652     auto unwinder = std::make_shared<Unwinder>();
653     ASSERT_TRUE(unwinder->UnwindLocalWithContext(context));
654     auto frames = unwinder->GetFrames();
655     GTEST_LOG_(INFO) << unwinder->GetFramesStr(frames);
656     ASSERT_GT(frames.size(), 1);
657     GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: end.";
658 }
659 #endif
660 
661 /**
662  * @tc.name: GetSymbolByPcTest001
663  * @tc.desc: test unwinder GetSymbolByPc interface
664  *  in local case
665  * @tc.type: FUNC
666  */
667 HWTEST_F(UnwinderTest, GetSymbolByPcTest001, TestSize.Level2)
668 {
669     GTEST_LOG_(INFO) << "GetSymbolByPcTest001: start.";
670     auto unwinder = std::make_shared<Unwinder>();
671     unwinder->UnwindLocal();
672     auto pcs = unwinder->GetPcs();
673     std::string funcName;
674     uint64_t funcOffset;
675     std::shared_ptr<DfxMaps> maps = std::make_shared<DfxMaps>();
676     ASSERT_FALSE(unwinder->GetSymbolByPc(0x00000000, maps, funcName, funcOffset)); // Find map is null
677     ASSERT_FALSE(unwinder->GetSymbolByPc(pcs[0], maps, funcName, funcOffset)); // Get elf is null
678     GTEST_LOG_(INFO) << "GetSymbolByPcTest001: end.";
679 }
680 } // namespace HiviewDFX
681 } // namepsace OHOS
682 
683