• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 #include <ctime>
18 #include <securec.h>
19 #include <string>
20 #include <vector>
21 #include "dfx_ptrace.h"
22 #include "dfx_regs.h"
23 #include "dfx_test_util.h"
24 
25 using namespace OHOS::HiviewDFX;
26 using namespace testing::ext;
27 using namespace std;
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 class DfxRegsTest : public testing::Test {
32 public:
SetUpTestCase(void)33     static void SetUpTestCase(void) {}
TearDownTestCase(void)34     static void TearDownTestCase(void) {}
SetUp()35     void SetUp() {}
TearDown()36     void TearDown() {}
37 };
38 
39 namespace {
40 #if defined(__aarch64__)
41 constexpr int VREGS_ARRAY_LEN = 32;
42 
43 struct Aarch64CtxHead {
44     uint32_t magic;
45     uint32_t size;
46 };
47 
48 struct Aarch64FpsimdContext {
49     struct Aarch64CtxHead head;
50     uint32_t fpsr;
51     uint32_t fpcr;
52     __uint128_t vregs[VREGS_ARRAY_LEN];
53 };
54 #endif
55 
56 /**
57  * @tc.name: DfxRegsTest001
58  * @tc.desc: test DfxRegs SetRegsData & GetRegsData functions
59  * @tc.type: FUNC
60  */
61 HWTEST_F(DfxRegsTest, DfxRegsTest001, TestSize.Level2)
62 {
63     GTEST_LOG_(INFO) << "DfxRegsTest001: start.";
64     auto dfxRegs = DfxRegs::Create();
65     ASSERT_NE(dfxRegs, nullptr);
66     std::vector<uintptr_t> setRegs {};
67     for (size_t i = 0; i < 10; i++) { // test 10 regs
68         setRegs.push_back(i);
69     }
70     dfxRegs->SetRegsData(setRegs);
71     auto getRegs = dfxRegs->GetRegsData();
72     ASSERT_EQ(setRegs, getRegs);
73 
74     uintptr_t regsData[REG_LAST] = { 0 };
75     dfxRegs->SetRegsData(regsData, REG_LAST);
76     getRegs = dfxRegs->GetRegsData();
77     for (size_t i = 0; i < getRegs.size(); i++) {
78         ASSERT_EQ(regsData[i], getRegs[i]);
79     }
80 
81     GTEST_LOG_(INFO) << "DfxRegsTest001: end.";
82 }
83 
84 /**
85  * @tc.name: DfxRegsTest002
86  * @tc.desc: test DfxRegs GetSpecialRegisterName
87  * @tc.type: FUNC
88  */
89 HWTEST_F(DfxRegsTest, DfxRegsTest002, TestSize.Level2)
90 {
91     GTEST_LOG_(INFO) << "DfxRegsTest002: start.";
92     auto dfxRegs = DfxRegs::Create();
93     uintptr_t val = 0x00000001;
94     dfxRegs->SetPc(val);
95     ASSERT_EQ(dfxRegs->GetPc(), val);
96     auto name = dfxRegs->GetSpecialRegsName(val);
97     ASSERT_EQ(name, "pc");
98 
99     val = 0x00000002;
100     dfxRegs->SetSp(val);
101     ASSERT_EQ(dfxRegs->GetSp(), val);
102     ASSERT_EQ(dfxRegs->GetSpecialRegsName(val), "sp");
103     ASSERT_EQ((*dfxRegs.get())[REG_SP], val);
104     ASSERT_GT(dfxRegs->RegsSize(), 0U);
105     uintptr_t *regVal = &val;
106     dfxRegs->SetReg(0, regVal);
107     ASSERT_EQ((*dfxRegs.get())[0], *regVal);
108     uintptr_t fp = 0x00000001;
109     uintptr_t lr = 0x00000002;
110     uintptr_t sp = 0x00000003;
111     uintptr_t pc = 0x00000004;
112     dfxRegs->SetSpecialRegs(fp, lr, sp, pc);
113 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
114     ASSERT_EQ(dfxRegs->GetSpecialRegsName(lr), "lr");
115     ASSERT_EQ(dfxRegs->GetSpecialRegsName(fp), "fp");
116     ASSERT_EQ(dfxRegs->GetSpecialRegsName(0x0), "");
117 #endif
118     ASSERT_EQ(dfxRegs->GetSpecialRegsName(pc), "pc");
119     ASSERT_EQ(dfxRegs->GetSpecialRegsName(sp), "sp");
120     uintptr_t fpGet;
121     uintptr_t lrGet;
122     uintptr_t spGet;
123     uintptr_t pcGet;
124     dfxRegs->GetSpecialRegs(fpGet, lrGet, spGet, pcGet);
125 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
126     ASSERT_EQ(fp, fpGet);
127     ASSERT_EQ(lr, lrGet);
128 #endif
129     ASSERT_EQ(sp, spGet);
130     ASSERT_EQ(pc, pcGet);
131     ASSERT_FALSE(dfxRegs->PrintRegs().empty());
132     ASSERT_FALSE(dfxRegs->PrintSpecialRegs().empty());
133 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
134     ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_FP), "fp");
135     ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_LR), "lr");
136 #endif
137     ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_PC), "pc");
138     ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_SP), "sp");
139     GTEST_LOG_(INFO) << "DfxRegsTest002: end.";
140 }
141 
142 /**
143  * @tc.name: DfxRegsTest003
144  * @tc.desc: test DfxRegs CreateFromUcontext
145  * @tc.type: FUNC
146  */
147 HWTEST_F(DfxRegsTest, DfxRegsTest003, TestSize.Level2)
148 {
149     GTEST_LOG_(INFO) << "DfxRegsTest003: start.";
150 
151     ucontext_t context;
152 #if defined(__arm__)
153     context.uc_mcontext.arm_r0 = 0; // 0 : the 1st register of arm
154     context.uc_mcontext.arm_r1 = 1; // 1 : the 2st register of arm
155     context.uc_mcontext.arm_r2 = 2; // 2 : the 3st register of arm
156     context.uc_mcontext.arm_r3 = 3; // 3 : the 4st register of arm
157     context.uc_mcontext.arm_r4 = 4; // 4 : the 5st register of arm
158     context.uc_mcontext.arm_r5 = 5; // 5 : the 6st register of arm
159     context.uc_mcontext.arm_r6 = 6; // 6 : the 7st register of arm
160     context.uc_mcontext.arm_r7 = 7; // 7 : the 8st register of arm
161     context.uc_mcontext.arm_r8 = 8; // 8 : the 9st register of arm
162     context.uc_mcontext.arm_r9 = 9; // 9 : the 10st register of arm
163     context.uc_mcontext.arm_r10 = 10; // 10 : the 11st register of arm
164     context.uc_mcontext.arm_fp = 11; // 11 : the 12st register of arm
165     context.uc_mcontext.arm_ip = 12; // 12 : the 13st register of arm
166     context.uc_mcontext.arm_sp = 13; // 13 : the 14st register of arm
167     context.uc_mcontext.arm_lr = 14; // 14 : the 15st register of arm
168     context.uc_mcontext.arm_pc = 15; // 15 : the 16st register of arm
169     context.uc_mcontext.arm_cpsr = 16; // 16 : the 17st register of arm
170 #elif defined(__aarch64__)
171     for (int i = 0; i < 31; i++) {
172         context.uc_mcontext.regs[i] = i;
173     }
174     context.uc_mcontext.sp = 31; // 31 : the 32st register of aarch64
175     context.uc_mcontext.pc = 32; // 32 : the 33st register of aarch64
176     context.uc_mcontext.pstate = 33;
177     uint8_t* pMctxRes = reinterpret_cast<uint8_t*>(const_cast<long double*>(&context.uc_mcontext.__reserved[0]));
178     uintptr_t* pEsr = reinterpret_cast<uintptr_t*>(pMctxRes + sizeof(Aarch64FpsimdContext) +
179         sizeof(Aarch64CtxHead));
180     *pEsr = 34;
181 #elif defined(__x86_64__)
182     context.uc_mcontext.gregs[REG_RAX] = 0; // 0 : the 1st register of x86_64
183     context.uc_mcontext.gregs[REG_RDX] = 1; // 1 : the 2st register of x86_64
184     context.uc_mcontext.gregs[REG_RCX] = 2; // 2 : the 3st register of x86_64
185     context.uc_mcontext.gregs[REG_RBX] = 3; // 3 : the 4st register of x86_64
186     context.uc_mcontext.gregs[REG_RSI] = 4; // 4 : the 5st register of x86_64
187     context.uc_mcontext.gregs[REG_RDI] = 5; // 5 : the 6st register of x86_64
188     context.uc_mcontext.gregs[REG_RBP] = 6; // 6 : the 7st register of x86_64
189     context.uc_mcontext.gregs[REG_RSP] = 7; // 7 : the 8st register of x86_64
190     context.uc_mcontext.gregs[REG_R8] = 8; // 8 : the 9st register of x86_64
191     context.uc_mcontext.gregs[REG_R9] = 9; // 9 : the 10st register of x86_64
192     context.uc_mcontext.gregs[REG_R10] = 10; // 10 : the 11st register of x86_64
193     context.uc_mcontext.gregs[REG_R11] = 11; // 11 : the 12st register of x86_64
194     context.uc_mcontext.gregs[REG_R12] = 12; // 12 : the 13st register of x86_64
195     context.uc_mcontext.gregs[REG_R13] = 13; // 13 : the 14st register of x86_64
196     context.uc_mcontext.gregs[REG_R14] = 14; // 14 : the 15st register of x86_64
197     context.uc_mcontext.gregs[REG_R15] = 15; // 15 : the 16st register of x86_64
198     context.uc_mcontext.gregs[REG_RIP] = 16; // 16 : the 17st register of x86_64
199 #endif
200     auto dfxRegs = DfxRegs::CreateFromUcontext(context);
201     for (size_t i = 0; i < REG_LAST; i++) {
202         ASSERT_EQ((*dfxRegs.get())[i], i);
203     }
204     GTEST_LOG_(INFO) << "DfxRegsTest003: end.";
205 }
206 
207 /**
208  * @tc.name: DfxRegsTest004
209  * @tc.desc: test DfxRegs SetFromQutMiniRegs SetFromFpMiniRegs
210  * @tc.type: FUNC
211  */
212 HWTEST_F(DfxRegsTest, DfxRegsTest004, TestSize.Level2)
213 {
214     GTEST_LOG_(INFO) << "DfxRegsTest004: start.";
215 #if defined(__arm__)
216     uintptr_t pushRegs[QUT_MINI_REGS_SIZE];
217     for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
218         pushRegs[i] = i + 1;
219     }
220     uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11,
221         REG_SP, REG_PC, REG_LR};
222     uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC};
223     auto dfxregsArm = std::make_shared<DfxRegsArm>();
224     dfxregsArm->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE);
225     for (size_t i = 0; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) {
226         ASSERT_EQ((*dfxregsArm.get())[qutRegs[i]], pushRegs[i]);
227     }
228     dfxregsArm->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE);
229     for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) {
230         ASSERT_EQ((*dfxregsArm.get())[fpRegs[i]], pushRegs[i]);
231     }
232 
233 #elif defined(__aarch64__)
234     uintptr_t pushRegs[QUT_MINI_REGS_SIZE];
235     for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
236         pushRegs[i] = i;
237     }
238     uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28,
239         REG_FP, REG_SP, REG_AARCH64_PC, REG_LR};
240     uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC};
241     auto dfxregsArm64 = std::make_shared<DfxRegsArm64>();
242     dfxregsArm64->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE);
243     for (size_t i = 1; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) {
244         ASSERT_EQ((*dfxregsArm64.get())[qutRegs[i]], pushRegs[i]);
245     }
246     dfxregsArm64->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE);
247     for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) {
248         ASSERT_EQ((*dfxregsArm64.get())[fpRegs[i]], pushRegs[i]);
249     }
250 #endif
251     GTEST_LOG_(INFO) << "DfxRegsTest004: end.";
252 }
253 
254 /**
255  * @tc.name: DfxRegsTest005
256  * @tc.desc: test DfxRegs CreateFromRegs
257  * @tc.type: FUNC
258  */
259 HWTEST_F(DfxRegsTest, DfxRegsTest005, TestSize.Level2)
260 {
261     GTEST_LOG_(INFO) << "DfxRegsTest005: start.";
262 #if defined(__arm__)
263     uintptr_t regs[QUT_MINI_REGS_SIZE];
264     for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
265         regs[i] = i + 1;
266     }
267     uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11,
268         REG_SP, REG_PC, REG_LR};
269     uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC};
270     auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
271     for (size_t i = 0; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) {
272         ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]);
273     }
274     dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
275     for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) {
276         ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]);
277     }
278 
279 #elif defined(__aarch64__)
280     uintptr_t regs[QUT_MINI_REGS_SIZE];
281     for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
282         regs[i] = i;
283     }
284     uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28,
285         REG_FP, REG_SP, REG_PC, REG_LR};
286     uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC};
287     auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
288     for (size_t i = 1; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) {
289         ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]);
290     }
291     dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
292     for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) {
293         ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]);
294     }
295 #endif
296     GTEST_LOG_(INFO) << "DfxRegsTest005: end.";
297 }
298 
299 
300 /**
301  * @tc.name: DfxRegsTest006
302  * @tc.desc: test DfxRegs CreateRemoteRegs
303  * @tc.type: FUNC
304  */
305 HWTEST_F(DfxRegsTest, DfxRegsTest006, TestSize.Level2)
306 {
307     GTEST_LOG_(INFO) << "DfxRegsTest006: start.";
308     static pid_t pid = getpid();
309     pid_t child = fork();
310     if (child == 0) {
311         DfxPtrace::Attach(pid);
312         auto dfxRegs = DfxRegs::CreateRemoteRegs(pid);
313         constexpr size_t maxIdx = 100;
314         EXPECT_NE(dfxRegs->GetReg(0), nullptr);
315         EXPECT_EQ(dfxRegs->GetReg(maxIdx), nullptr);
316         uintptr_t value = 0;
317         dfxRegs->SetReg(maxIdx, &value);
318 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
319         uintptr_t fp = 0x80;
320         dfxRegs->SetFp(fp);
321         EXPECT_EQ(dfxRegs->GetFp(), fp);
322 #endif
323         DfxPtrace::Detach(pid);
324         CheckAndExit(HasFailure());
325     }
326     int status;
327     wait(&status);
328     ASSERT_EQ(status, 0);
329     GTEST_LOG_(INFO) << "DfxRegsTest006: end.";
330 }
331 }
332 } // namespace HiviewDFX
333 } // namespace OHOS
334