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
24 using namespace OHOS::HiviewDFX;
25 using namespace testing::ext;
26 using namespace std;
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 class DfxRegsTest : public testing::Test {
31 public:
SetUpTestCase(void)32 static void SetUpTestCase(void) {}
TearDownTestCase(void)33 static void TearDownTestCase(void) {}
SetUp()34 void SetUp() {}
TearDown()35 void TearDown() {}
36 };
37
38 namespace {
39 /**
40 * @tc.name: DfxRegsTest001
41 * @tc.desc: test DfxRegs SetRegsData & GetRegsData functions
42 * @tc.type: FUNC
43 */
HWTEST_F(DfxRegsTest, DfxRegsTest001, TestSize.Level2)44 HWTEST_F(DfxRegsTest, DfxRegsTest001, TestSize.Level2)
45 {
46 GTEST_LOG_(INFO) << "DfxRegsTest001: start.";
47 auto dfxRegs = DfxRegs::Create();
48 ASSERT_NE(dfxRegs, nullptr);
49 std::vector<uintptr_t> setRegs {};
50 for (size_t i = 0; i < 10; i++) { // test 10 regs
51 setRegs.push_back(i);
52 }
53 dfxRegs->SetRegsData(setRegs);
54 auto getRegs = dfxRegs->GetRegsData();
55 ASSERT_EQ(setRegs, getRegs);
56
57 uintptr_t regsData[REG_LAST] = { 0 };
58 dfxRegs->SetRegsData(regsData, REG_LAST);
59 getRegs = dfxRegs->GetRegsData();
60 for (size_t i = 0; i < getRegs.size(); i++) {
61 ASSERT_EQ(regsData[i], getRegs[i]);
62 }
63
64 GTEST_LOG_(INFO) << "DfxRegsTest001: end.";
65 }
66
67 /**
68 * @tc.name: DfxRegsTest002
69 * @tc.desc: test DfxRegs GetSpecialRegisterName
70 * @tc.type: FUNC
71 */
HWTEST_F(DfxRegsTest, DfxRegsTest002, TestSize.Level2)72 HWTEST_F(DfxRegsTest, DfxRegsTest002, TestSize.Level2)
73 {
74 GTEST_LOG_(INFO) << "DfxRegsTest002: start.";
75 auto dfxRegs = DfxRegs::Create();
76 uintptr_t val = 0x00000001;
77 dfxRegs->SetPc(val);
78 ASSERT_EQ(dfxRegs->GetPc(), val);
79 auto name = dfxRegs->GetSpecialRegsName(val);
80 ASSERT_EQ(name, "pc");
81
82 val = 0x00000002;
83 dfxRegs->SetSp(val);
84 ASSERT_EQ(dfxRegs->GetSp(), val);
85 ASSERT_EQ(dfxRegs->GetSpecialRegsName(val), "sp");
86 ASSERT_EQ((*dfxRegs.get())[REG_SP], val);
87 ASSERT_GT(dfxRegs->RegsSize(), 0U);
88 uintptr_t *regVal = &val;
89 dfxRegs->SetReg(0, regVal);
90 ASSERT_EQ((*dfxRegs.get())[0], *regVal);
91 uintptr_t fp = 0x00000001;
92 uintptr_t lr = 0x00000002;
93 uintptr_t sp = 0x00000003;
94 uintptr_t pc = 0x00000004;
95 dfxRegs->SetSpecialRegs(fp, lr, sp, pc);
96 ASSERT_EQ(dfxRegs->GetSpecialRegsName(lr), "lr");
97 ASSERT_EQ(dfxRegs->GetSpecialRegsName(fp), "fp");
98 ASSERT_EQ(dfxRegs->GetSpecialRegsName(pc), "pc");
99 ASSERT_EQ(dfxRegs->GetSpecialRegsName(sp), "sp");
100 ASSERT_EQ(dfxRegs->GetSpecialRegsName(0x0), "");
101 uintptr_t fpGet;
102 uintptr_t lrGet;
103 uintptr_t spGet;
104 uintptr_t pcGet;
105 dfxRegs->GetSpecialRegs(fpGet, lrGet, spGet, pcGet);
106 ASSERT_EQ(fp, fpGet);
107 ASSERT_EQ(lr, lrGet);
108 ASSERT_EQ(sp, spGet);
109 ASSERT_EQ(pc, pcGet);
110 ASSERT_FALSE(dfxRegs->PrintRegs().empty());
111 ASSERT_FALSE(dfxRegs->PrintSpecialRegs().empty());
112 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
113 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_FP), "fp");
114 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_LR), "lr");
115 #endif
116 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_PC), "pc");
117 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_SP), "sp");
118 GTEST_LOG_(INFO) << "DfxRegsTest002: end.";
119 }
120
121 /**
122 * @tc.name: DfxRegsTest003
123 * @tc.desc: test DfxRegs CreateFromUcontext
124 * @tc.type: FUNC
125 */
HWTEST_F(DfxRegsTest, DfxRegsTest003, TestSize.Level2)126 HWTEST_F(DfxRegsTest, DfxRegsTest003, TestSize.Level2)
127 {
128 GTEST_LOG_(INFO) << "DfxRegsTest003: start.";
129
130 ucontext_t context;
131 #if defined(__arm__)
132 context.uc_mcontext.arm_r0 = 0; // 0 : the 1st register of arm
133 context.uc_mcontext.arm_r1 = 1; // 1 : the 2st register of arm
134 context.uc_mcontext.arm_r2 = 2; // 2 : the 3st register of arm
135 context.uc_mcontext.arm_r3 = 3; // 3 : the 4st register of arm
136 context.uc_mcontext.arm_r4 = 4; // 4 : the 5st register of arm
137 context.uc_mcontext.arm_r5 = 5; // 5 : the 6st register of arm
138 context.uc_mcontext.arm_r6 = 6; // 6 : the 7st register of arm
139 context.uc_mcontext.arm_r7 = 7; // 7 : the 8st register of arm
140 context.uc_mcontext.arm_r8 = 8; // 8 : the 9st register of arm
141 context.uc_mcontext.arm_r9 = 9; // 9 : the 10st register of arm
142 context.uc_mcontext.arm_r10 = 10; // 10 : the 11st register of arm
143 context.uc_mcontext.arm_fp = 11; // 11 : the 12st register of arm
144 context.uc_mcontext.arm_ip = 12; // 12 : the 13st register of arm
145 context.uc_mcontext.arm_sp = 13; // 13 : the 14st register of arm
146 context.uc_mcontext.arm_lr = 14; // 14 : the 15st register of arm
147 context.uc_mcontext.arm_pc = 15; // 15 : the 16st register of arm
148 #elif defined(__aarch64__)
149 for (int i = 0; i < 31; i++) {
150 context.uc_mcontext.regs[i] = i;
151 }
152 context.uc_mcontext.sp = 31; // 31 : the 32st register of aarch64
153 context.uc_mcontext.pc = 32; // 32 : the 33st register of aarch64
154 #elif defined(__x86_64__)
155 context.uc_mcontext.gregs[REG_RAX] = 0; // 0 : the 1st register of x86_64
156 context.uc_mcontext.gregs[REG_RDX] = 1; // 1 : the 2st register of x86_64
157 context.uc_mcontext.gregs[REG_RCX] = 2; // 2 : the 3st register of x86_64
158 context.uc_mcontext.gregs[REG_RBX] = 3; // 3 : the 4st register of x86_64
159 context.uc_mcontext.gregs[REG_RSI] = 4; // 4 : the 5st register of x86_64
160 context.uc_mcontext.gregs[REG_RDI] = 5; // 5 : the 6st register of x86_64
161 context.uc_mcontext.gregs[REG_RBP] = 6; // 6 : the 7st register of x86_64
162 context.uc_mcontext.gregs[REG_RSP] = 7; // 7 : the 8st register of x86_64
163 context.uc_mcontext.gregs[REG_R8] = 8; // 8 : the 9st register of x86_64
164 context.uc_mcontext.gregs[REG_R9] = 9; // 9 : the 10st register of x86_64
165 context.uc_mcontext.gregs[REG_R10] = 10; // 10 : the 11st register of x86_64
166 context.uc_mcontext.gregs[REG_R11] = 11; // 11 : the 12st register of x86_64
167 context.uc_mcontext.gregs[REG_R12] = 12; // 12 : the 13st register of x86_64
168 context.uc_mcontext.gregs[REG_R13] = 13; // 13 : the 14st register of x86_64
169 context.uc_mcontext.gregs[REG_R14] = 14; // 14 : the 15st register of x86_64
170 context.uc_mcontext.gregs[REG_R15] = 15; // 15 : the 16st register of x86_64
171 context.uc_mcontext.gregs[REG_RIP] = 16; // 16 : the 17st register of x86_64
172 #endif
173 auto dfxRegs = DfxRegs::CreateFromUcontext(context);
174 for (size_t i = 0; i < REG_LAST; i++) {
175 ASSERT_EQ((*dfxRegs.get())[i], i);
176 }
177 GTEST_LOG_(INFO) << "DfxRegsTest003: end.";
178 }
179
180 /**
181 * @tc.name: DfxRegsTest004
182 * @tc.desc: test DfxRegs SetFromQutMiniRegs SetFromFpMiniRegs
183 * @tc.type: FUNC
184 */
HWTEST_F(DfxRegsTest, DfxRegsTest004, TestSize.Level2)185 HWTEST_F(DfxRegsTest, DfxRegsTest004, TestSize.Level2)
186 {
187 GTEST_LOG_(INFO) << "DfxRegsTest004: start.";
188 #if defined(__arm__)
189 uintptr_t pushRegs[QUT_MINI_REGS_SIZE];
190 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
191 pushRegs[i] = i + 1;
192 }
193 uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11,
194 REG_SP, REG_PC, REG_LR};
195 uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC};
196 auto dfxregsArm = std::make_shared<DfxRegsArm>();
197 dfxregsArm->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE);
198 for (size_t i = 0; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) {
199 ASSERT_EQ((*dfxregsArm.get())[qutRegs[i]], pushRegs[i]);
200 }
201 dfxregsArm->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE);
202 for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) {
203 ASSERT_EQ((*dfxregsArm.get())[fpRegs[i]], pushRegs[i]);
204 }
205
206 #elif defined(__aarch64__)
207 uintptr_t pushRegs[QUT_MINI_REGS_SIZE];
208 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
209 pushRegs[i] = i;
210 }
211 uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28,
212 REG_FP, REG_SP, REG_AARCH64_PC, REG_LR};
213 uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC};
214 auto dfxregsArm64 = std::make_shared<DfxRegsArm64>();
215 dfxregsArm64->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE);
216 for (size_t i = 1; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) {
217 ASSERT_EQ((*dfxregsArm64.get())[qutRegs[i]], pushRegs[i]);
218 }
219 dfxregsArm64->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE);
220 for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) {
221 ASSERT_EQ((*dfxregsArm64.get())[fpRegs[i]], pushRegs[i]);
222 }
223 #endif
224 GTEST_LOG_(INFO) << "DfxRegsTest004: end.";
225 }
226
227 /**
228 * @tc.name: DfxRegsTest005
229 * @tc.desc: test DfxRegs CreateFromRegs
230 * @tc.type: FUNC
231 */
HWTEST_F(DfxRegsTest, DfxRegsTest005, TestSize.Level2)232 HWTEST_F(DfxRegsTest, DfxRegsTest005, TestSize.Level2)
233 {
234 GTEST_LOG_(INFO) << "DfxRegsTest005: start.";
235 #if defined(__arm__)
236 uintptr_t regs[QUT_MINI_REGS_SIZE];
237 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
238 regs[i] = i + 1;
239 }
240 uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11,
241 REG_SP, REG_PC, REG_LR};
242 uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC};
243 auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
244 for (size_t i = 0; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) {
245 ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]);
246 }
247 dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
248 for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) {
249 ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]);
250 }
251
252 #elif defined(__aarch64__)
253 uintptr_t regs[QUT_MINI_REGS_SIZE];
254 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) {
255 regs[i] = i;
256 }
257 uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28,
258 REG_FP, REG_SP, REG_PC, REG_LR};
259 uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC};
260 auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
261 for (size_t i = 1; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) {
262 ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]);
263 }
264 dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
265 for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) {
266 ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]);
267 }
268 #endif
269 GTEST_LOG_(INFO) << "DfxRegsTest005: end.";
270 }
271
272
273 /**
274 * @tc.name: DfxRegsTest006
275 * @tc.desc: test DfxRegs CreateRemoteRegs
276 * @tc.type: FUNC
277 */
HWTEST_F(DfxRegsTest, DfxRegsTest006, TestSize.Level2)278 HWTEST_F(DfxRegsTest, DfxRegsTest006, TestSize.Level2)
279 {
280 GTEST_LOG_(INFO) << "DfxRegsTest006: start.";
281 static pid_t pid = getpid();
282 pid_t child = fork();
283 if (child == 0) {
284 DfxPtrace::Attach(pid);
285 auto dfxRegs = DfxRegs::CreateRemoteRegs(pid);
286 constexpr size_t maxIdx = 100;
287 ASSERT_NE(dfxRegs->GetReg(0), nullptr);
288 ASSERT_EQ(dfxRegs->GetReg(maxIdx), nullptr);
289 uintptr_t value = 0;
290 dfxRegs->SetReg(maxIdx, &value);
291 uintptr_t fp = 0x80;
292 dfxRegs->SetFp(fp);
293 ASSERT_EQ(dfxRegs->GetFp(), fp);
294 DfxPtrace::Detach(pid);
295 _exit(0);
296 }
297 int status;
298 int ret = wait(&status);
299 ASSERT_EQ(status, 0);
300 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
301 GTEST_LOG_(INFO) << "DfxRegsTest006: end.";
302 }
303 }
304 } // namespace HiviewDFX
305 } // namespace OHOS
306