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 <thread>
20#include <unistd.h>
21#include <malloc.h>
22#include <securec.h>
23#include "dfx_ptrace.h"
24#include "dfx_regs_get.h"
25#include "unwinder.h"
26
27using namespace testing;
28using namespace testing::ext;
29
30namespace OHOS {
31namespace HiviewDFX {
32#undef LOG_DOMAIN
33#undef LOG_TAG
34#define LOG_TAG "DfxUnwinderPacTest"
35#define LOG_DOMAIN 0xD002D11
36
37class UnwinderPacTest : public testing::Test {
38public:
39    static void SetUpTestCase() {}
40    static void TearDownTestCase() {}
41    void SetUp() {}
42    void TearDown() {}
43};
44
45/**
46 * @tc.name: UnwinderPacTest001
47 * @tc.desc: test unwinder unwind interface with pac
48 * @tc.type: FUNC
49 */
50HWTEST_F(UnwinderPacTest, UnwinderPacTest001, TestSize.Level2)
51{
52    GTEST_LOG_(INFO) << "UnwinderPacTest001: start.";
53    static pid_t pid = getpid();
54    pid_t child = fork();
55    if (child == 0) {
56        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
57        auto unwinder = std::make_shared<Unwinder>(pid);
58        bool unwRet = DfxPtrace::Attach(pid);
59        EXPECT_EQ(true, unwRet) << "UnwinderPacTest001: Attach:" << unwRet;
60        auto regs = DfxRegs::CreateRemoteRegs(pid);
61        auto maps = DfxMaps::Create(pid);
62        unwinder->SetRegs(regs);
63        UnwindContext context;
64        context.pid = pid;
65        context.regs = regs;
66        context.maps = maps;
67        unwRet = unwinder->Unwind(&context);
68        EXPECT_EQ(true, unwRet) << "UnwinderPacTest001: Unwind:" << unwRet;
69        auto frames = unwinder->GetFrames();
70        ASSERT_GT(frames.size(), 1);
71        GTEST_LOG_(INFO) << "frames:\n" << Unwinder::GetFramesStr(frames);
72        DfxPtrace::Detach(pid);
73        _exit(0);
74    }
75
76    int status;
77    int ret = wait(&status);
78    ASSERT_EQ(status, 0);
79    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
80    GTEST_LOG_(INFO) << "UnwinderPacTest001: end.";
81}
82
83/**
84 * @tc.name: UnwinderPacTest002
85 * @tc.desc: test unwinder FpStep interface with pac
86 * @tc.type: FUNC
87 */
88HWTEST_F(UnwinderPacTest, UnwinderPacTest002, TestSize.Level2)
89{
90    GTEST_LOG_(INFO) << "UnwinderPacTest002: start.";
91#if defined(__aarch64__)
92    static pid_t pid = getpid();
93    pid_t child = fork();
94    if (child == 0) {
95        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
96        auto unwinder = std::make_shared<Unwinder>(pid);
97        bool unwRet = DfxPtrace::Attach(pid);
98        EXPECT_EQ(true, unwRet) << "UnwinderPacTest002: Attach:" << unwRet;
99        auto regs = DfxRegs::CreateRemoteRegs(pid);
100        unwinder->SetRegs(regs);
101        UnwindContext context;
102        context.pid = pid;
103        context.regs = regs;
104        unwRet = unwinder->UnwindByFp(&context);
105        ASSERT_TRUE(unwRet) << "UnwinderPacTest002: unwRet:" << unwRet;
106        DfxPtrace::Detach(pid);
107        _exit(0);
108    }
109
110    int status;
111    int ret = wait(&status);
112    ASSERT_EQ(status, 0);
113    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
114#endif
115    GTEST_LOG_(INFO) << "UnwinderPacTest002: end.";
116}
117} // namespace HiviewDFX
118} // namepsace OHOS