1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include <gtest/gtest.h>
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cstdio>
19800b99b8Sopenharmony_ci#include <malloc.h>
20800b99b8Sopenharmony_ci#include <map>
21800b99b8Sopenharmony_ci#include <securec.h>
22800b99b8Sopenharmony_ci#include <thread>
23800b99b8Sopenharmony_ci#include <unistd.h>
24800b99b8Sopenharmony_ci
25800b99b8Sopenharmony_ci#include "dfx_config.h"
26800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h"
27800b99b8Sopenharmony_ci#include "dfx_ptrace.h"
28800b99b8Sopenharmony_ci#include "dfx_regs_get.h"
29800b99b8Sopenharmony_ci#include "dfx_test_util.h"
30800b99b8Sopenharmony_ci#include "elapsed_time.h"
31800b99b8Sopenharmony_ci#include "unwinder.h"
32800b99b8Sopenharmony_ci
33800b99b8Sopenharmony_ci#if defined(__x86_64__)
34800b99b8Sopenharmony_ci#include <unwind.h> // GCC's internal unwinder, part of libgcc
35800b99b8Sopenharmony_ci#endif
36800b99b8Sopenharmony_ci
37800b99b8Sopenharmony_ciusing namespace testing;
38800b99b8Sopenharmony_ciusing namespace testing::ext;
39800b99b8Sopenharmony_ci
40800b99b8Sopenharmony_cinamespace OHOS {
41800b99b8Sopenharmony_cinamespace HiviewDFX {
42800b99b8Sopenharmony_ci#undef LOG_DOMAIN
43800b99b8Sopenharmony_ci#undef LOG_TAG
44800b99b8Sopenharmony_ci#define LOG_TAG "DfxUnwinderTest"
45800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
46800b99b8Sopenharmony_ci#define TIME_SLEEP 3
47800b99b8Sopenharmony_ci
48800b99b8Sopenharmony_ciclass UnwinderTest : public testing::Test {
49800b99b8Sopenharmony_cipublic:
50800b99b8Sopenharmony_ci    static void SetUpTestCase() {}
51800b99b8Sopenharmony_ci    static void TearDownTestCase() {}
52800b99b8Sopenharmony_ci    void SetUp() {}
53800b99b8Sopenharmony_ci    void TearDown() {}
54800b99b8Sopenharmony_ci
55800b99b8Sopenharmony_ci    std::map<int, std::shared_ptr<Unwinder>> unwinders_;
56800b99b8Sopenharmony_ci    const size_t skipFrameNum = 2;
57800b99b8Sopenharmony_ci};
58800b99b8Sopenharmony_ci
59800b99b8Sopenharmony_ci/**
60800b99b8Sopenharmony_ci * @tc.name: GetStackRangeTest001
61800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetStackRange interface in pid == tid
62800b99b8Sopenharmony_ci * @tc.type: FUNC
63800b99b8Sopenharmony_ci */
64800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetStackRangeTest001, TestSize.Level2)
65800b99b8Sopenharmony_ci{
66800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetStackRangeTest001: start.";
67800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
68800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1;
69800b99b8Sopenharmony_ci    uintptr_t stackTop = static_cast<uintptr_t>(-1);
70800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, GetStackRange(stackBottom, stackTop) is true";
71800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
72800b99b8Sopenharmony_ci    // When the param is less than -1, maps_ = null when method Unwinder is constructed
73800b99b8Sopenharmony_ci    auto unwinderNegative = std::make_shared<Unwinder>(-2);
74800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, GetStackRange(stackBottom, stackTop) is false";
75800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinderNegative->GetStackRange(stackBottom, stackTop));
76800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetStackRangeTest001: end.";
77800b99b8Sopenharmony_ci}
78800b99b8Sopenharmony_ci
79800b99b8Sopenharmony_ci/**
80800b99b8Sopenharmony_ci * @tc.name: GetStackRangeTest002
81800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetStackRange interface in pid != tid
82800b99b8Sopenharmony_ci * @tc.type: FUNC
83800b99b8Sopenharmony_ci */
84800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetStackRangeTest002, TestSize.Level2)
85800b99b8Sopenharmony_ci{
86800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetStackRangeTest002: start.";
87800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
88800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1;
89800b99b8Sopenharmony_ci    uintptr_t stackTop = static_cast<uintptr_t>(-1);
90800b99b8Sopenharmony_ci    bool result = false;
91800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "Run the function with thread will get pid != tid, "
92800b99b8Sopenharmony_ci                        "GetStackRange(stackBottom, stackTop) is true";
93800b99b8Sopenharmony_ci    std::thread th([unwinder, &stackBottom, &stackTop, &result] {
94800b99b8Sopenharmony_ci        result = unwinder->GetStackRange(stackBottom, stackTop);
95800b99b8Sopenharmony_ci    });
96800b99b8Sopenharmony_ci    if (th.joinable()) {
97800b99b8Sopenharmony_ci        th.join();
98800b99b8Sopenharmony_ci    }
99800b99b8Sopenharmony_ci    ASSERT_TRUE(result);
100800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetStackRangeTest002: end.";
101800b99b8Sopenharmony_ci}
102800b99b8Sopenharmony_ci
103800b99b8Sopenharmony_ci/**
104800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest001
105800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind
106800b99b8Sopenharmony_ci * @tc.type: FUNC
107800b99b8Sopenharmony_ci */
108800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest001, TestSize.Level2)
109800b99b8Sopenharmony_ci{
110800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest001: start.";
111800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
112800b99b8Sopenharmony_ci    ElapsedTime counter;
113800b99b8Sopenharmony_ci    MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
114800b99b8Sopenharmony_ci    unwinder->EnableMethodIdLocal(true);
115800b99b8Sopenharmony_ci    time_t elapsed1 = counter.Elapsed();
116800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderLocalTest001: Unwind:" << unwRet;
117800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
118800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
119800b99b8Sopenharmony_ci    time_t elapsed2 = counter.Elapsed();
120800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
121800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest001: frames:\n" << Unwinder::GetFramesStr(frames);
122800b99b8Sopenharmony_ci    unwRet = unwinder->UnwindLocal(false, false, DEFAULT_MAX_FRAME_NUM, skipFrameNum);
123800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderLocalTest001: Unwind:" << unwRet;
124800b99b8Sopenharmony_ci    auto frames2 = unwinder->GetFrames();
125800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), frames2.size());
126800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest001: frames2:\n" << Unwinder::GetFramesStr(frames2);
127800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest001: end.";
128800b99b8Sopenharmony_ci}
129800b99b8Sopenharmony_ci
130800b99b8Sopenharmony_ci/**
131800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest002
132800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind n counts
133800b99b8Sopenharmony_ci * @tc.type: FUNC
134800b99b8Sopenharmony_ci */
135800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest002, TestSize.Level2)
136800b99b8Sopenharmony_ci{
137800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest002: start.";
138800b99b8Sopenharmony_ci    unwinders_.clear();
139800b99b8Sopenharmony_ci    std::shared_ptr<Unwinder> unwinder = nullptr;
140800b99b8Sopenharmony_ci    pid_t pid = getpid();
141800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << pid;
142800b99b8Sopenharmony_ci    for (int i = 0; i < 10; ++i) {
143800b99b8Sopenharmony_ci        auto it = unwinders_.find(pid);
144800b99b8Sopenharmony_ci        if (it != unwinders_.end()) {
145800b99b8Sopenharmony_ci            unwinder = it->second;
146800b99b8Sopenharmony_ci        } else {
147800b99b8Sopenharmony_ci            unwinder = std::make_shared<Unwinder>();
148800b99b8Sopenharmony_ci        }
149800b99b8Sopenharmony_ci        ElapsedTime counter;
150800b99b8Sopenharmony_ci        MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
151800b99b8Sopenharmony_ci        time_t elapsed1 = counter.Elapsed();
152800b99b8Sopenharmony_ci        EXPECT_EQ(true, unwRet) << "UnwinderLocalTest002: Unwind:" << unwRet;
153800b99b8Sopenharmony_ci        auto frames = unwinder->GetFrames();
154800b99b8Sopenharmony_ci        ASSERT_GT(frames.size(), 1);
155800b99b8Sopenharmony_ci        time_t elapsed2 = counter.Elapsed();
156800b99b8Sopenharmony_ci        GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
157800b99b8Sopenharmony_ci        GTEST_LOG_(INFO) << "UnwinderLocalTest002: frames:\n" << Unwinder::GetFramesStr(frames);
158800b99b8Sopenharmony_ci        unwinders_[pid] = unwinder;
159800b99b8Sopenharmony_ci        sleep(1);
160800b99b8Sopenharmony_ci    };
161800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest002: end.";
162800b99b8Sopenharmony_ci}
163800b99b8Sopenharmony_ci
164800b99b8Sopenharmony_ci/**
165800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest003
166800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocal interface
167800b99b8Sopenharmony_ci * @tc.type: FUNC
168800b99b8Sopenharmony_ci */
169800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest003, TestSize.Level2)
170800b99b8Sopenharmony_ci{
171800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest003: start.";
172800b99b8Sopenharmony_ci    // When the param is less than -1, maps_ = null when method Unwinder is constructed
173800b99b8Sopenharmony_ci    auto unwinderNegative = std::make_shared<Unwinder>(-2);
174800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, "
175800b99b8Sopenharmony_ci                         "UnwindLocal(maxFrameNum, skipFrameNum) is false";
176800b99b8Sopenharmony_ci    ASSERT_FALSE(unwinderNegative->UnwindLocal());
177800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
178800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, "
179800b99b8Sopenharmony_ci                        "UnwindLocal(maxFrameNum, skipFrameNum) is true";
180800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->UnwindLocal());
181800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderLocalTest003: end.";
182800b99b8Sopenharmony_ci}
183800b99b8Sopenharmony_ci
184800b99b8Sopenharmony_ci/**
185800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest001
186800b99b8Sopenharmony_ci * @tc.desc: test unwinder remote unwind
187800b99b8Sopenharmony_ci * @tc.type: FUNC
188800b99b8Sopenharmony_ci */
189800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest001, TestSize.Level2)
190800b99b8Sopenharmony_ci{
191800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest001: start.";
192800b99b8Sopenharmony_ci    pid_t child = fork();
193800b99b8Sopenharmony_ci    if (child == 0) {
194800b99b8Sopenharmony_ci        sleep(TIME_SLEEP);
195800b99b8Sopenharmony_ci        _exit(0);
196800b99b8Sopenharmony_ci    }
197800b99b8Sopenharmony_ci
198800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
199800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(child);
200800b99b8Sopenharmony_ci    bool unwRet = DfxPtrace::Attach(child);
201800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: Attach:" << unwRet;
202800b99b8Sopenharmony_ci    ElapsedTime counter;
203800b99b8Sopenharmony_ci    unwRet = unwinder->UnwindRemote(child);
204800b99b8Sopenharmony_ci    time_t elapsed1 = counter.Elapsed();
205800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: unwRet:" << unwRet;
206800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
207800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
208800b99b8Sopenharmony_ci    time_t elapsed2 = counter.Elapsed();
209800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
210800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest001: frames:\n" << Unwinder::GetFramesStr(frames);
211800b99b8Sopenharmony_ci    unwRet = unwinder->UnwindRemote(child, false, DEFAULT_MAX_FRAME_NUM, skipFrameNum);
212800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: unwRet:" << unwRet;
213800b99b8Sopenharmony_ci    auto frames2 = unwinder->GetFrames();
214800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), frames2.size());
215800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest001: frames2:\n" << Unwinder::GetFramesStr(frames2);
216800b99b8Sopenharmony_ci    DfxPtrace::Detach(child);
217800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest001: end.";
218800b99b8Sopenharmony_ci}
219800b99b8Sopenharmony_ci
220800b99b8Sopenharmony_ci/**
221800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest002
222800b99b8Sopenharmony_ci * @tc.desc: test unwinder remote unwind n counts
223800b99b8Sopenharmony_ci * @tc.type: FUNC
224800b99b8Sopenharmony_ci */
225800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest002, TestSize.Level2)
226800b99b8Sopenharmony_ci{
227800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest002: start.";
228800b99b8Sopenharmony_ci    pid_t child = fork();
229800b99b8Sopenharmony_ci    if (child == 0) {
230800b99b8Sopenharmony_ci        sleep(TIME_SLEEP);
231800b99b8Sopenharmony_ci        _exit(0);
232800b99b8Sopenharmony_ci    }
233800b99b8Sopenharmony_ci
234800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
235800b99b8Sopenharmony_ci    unwinders_.clear();
236800b99b8Sopenharmony_ci    std::shared_ptr<Unwinder> unwinder = nullptr;
237800b99b8Sopenharmony_ci    bool unwRet = DfxPtrace::Attach(child);
238800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Attach:" << unwRet;
239800b99b8Sopenharmony_ci    for (int i = 0; i < 10; ++i) {
240800b99b8Sopenharmony_ci        auto it = unwinders_.find(child);
241800b99b8Sopenharmony_ci        if (it != unwinders_.end()) {
242800b99b8Sopenharmony_ci            unwinder = it->second;
243800b99b8Sopenharmony_ci        } else {
244800b99b8Sopenharmony_ci            unwinder = std::make_shared<Unwinder>(child);
245800b99b8Sopenharmony_ci        }
246800b99b8Sopenharmony_ci        ElapsedTime counter;
247800b99b8Sopenharmony_ci        unwRet = unwinder->UnwindRemote(child);
248800b99b8Sopenharmony_ci        time_t elapsed1 = counter.Elapsed();
249800b99b8Sopenharmony_ci        EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Unwind:" << unwRet;
250800b99b8Sopenharmony_ci        auto frames = unwinder->GetFrames();
251800b99b8Sopenharmony_ci        ASSERT_GT(frames.size(), 1);
252800b99b8Sopenharmony_ci        time_t elapsed2 = counter.Elapsed();
253800b99b8Sopenharmony_ci        GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
254800b99b8Sopenharmony_ci        GTEST_LOG_(INFO) << "UnwinderRemoteTest002: frames:\n" << Unwinder::GetFramesStr(frames);
255800b99b8Sopenharmony_ci        unwinders_[child] = unwinder;
256800b99b8Sopenharmony_ci        sleep(1);
257800b99b8Sopenharmony_ci    }
258800b99b8Sopenharmony_ci    DfxPtrace::Detach(child);
259800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest002: end.";
260800b99b8Sopenharmony_ci}
261800b99b8Sopenharmony_ci
262800b99b8Sopenharmony_ci/**
263800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest003
264800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindRemote interface
265800b99b8Sopenharmony_ci * @tc.type: FUNC
266800b99b8Sopenharmony_ci */
267800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest003, TestSize.Level2)
268800b99b8Sopenharmony_ci{
269800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest003: start.";
270800b99b8Sopenharmony_ci    // When the param is less than -1, pid_ < 0 when method Unwinder is constructed
271800b99b8Sopenharmony_ci    auto unwinderNegative = std::make_shared<Unwinder>(-2);
272800b99b8Sopenharmony_ci    size_t maxFrameNum = 64;
273800b99b8Sopenharmony_ci    size_t skipFrameNum = 0;
274800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "when pid <= 0, UnwindRemote(maxFrameNum, skipFrameNum) is false";
275800b99b8Sopenharmony_ci    ASSERT_FALSE(unwinderNegative->UnwindRemote(-2, maxFrameNum, skipFrameNum));
276800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderRemoteTest003: end.";
277800b99b8Sopenharmony_ci}
278800b99b8Sopenharmony_ci
279800b99b8Sopenharmony_ci/**
280800b99b8Sopenharmony_ci * @tc.name: UnwindTest001
281800b99b8Sopenharmony_ci * @tc.desc: test unwinder unwind interface in remote case
282800b99b8Sopenharmony_ci * @tc.type: FUNC
283800b99b8Sopenharmony_ci */
284800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest001, TestSize.Level2)
285800b99b8Sopenharmony_ci{
286800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest001: start.";
287800b99b8Sopenharmony_ci    pid_t child = fork();
288800b99b8Sopenharmony_ci    if (child == 0) {
289800b99b8Sopenharmony_ci        sleep(TIME_SLEEP);
290800b99b8Sopenharmony_ci        _exit(0);
291800b99b8Sopenharmony_ci    }
292800b99b8Sopenharmony_ci
293800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
294800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(child);
295800b99b8Sopenharmony_ci    bool unwRet = DfxPtrace::Attach(child);
296800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwindTest001: Attach:" << unwRet;
297800b99b8Sopenharmony_ci    auto regs = DfxRegs::CreateRemoteRegs(child);
298800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
299800b99b8Sopenharmony_ci    auto maps = DfxMaps::Create(child);
300800b99b8Sopenharmony_ci    UnwindContext context;
301800b99b8Sopenharmony_ci    context.pid = child;
302800b99b8Sopenharmony_ci    context.regs = regs;
303800b99b8Sopenharmony_ci    context.maps = maps;
304800b99b8Sopenharmony_ci    ElapsedTime counter;
305800b99b8Sopenharmony_ci    unwRet = unwinder->Unwind(&context);
306800b99b8Sopenharmony_ci    time_t elapsed1 = counter.Elapsed();
307800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwindTest001: Unwind:" << unwRet;
308800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
309800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
310800b99b8Sopenharmony_ci    time_t elapsed2 = counter.Elapsed();
311800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2;
312800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest001: frames:\n" << Unwinder::GetFramesStr(frames);
313800b99b8Sopenharmony_ci    DfxPtrace::Detach(child);
314800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest001: end.";
315800b99b8Sopenharmony_ci}
316800b99b8Sopenharmony_ci
317800b99b8Sopenharmony_ci/**
318800b99b8Sopenharmony_ci * @tc.name: UnwindTest002
319800b99b8Sopenharmony_ci * @tc.desc: test unwinder unwind interface in local case
320800b99b8Sopenharmony_ci * @tc.type: FUNC
321800b99b8Sopenharmony_ci */
322800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest002, TestSize.Level2)
323800b99b8Sopenharmony_ci{
324800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest002: start.";
325800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
326800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
327800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
328800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest002: GetStackRange.";
329800b99b8Sopenharmony_ci    UnwindContext context;
330800b99b8Sopenharmony_ci    context.stackCheck = false;
331800b99b8Sopenharmony_ci    context.stackBottom = stackBottom;
332800b99b8Sopenharmony_ci    context.stackTop = stackTop;
333800b99b8Sopenharmony_ci
334800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
335800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
336800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
337800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
338800b99b8Sopenharmony_ci    auto maps = DfxMaps::Create(getpid());
339800b99b8Sopenharmony_ci    context.pid = UNWIND_TYPE_LOCAL;
340800b99b8Sopenharmony_ci    context.regs = regs;
341800b99b8Sopenharmony_ci    context.maps = maps;
342800b99b8Sopenharmony_ci    bool unwRet = unwinder->Unwind(&context);
343800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwindTest002: unwRet:" << unwRet;
344800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
345800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
346800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest002:frames:\n" << Unwinder::GetFramesStr(frames);
347800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest002: end.";
348800b99b8Sopenharmony_ci}
349800b99b8Sopenharmony_ci
350800b99b8Sopenharmony_ci/**
351800b99b8Sopenharmony_ci * @tc.name: UnwindTest003
352800b99b8Sopenharmony_ci * @tc.desc: test GetLastErrorCode GetLastErrorAddr functions
353800b99b8Sopenharmony_ci *  in local case
354800b99b8Sopenharmony_ci * @tc.type: FUNC
355800b99b8Sopenharmony_ci */
356800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest003, TestSize.Level2)
357800b99b8Sopenharmony_ci{
358800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest003: start.";
359800b99b8Sopenharmony_ci
360800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
361800b99b8Sopenharmony_ci    unwinder->IgnoreMixstack(true);
362800b99b8Sopenharmony_ci    MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
363800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "UnwindTest003: Unwind ret:" << unwRet;
364800b99b8Sopenharmony_ci    unwinder->EnableFillFrames(false);
365800b99b8Sopenharmony_ci    const auto& frames = unwinder->GetFrames();
366800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1) << "frames.size() error";
367800b99b8Sopenharmony_ci
368800b99b8Sopenharmony_ci    uint16_t errorCode = unwinder->GetLastErrorCode();
369800b99b8Sopenharmony_ci    uint64_t errorAddr = unwinder->GetLastErrorAddr();
370800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "errorCode:" << errorCode;
371800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "errorAddr:" << errorAddr;
372800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest003: end.";
373800b99b8Sopenharmony_ci}
374800b99b8Sopenharmony_ci
375800b99b8Sopenharmony_ci/**
376800b99b8Sopenharmony_ci * @tc.name: UnwindTest004
377800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind for
378800b99b8Sopenharmony_ci * GetFramesStr(const std::vector<std::shared_ptr<DfxFrame>>& frames)
379800b99b8Sopenharmony_ci * @tc.type: FUNC
380800b99b8Sopenharmony_ci */
381800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest004, TestSize.Level2)
382800b99b8Sopenharmony_ci{
383800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest004: start.";
384800b99b8Sopenharmony_ci
385800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
386800b99b8Sopenharmony_ci    ElapsedTime counter;
387800b99b8Sopenharmony_ci    MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal();
388800b99b8Sopenharmony_ci    ASSERT_EQ(true, unwRet) << "UnwindTest004: Unwind:" << unwRet;
389800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
390800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
391800b99b8Sopenharmony_ci
392800b99b8Sopenharmony_ci    auto framesVec = DfxFrameFormatter::ConvertFrames(frames);
393800b99b8Sopenharmony_ci    std::string framesStr = DfxFrameFormatter::GetFramesStr(framesVec);
394800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest004: frames:\n" << framesStr;
395800b99b8Sopenharmony_ci
396800b99b8Sopenharmony_ci    string log[] = {"pc", "test_unwind", "#00", "#01", "#02"};
397800b99b8Sopenharmony_ci    int len = sizeof(log) / sizeof(log[0]);
398800b99b8Sopenharmony_ci    int count = GetKeywordsNum(framesStr, log, len);
399800b99b8Sopenharmony_ci    ASSERT_EQ(count, len) << "UnwindTest004 Failed";
400800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindTest004: end.";
401800b99b8Sopenharmony_ci}
402800b99b8Sopenharmony_ci
403800b99b8Sopenharmony_ci/**
404800b99b8Sopenharmony_ci * @tc.name: StepTest001
405800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in remote case
406800b99b8Sopenharmony_ci * @tc.type: FUNC
407800b99b8Sopenharmony_ci */
408800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest001, TestSize.Level2)
409800b99b8Sopenharmony_ci{
410800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest001: start.";
411800b99b8Sopenharmony_ci    pid_t child = fork();
412800b99b8Sopenharmony_ci    if (child == 0) {
413800b99b8Sopenharmony_ci        sleep(TIME_SLEEP);
414800b99b8Sopenharmony_ci        _exit(0);
415800b99b8Sopenharmony_ci    }
416800b99b8Sopenharmony_ci
417800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
418800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(child);
419800b99b8Sopenharmony_ci    bool unwRet = DfxPtrace::Attach(child);
420800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "StepTest001: Attach:" << unwRet;
421800b99b8Sopenharmony_ci    auto regs = DfxRegs::CreateRemoteRegs(child);
422800b99b8Sopenharmony_ci    auto maps = DfxMaps::Create(child);
423800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
424800b99b8Sopenharmony_ci    UnwindContext context;
425800b99b8Sopenharmony_ci    context.pid = child;
426800b99b8Sopenharmony_ci    context.regs = regs;
427800b99b8Sopenharmony_ci    context.maps = maps;
428800b99b8Sopenharmony_ci
429800b99b8Sopenharmony_ci    uintptr_t pc, sp;
430800b99b8Sopenharmony_ci    pc = regs->GetPc();
431800b99b8Sopenharmony_ci    sp = regs->GetSp();
432800b99b8Sopenharmony_ci    std::shared_ptr<DfxMap> map = nullptr;
433800b99b8Sopenharmony_ci    ASSERT_TRUE(maps->FindMapByAddr(pc, map));
434800b99b8Sopenharmony_ci    context.map = map;
435800b99b8Sopenharmony_ci    unwRet = unwinder->Step(pc, sp, &context);
436800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest001: Unwind:" << unwRet;
437800b99b8Sopenharmony_ci    DfxPtrace::Detach(child);
438800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest001: end.";
439800b99b8Sopenharmony_ci}
440800b99b8Sopenharmony_ci
441800b99b8Sopenharmony_ci/**
442800b99b8Sopenharmony_ci * @tc.name: StepTest002
443800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in local case
444800b99b8Sopenharmony_ci * @tc.type: FUNC
445800b99b8Sopenharmony_ci */
446800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest002, TestSize.Level2)
447800b99b8Sopenharmony_ci{
448800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest002: start.";
449800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
450800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
451800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
452800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest002: GetStackRange.";
453800b99b8Sopenharmony_ci    auto maps = DfxMaps::Create(getpid());
454800b99b8Sopenharmony_ci    UnwindContext context;
455800b99b8Sopenharmony_ci    context.pid = UNWIND_TYPE_LOCAL;
456800b99b8Sopenharmony_ci    context.stackCheck = false;
457800b99b8Sopenharmony_ci    context.stackBottom = stackBottom;
458800b99b8Sopenharmony_ci    context.stackTop = stackTop;
459800b99b8Sopenharmony_ci
460800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
461800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
462800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
463800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
464800b99b8Sopenharmony_ci    context.regs = regs;
465800b99b8Sopenharmony_ci    context.maps = maps;
466800b99b8Sopenharmony_ci
467800b99b8Sopenharmony_ci    uintptr_t pc, sp;
468800b99b8Sopenharmony_ci    pc = regs->GetPc();
469800b99b8Sopenharmony_ci    sp = regs->GetSp();
470800b99b8Sopenharmony_ci    bool unwRet = unwinder->Step(pc, sp, &context);
471800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest002: unwRet:" << unwRet;
472800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest002: end.";
473800b99b8Sopenharmony_ci}
474800b99b8Sopenharmony_ci
475800b99b8Sopenharmony_ci#if defined(__aarch64__)
476800b99b8Sopenharmony_ci/**
477800b99b8Sopenharmony_ci * @tc.name: StepTest003
478800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindByFp interface in remote case
479800b99b8Sopenharmony_ci * @tc.type: FUNC
480800b99b8Sopenharmony_ci */
481800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest003, TestSize.Level2)
482800b99b8Sopenharmony_ci{
483800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest003: start.";
484800b99b8Sopenharmony_ci    pid_t child = fork();
485800b99b8Sopenharmony_ci    if (child == 0) {
486800b99b8Sopenharmony_ci        sleep(TIME_SLEEP);
487800b99b8Sopenharmony_ci        _exit(0);
488800b99b8Sopenharmony_ci    }
489800b99b8Sopenharmony_ci
490800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid();
491800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(child);
492800b99b8Sopenharmony_ci    bool unwRet = DfxPtrace::Attach(child);
493800b99b8Sopenharmony_ci    EXPECT_EQ(true, unwRet) << "StepTest003: Attach:" << unwRet;
494800b99b8Sopenharmony_ci    auto regs = DfxRegs::CreateRemoteRegs(child);
495800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
496800b99b8Sopenharmony_ci    UnwindContext context;
497800b99b8Sopenharmony_ci    context.pid = child;
498800b99b8Sopenharmony_ci    ElapsedTime counter;
499800b99b8Sopenharmony_ci    unwRet = unwinder->UnwindByFp(&context);
500800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest003: unwind:" << unwRet;
501800b99b8Sopenharmony_ci    DfxPtrace::Detach(child);
502800b99b8Sopenharmony_ci    time_t elapsed = counter.Elapsed();
503800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest003: Elapsed: " << elapsed;
504800b99b8Sopenharmony_ci    auto pcs = unwinder->GetPcs();
505800b99b8Sopenharmony_ci    std::vector<DfxFrame> frames;
506800b99b8Sopenharmony_ci    unwinder->GetFramesByPcs(frames, pcs);
507800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
508800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest003: frames:\n" << Unwinder::GetFramesStr(frames);
509800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest003: end.";
510800b99b8Sopenharmony_ci}
511800b99b8Sopenharmony_ci
512800b99b8Sopenharmony_ci/**
513800b99b8Sopenharmony_ci * @tc.name: StepTest004
514800b99b8Sopenharmony_ci * @tc.desc: test unwinder FpStep interface in local case
515800b99b8Sopenharmony_ci * @tc.type: FUNC
516800b99b8Sopenharmony_ci */
517800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest004, TestSize.Level2)
518800b99b8Sopenharmony_ci{
519800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest004: start.";
520800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
521800b99b8Sopenharmony_ci    ElapsedTime counter;
522800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
523800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
524800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest004: GetStackRange.";
525800b99b8Sopenharmony_ci
526800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
527800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
528800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
529800b99b8Sopenharmony_ci    UnwindContext context;
530800b99b8Sopenharmony_ci    context.pid = UNWIND_TYPE_LOCAL;
531800b99b8Sopenharmony_ci    context.stackCheck = false;
532800b99b8Sopenharmony_ci    context.stackBottom = stackBottom;
533800b99b8Sopenharmony_ci    context.stackTop = stackTop;
534800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
535800b99b8Sopenharmony_ci
536800b99b8Sopenharmony_ci    bool unwRet = unwinder->UnwindByFp(&context);
537800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest004: unwRet:" << unwRet;
538800b99b8Sopenharmony_ci    auto unwSize = unwinder->GetPcs().size();
539800b99b8Sopenharmony_ci    ASSERT_GT(unwSize, 1) << "pcs.size() error";
540800b99b8Sopenharmony_ci
541800b99b8Sopenharmony_ci    uintptr_t miniRegs[FP_MINI_REGS_SIZE] = {0};
542800b99b8Sopenharmony_ci    GetFramePointerMiniRegs(miniRegs, sizeof(miniRegs) / sizeof(miniRegs[0]));
543800b99b8Sopenharmony_ci    regs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, miniRegs, sizeof(miniRegs) / sizeof(miniRegs[0]));
544800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
545800b99b8Sopenharmony_ci    size_t idx = 0;
546800b99b8Sopenharmony_ci    uintptr_t pc, fp;
547800b99b8Sopenharmony_ci    while (true) {
548800b99b8Sopenharmony_ci        pc = regs->GetPc();
549800b99b8Sopenharmony_ci        fp = regs->GetFp();
550800b99b8Sopenharmony_ci        idx++;
551800b99b8Sopenharmony_ci        if (!unwinder->FpStep(fp, pc, &context) || (pc == 0)) {
552800b99b8Sopenharmony_ci            break;
553800b99b8Sopenharmony_ci        }
554800b99b8Sopenharmony_ci    };
555800b99b8Sopenharmony_ci    ASSERT_EQ(idx, unwSize) << "StepTest004: idx:" << idx;
556800b99b8Sopenharmony_ci    time_t elapsed = counter.Elapsed();
557800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest004: Elapsed: " << elapsed;
558800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest004: end.";
559800b99b8Sopenharmony_ci}
560800b99b8Sopenharmony_ci#endif
561800b99b8Sopenharmony_ci
562800b99b8Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__)
563800b99b8Sopenharmony_ci/**
564800b99b8Sopenharmony_ci * @tc.name: StepTest005
565800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in lr callback with apply failed case
566800b99b8Sopenharmony_ci * @tc.type: FUNC
567800b99b8Sopenharmony_ci */
568800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest005, TestSize.Level2)
569800b99b8Sopenharmony_ci{
570800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest005: start.";
571800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
572800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
573800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
574800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest005: GetStackRange.";
575800b99b8Sopenharmony_ci
576800b99b8Sopenharmony_ci    UnwindContext context;
577800b99b8Sopenharmony_ci    context.pid = UNWIND_TYPE_LOCAL;
578800b99b8Sopenharmony_ci    context.stackCheck = false;
579800b99b8Sopenharmony_ci    context.stackBottom = stackBottom;
580800b99b8Sopenharmony_ci    context.stackTop = stackTop;
581800b99b8Sopenharmony_ci
582800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
583800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
584800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
585800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
586800b99b8Sopenharmony_ci    context.regs = regs;
587800b99b8Sopenharmony_ci    context.maps = unwinder->GetMaps();
588800b99b8Sopenharmony_ci
589800b99b8Sopenharmony_ci    uintptr_t lr = *(regs->GetReg(REG_LR));
590800b99b8Sopenharmony_ci    uintptr_t pc = regs->GetPc();
591800b99b8Sopenharmony_ci    uintptr_t failSp = stackTop + 1; // arm cfa get from sp
592800b99b8Sopenharmony_ci    regs->SetSp(failSp);
593800b99b8Sopenharmony_ci    uintptr_t failFp = stackTop + 1; // arm64 cfa get from fp
594800b99b8Sopenharmony_ci    regs->SetFp(failFp);
595800b99b8Sopenharmony_ci    bool unwRet = unwinder->Step(pc, failSp, &context);
596800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest005: unwRet:" << unwRet;
597800b99b8Sopenharmony_ci    ASSERT_EQ(lr, pc) << "StepTest005: lr callback";
598800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest005: end.";
599800b99b8Sopenharmony_ci}
600800b99b8Sopenharmony_ci
601800b99b8Sopenharmony_ci/**
602800b99b8Sopenharmony_ci * @tc.name: StepTest006
603800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in lr callback with step failed case
604800b99b8Sopenharmony_ci * @tc.type: FUNC
605800b99b8Sopenharmony_ci */
606800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest006, TestSize.Level2)
607800b99b8Sopenharmony_ci{
608800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest006: start.";
609800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
610800b99b8Sopenharmony_ci    uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
611800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop));
612800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest006: GetStackRange.";
613800b99b8Sopenharmony_ci
614800b99b8Sopenharmony_ci    UnwindContext context;
615800b99b8Sopenharmony_ci    context.pid = UNWIND_TYPE_LOCAL;
616800b99b8Sopenharmony_ci    context.stackCheck = true;
617800b99b8Sopenharmony_ci    context.stackBottom = stackBottom;
618800b99b8Sopenharmony_ci    context.stackTop = stackTop;
619800b99b8Sopenharmony_ci
620800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
621800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
622800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
623800b99b8Sopenharmony_ci    unwinder->SetRegs(regs);
624800b99b8Sopenharmony_ci    context.regs = regs;
625800b99b8Sopenharmony_ci    context.maps = unwinder->GetMaps();
626800b99b8Sopenharmony_ci
627800b99b8Sopenharmony_ci    uintptr_t lr = *(regs->GetReg(REG_LR));
628800b99b8Sopenharmony_ci    uintptr_t sp = regs->GetSp();
629800b99b8Sopenharmony_ci    uintptr_t failPc = stackTop + 1;
630800b99b8Sopenharmony_ci    regs->SetPc(failPc);
631800b99b8Sopenharmony_ci    bool unwRet = unwinder->Step(failPc, sp, &context);
632800b99b8Sopenharmony_ci    ASSERT_TRUE(unwRet) << "StepTest006: unwRet:" << unwRet;
633800b99b8Sopenharmony_ci    ASSERT_EQ(lr, failPc) << "StepTest006: lr callback";
634800b99b8Sopenharmony_ci
635800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "StepTest006: end.";
636800b99b8Sopenharmony_ci}
637800b99b8Sopenharmony_ci#endif
638800b99b8Sopenharmony_ci
639800b99b8Sopenharmony_ci/**
640800b99b8Sopenharmony_ci * @tc.name: DfxConfigTest001
641800b99b8Sopenharmony_ci * @tc.desc: test DfxConfig class functions
642800b99b8Sopenharmony_ci * @tc.type: FUNC
643800b99b8Sopenharmony_ci */
644800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, DfxConfigTest001, TestSize.Level2)
645800b99b8Sopenharmony_ci{
646800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "DfxConfigTest001: start.";
647800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().displayRegister, true);
648800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().displayBacktrace, true);
649800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().displayMaps, true);
650800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().displayFaultStack, true);
651800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().dumpOtherThreads, true);
652800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().highAddressStep, 512);
653800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().lowAddressStep, 16);
654800b99b8Sopenharmony_ci    ASSERT_EQ(DfxConfig::GetConfig().maxFrameNums, 256);
655800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "DfxConfigTest001: end.";
656800b99b8Sopenharmony_ci}
657800b99b8Sopenharmony_ci
658800b99b8Sopenharmony_ci/**
659800b99b8Sopenharmony_ci * @tc.name: FillFrameTest001
660800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillFrame interface
661800b99b8Sopenharmony_ci *  in local case
662800b99b8Sopenharmony_ci * @tc.type: FUNC
663800b99b8Sopenharmony_ci */
664800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillFrameTest001, TestSize.Level2)
665800b99b8Sopenharmony_ci{
666800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillFrameTest001: start.";
667800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
668800b99b8Sopenharmony_ci    DfxFrame frame;
669800b99b8Sopenharmony_ci    unwinder->FillFrame(frame);
670800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << " when DfxFrame::map is null, frame.buildId.size() is 0";
671800b99b8Sopenharmony_ci    ASSERT_EQ(frame.buildId.size(), 0);
672800b99b8Sopenharmony_ci    string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so.noexit";
673800b99b8Sopenharmony_ci    auto map = DfxMap::Create(testMap, sizeof(testMap));
674800b99b8Sopenharmony_ci    frame.map = map;
675800b99b8Sopenharmony_ci    unwinder->FillFrame(frame);
676800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file not exist, frame.buildId.size() is 0";
677800b99b8Sopenharmony_ci    ASSERT_EQ(frame.buildId.size(), 0);
678800b99b8Sopenharmony_ci#ifdef __arm__
679800b99b8Sopenharmony_ci    testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so";
680800b99b8Sopenharmony_ci#else
681800b99b8Sopenharmony_ci    testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so";
682800b99b8Sopenharmony_ci#endif
683800b99b8Sopenharmony_ci    map = DfxMap::Create(testMap, sizeof(testMap));
684800b99b8Sopenharmony_ci    frame.map = map;
685800b99b8Sopenharmony_ci    unwinder->FillFrame(frame);
686800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file exist, frame.buildId.size() is bigger than 0";
687800b99b8Sopenharmony_ci    ASSERT_EQ(frame.buildId.size() == 0, false);
688800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillFrameTest001: end.";
689800b99b8Sopenharmony_ci}
690800b99b8Sopenharmony_ci
691800b99b8Sopenharmony_ci/**
692800b99b8Sopenharmony_ci * @tc.name: FillJsFrameTest001
693800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillJsFrame interface
694800b99b8Sopenharmony_ci *  in local case
695800b99b8Sopenharmony_ci * @tc.type: FUNC
696800b99b8Sopenharmony_ci */
697800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillJsFrameTest001, TestSize.Level2)
698800b99b8Sopenharmony_ci{
699800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillJsFrameTest001: start.";
700800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
701800b99b8Sopenharmony_ci    DfxFrame frame;
702800b99b8Sopenharmony_ci    unwinder->FillJsFrame(frame);
703800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << " when DfxFrame::map is null, frame.map is nullptr";
704800b99b8Sopenharmony_ci    ASSERT_EQ(frame.map, nullptr);
705800b99b8Sopenharmony_ci    string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so";
706800b99b8Sopenharmony_ci    auto map = DfxMap::Create(testMap, sizeof(testMap));
707800b99b8Sopenharmony_ci    frame.map = map;
708800b99b8Sopenharmony_ci    unwinder->FillJsFrame(frame);
709800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file exist, frame.map.GetHap is not nullptr";
710800b99b8Sopenharmony_ci    ASSERT_NE(frame.map->GetHap(), nullptr);
711800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillJsFrameTest001: end.";
712800b99b8Sopenharmony_ci}
713800b99b8Sopenharmony_ci
714800b99b8Sopenharmony_ci/**
715800b99b8Sopenharmony_ci * @tc.name: FillFramesTest001
716800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillFrames interface
717800b99b8Sopenharmony_ci *  in local case
718800b99b8Sopenharmony_ci * @tc.type: FUNC
719800b99b8Sopenharmony_ci */
720800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillFramesTest001, TestSize.Level2)
721800b99b8Sopenharmony_ci{
722800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillFramesTest001: start.";
723800b99b8Sopenharmony_ci#ifdef __arm__
724800b99b8Sopenharmony_ci    const string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so";
725800b99b8Sopenharmony_ci#else
726800b99b8Sopenharmony_ci    const string testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so";
727800b99b8Sopenharmony_ci#endif
728800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
729800b99b8Sopenharmony_ci    std::vector<DfxFrame> frames;
730800b99b8Sopenharmony_ci    DfxFrame frame;
731800b99b8Sopenharmony_ci    auto map = DfxMap::Create(testMap, sizeof(testMap));
732800b99b8Sopenharmony_ci    frame.map = map;
733800b99b8Sopenharmony_ci    frames.push_back(frame);
734800b99b8Sopenharmony_ci    ASSERT_EQ(frames[0].buildId.size(), 0);
735800b99b8Sopenharmony_ci    unwinder->FillFrames(frames);
736800b99b8Sopenharmony_ci    ASSERT_EQ(frames[0].buildId.size() == 0, false);
737800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "FillFramesTest001: end.";
738800b99b8Sopenharmony_ci}
739800b99b8Sopenharmony_ci
740800b99b8Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__)
741800b99b8Sopenharmony_ci/**
742800b99b8Sopenharmony_ci * @tc.name: UnwindLocalWithContextTest001
743800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocalWithContext interface
744800b99b8Sopenharmony_ci *  in local case
745800b99b8Sopenharmony_ci * @tc.type: FUNC
746800b99b8Sopenharmony_ci */
747800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalWithContextTest001, TestSize.Level2)
748800b99b8Sopenharmony_ci{
749800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: start.";
750800b99b8Sopenharmony_ci    auto regs = DfxRegs::Create();
751800b99b8Sopenharmony_ci    auto regsData = regs->RawData();
752800b99b8Sopenharmony_ci    GetLocalRegs(regsData);
753800b99b8Sopenharmony_ci    ucontext_t context;
754800b99b8Sopenharmony_ci    (void)memset_s(&context, sizeof(context), 0, sizeof(context));
755800b99b8Sopenharmony_ci#ifdef __arm__
756800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r0 = *(regs->GetReg(REG_ARM_R0));
757800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r1 = *(regs->GetReg(REG_ARM_R1));
758800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r2 = *(regs->GetReg(REG_ARM_R2));
759800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r3 = *(regs->GetReg(REG_ARM_R3));
760800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r4 = *(regs->GetReg(REG_ARM_R4));
761800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r5 = *(regs->GetReg(REG_ARM_R5));
762800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r6 = *(regs->GetReg(REG_ARM_R6));
763800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r7 = *(regs->GetReg(REG_ARM_R7));
764800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r8 = *(regs->GetReg(REG_ARM_R8));
765800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r9 = *(regs->GetReg(REG_ARM_R9));
766800b99b8Sopenharmony_ci    context.uc_mcontext.arm_r10 = *(regs->GetReg(REG_ARM_R10));
767800b99b8Sopenharmony_ci    context.uc_mcontext.arm_fp = *(regs->GetReg(REG_ARM_R11));
768800b99b8Sopenharmony_ci    context.uc_mcontext.arm_ip = *(regs->GetReg(REG_ARM_R12));
769800b99b8Sopenharmony_ci    context.uc_mcontext.arm_sp = *(regs->GetReg(REG_ARM_R13));
770800b99b8Sopenharmony_ci    context.uc_mcontext.arm_lr = *(regs->GetReg(REG_ARM_R14));
771800b99b8Sopenharmony_ci    context.uc_mcontext.arm_pc = *(regs->GetReg(REG_ARM_R15));
772800b99b8Sopenharmony_ci#else
773800b99b8Sopenharmony_ci    for (int i = 0; i < REG_LAST; ++i) {
774800b99b8Sopenharmony_ci        context.uc_mcontext.regs[i] = *(regs->GetReg(i));
775800b99b8Sopenharmony_ci    }
776800b99b8Sopenharmony_ci#endif
777800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
778800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->UnwindLocalWithContext(context));
779800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
780800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
781800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: frames:\n" << Unwinder::GetFramesStr(frames);
782800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: end.";
783800b99b8Sopenharmony_ci}
784800b99b8Sopenharmony_ci#endif
785800b99b8Sopenharmony_ci
786800b99b8Sopenharmony_cistatic int32_t g_tid = 0;
787800b99b8Sopenharmony_cistatic std::mutex g_mutex;
788800b99b8Sopenharmony_ci__attribute__((noinline)) void ThreadTest002()
789800b99b8Sopenharmony_ci{
790800b99b8Sopenharmony_ci    printf("ThreadTest002\n");
791800b99b8Sopenharmony_ci    g_mutex.lock();
792800b99b8Sopenharmony_ci    g_mutex.unlock();
793800b99b8Sopenharmony_ci}
794800b99b8Sopenharmony_ci
795800b99b8Sopenharmony_ci__attribute__((noinline)) void ThreadTest001()
796800b99b8Sopenharmony_ci{
797800b99b8Sopenharmony_ci    g_tid = gettid();
798800b99b8Sopenharmony_ci    printf("ThreadTest001: tid: %d\n", g_tid);
799800b99b8Sopenharmony_ci    ThreadTest002();
800800b99b8Sopenharmony_ci}
801800b99b8Sopenharmony_ci
802800b99b8Sopenharmony_ci/**
803800b99b8Sopenharmony_ci * @tc.name: UnwindLocalWithTidTest001
804800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocalWithTid interface
805800b99b8Sopenharmony_ci *  in local case
806800b99b8Sopenharmony_ci * @tc.type: FUNC
807800b99b8Sopenharmony_ci */
808800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalWithTidTest001, TestSize.Level2)
809800b99b8Sopenharmony_ci{
810800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: start.";
811800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
812800b99b8Sopenharmony_ci    g_mutex.lock();
813800b99b8Sopenharmony_ci    std::thread unwThread(ThreadTest001);
814800b99b8Sopenharmony_ci    sleep(1);
815800b99b8Sopenharmony_ci    if (g_tid <= 0) {
816800b99b8Sopenharmony_ci        FAIL() << "UnwindLocalWithTidTest001: Failed to create child thread.\n";
817800b99b8Sopenharmony_ci    }
818800b99b8Sopenharmony_ci    ASSERT_TRUE(unwinder->UnwindLocalWithTid(g_tid));
819800b99b8Sopenharmony_ci#if defined(__aarch64__)
820800b99b8Sopenharmony_ci    auto pcs = unwinder->GetPcs();
821800b99b8Sopenharmony_ci    std::vector<DfxFrame> frames;
822800b99b8Sopenharmony_ci    unwinder->GetFramesByPcs(frames, pcs);
823800b99b8Sopenharmony_ci#else
824800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
825800b99b8Sopenharmony_ci#endif
826800b99b8Sopenharmony_ci    ASSERT_GT(frames.size(), 1);
827800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: frames:\n" << Unwinder::GetFramesStr(frames);
828800b99b8Sopenharmony_ci    g_mutex.unlock();
829800b99b8Sopenharmony_ci    g_tid = 0;
830800b99b8Sopenharmony_ci    if (unwThread.joinable()) {
831800b99b8Sopenharmony_ci        unwThread.join();
832800b99b8Sopenharmony_ci    }
833800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: end.";
834800b99b8Sopenharmony_ci}
835800b99b8Sopenharmony_ci
836800b99b8Sopenharmony_ci#if defined(__x86_64__)
837800b99b8Sopenharmony_cistatic _Unwind_Reason_Code TraceFunc(_Unwind_Context *ctx, void *d)
838800b99b8Sopenharmony_ci{
839800b99b8Sopenharmony_ci    int *depth = (int*)d;
840800b99b8Sopenharmony_ci    printf("\t#%d: program counter at %p\n", *depth, reinterpret_cast<void *>(_Unwind_GetIP(ctx)));
841800b99b8Sopenharmony_ci    (*depth)++;
842800b99b8Sopenharmony_ci    return _URC_NO_REASON;
843800b99b8Sopenharmony_ci}
844800b99b8Sopenharmony_ci
845800b99b8Sopenharmony_cistatic void PrintUnwindBacktrace()
846800b99b8Sopenharmony_ci{
847800b99b8Sopenharmony_ci    int depth = 0;
848800b99b8Sopenharmony_ci    _Unwind_Backtrace(&TraceFunc, &depth);
849800b99b8Sopenharmony_ci}
850800b99b8Sopenharmony_ci
851800b99b8Sopenharmony_ci/**
852800b99b8Sopenharmony_ci * @tc.name: UnwindLocalX86_64Test001
853800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocal interface
854800b99b8Sopenharmony_ci * @tc.type: FUNC
855800b99b8Sopenharmony_ci */
856800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalX86_64Test001, TestSize.Level2)
857800b99b8Sopenharmony_ci{
858800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: start.";
859800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
860800b99b8Sopenharmony_ci    if (unwinder->UnwindLocal()) {
861800b99b8Sopenharmony_ci        auto frames = unwinder->GetFrames();
862800b99b8Sopenharmony_ci        printf("Unwinder frame size: %zu\n", frames.size());
863800b99b8Sopenharmony_ci        auto framesStr = Unwinder::GetFramesStr(frames);
864800b99b8Sopenharmony_ci        printf("Unwinder frames:\n%s\n", framesStr.c_str());
865800b99b8Sopenharmony_ci        ASSERT_GT(frames.size(), 0);
866800b99b8Sopenharmony_ci    }
867800b99b8Sopenharmony_ci
868800b99b8Sopenharmony_ci    PrintUnwindBacktrace();
869800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: end.";
870800b99b8Sopenharmony_ci}
871800b99b8Sopenharmony_ci
872800b99b8Sopenharmony_ci/**
873800b99b8Sopenharmony_ci * @tc.name: UnwindRemoteX86_64Test001
874800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindRemote interface
875800b99b8Sopenharmony_ci * @tc.type: FUNC
876800b99b8Sopenharmony_ci */
877800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindRemoteX86_64Test001, TestSize.Level2)
878800b99b8Sopenharmony_ci{
879800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: start.";
880800b99b8Sopenharmony_ci    const pid_t initPid = 1;
881800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(initPid);
882800b99b8Sopenharmony_ci    DfxPtrace::Attach(initPid);
883800b99b8Sopenharmony_ci    if (unwinder->UnwindRemote(initPid)) {
884800b99b8Sopenharmony_ci        auto frames = unwinder->GetFrames();
885800b99b8Sopenharmony_ci        printf("Unwinder frame size: %zu\n", frames.size());
886800b99b8Sopenharmony_ci        auto framesStr = Unwinder::GetFramesStr(frames);
887800b99b8Sopenharmony_ci        printf("Unwinder frames:\n%s\n", framesStr.c_str());
888800b99b8Sopenharmony_ci        ASSERT_GT(frames.size(), 0);
889800b99b8Sopenharmony_ci    }
890800b99b8Sopenharmony_ci    DfxPtrace::Detach(initPid);
891800b99b8Sopenharmony_ci
892800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwindRemoteX86_64Test001: end.";
893800b99b8Sopenharmony_ci}
894800b99b8Sopenharmony_ci#endif
895800b99b8Sopenharmony_ci
896800b99b8Sopenharmony_ci/**
897800b99b8Sopenharmony_ci * @tc.name: GetSymbolByPcTest001
898800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetSymbolByPc interface
899800b99b8Sopenharmony_ci *  in local case
900800b99b8Sopenharmony_ci * @tc.type: FUNC
901800b99b8Sopenharmony_ci */
902800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetSymbolByPcTest001, TestSize.Level2)
903800b99b8Sopenharmony_ci{
904800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetSymbolByPcTest001: start.";
905800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
906800b99b8Sopenharmony_ci    unwinder->UnwindLocal();
907800b99b8Sopenharmony_ci    auto frames = unwinder->GetFrames();
908800b99b8Sopenharmony_ci    uintptr_t pc0 = static_cast<uintptr_t>(frames[0].pc);
909800b99b8Sopenharmony_ci    std::string funcName;
910800b99b8Sopenharmony_ci    uint64_t funcOffset;
911800b99b8Sopenharmony_ci    std::shared_ptr<DfxMaps> maps = std::make_shared<DfxMaps>();
912800b99b8Sopenharmony_ci    ASSERT_FALSE(unwinder->GetSymbolByPc(0x00000000, maps, funcName, funcOffset)); // Find map is null
913800b99b8Sopenharmony_ci    ASSERT_FALSE(unwinder->GetSymbolByPc(pc0, maps, funcName, funcOffset)); // Get elf is null
914800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "GetSymbolByPcTest001: end.";
915800b99b8Sopenharmony_ci}
916800b99b8Sopenharmony_ci
917800b99b8Sopenharmony_ci/**
918800b99b8Sopenharmony_ci * @tc.name: AccessMemTest001
919800b99b8Sopenharmony_ci * @tc.desc: test unwinder AccessMem interface
920800b99b8Sopenharmony_ci * @tc.type: FUNC
921800b99b8Sopenharmony_ci */
922800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, AccessMemTest001, TestSize.Level2)
923800b99b8Sopenharmony_ci{
924800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "AccessMemTest001: start.";
925800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
926800b99b8Sopenharmony_ci    auto acc = std::make_shared<DfxAccessorsLocal>();
927800b99b8Sopenharmony_ci    auto memory = std::make_shared<DfxMemory>(acc);
928800b99b8Sopenharmony_ci    uintptr_t val;
929800b99b8Sopenharmony_ci    EXPECT_FALSE(memory->ReadReg(0, &val));
930800b99b8Sopenharmony_ci    uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa};
931800b99b8Sopenharmony_ci    UnwindContext ctx;
932800b99b8Sopenharmony_ci    ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
933800b99b8Sopenharmony_ci    memory->SetCtx(&ctx);
934800b99b8Sopenharmony_ci    EXPECT_FALSE(memory->ReadReg(-1, &val));
935800b99b8Sopenharmony_ci
936800b99b8Sopenharmony_ci    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
937800b99b8Sopenharmony_ci    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
938800b99b8Sopenharmony_ci    EXPECT_FALSE(unwinder->AccessMem(&memory, addr, nullptr));
939800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "AccessMemTest001: end.";
940800b99b8Sopenharmony_ci}
941800b99b8Sopenharmony_ci
942800b99b8Sopenharmony_ci/**
943800b99b8Sopenharmony_ci * @tc.name: UnwinderTest001
944800b99b8Sopenharmony_ci * @tc.desc: test Unwinder::xxxx interface
945800b99b8Sopenharmony_ci * @tc.type: FUNC
946800b99b8Sopenharmony_ci */
947800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderTest001, TestSize.Level2)
948800b99b8Sopenharmony_ci{
949800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderTest001: start.";
950800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(getpid());
951800b99b8Sopenharmony_ci    unwinder->EnableUnwindCache(false);
952800b99b8Sopenharmony_ci    unwinder->EnableFpCheckMapExec(false);
953800b99b8Sopenharmony_ci    auto regs = unwinder->GetRegs();
954800b99b8Sopenharmony_ci    ASSERT_EQ(regs, nullptr);
955800b99b8Sopenharmony_ci    DfxFrame frame;
956800b99b8Sopenharmony_ci    unwinder->FillFrame(frame);
957800b99b8Sopenharmony_ci    unwinder->AddFrame(frame);
958800b99b8Sopenharmony_ci    unwinder->ArkWriteJitCodeToFile(1);
959800b99b8Sopenharmony_ci    auto jitCache = unwinder->GetJitCache();
960800b99b8Sopenharmony_ci    ASSERT_EQ(jitCache.size(), 0);
961800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderTest001: end.";
962800b99b8Sopenharmony_ci}
963800b99b8Sopenharmony_ci
964800b99b8Sopenharmony_ci/**
965800b99b8Sopenharmony_ci * @tc.name: UnwinderTest002
966800b99b8Sopenharmony_ci * @tc.desc: test DfxFrameFormatter GetFrameStr
967800b99b8Sopenharmony_ci * @tc.type: FUNC
968800b99b8Sopenharmony_ci */
969800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderTest002, TestSize.Level2)
970800b99b8Sopenharmony_ci{
971800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderTest002: start.";
972800b99b8Sopenharmony_ci    std::shared_ptr<DfxFrame> frame = nullptr;
973800b99b8Sopenharmony_ci    std::string str = DfxFrameFormatter::GetFrameStr(frame);
974800b99b8Sopenharmony_ci    ASSERT_EQ(str, "");
975800b99b8Sopenharmony_ci    std::vector<std::shared_ptr<DfxFrame>> frames;
976800b99b8Sopenharmony_ci    str = DfxFrameFormatter::GetFramesStr(frames);
977800b99b8Sopenharmony_ci    ASSERT_EQ(str, "");
978800b99b8Sopenharmony_ci    GTEST_LOG_(INFO) << "UnwinderTest002: end.";
979800b99b8Sopenharmony_ci}
980800b99b8Sopenharmony_ci} // namespace HiviewDFX
981800b99b8Sopenharmony_ci} // namepsace OHOS
982800b99b8Sopenharmony_ci
983