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