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 */ 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 */ 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 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) 97 ASSERT_EQ(dfxRegs->GetSpecialRegsName(lr), "lr"); 98 ASSERT_EQ(dfxRegs->GetSpecialRegsName(fp), "fp"); 99 ASSERT_EQ(dfxRegs->GetSpecialRegsName(0x0), ""); 100 #endif 101 ASSERT_EQ(dfxRegs->GetSpecialRegsName(pc), "pc"); 102 ASSERT_EQ(dfxRegs->GetSpecialRegsName(sp), "sp"); 103 uintptr_t fpGet; 104 uintptr_t lrGet; 105 uintptr_t spGet; 106 uintptr_t pcGet; 107 dfxRegs->GetSpecialRegs(fpGet, lrGet, spGet, pcGet); 108 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) 109 ASSERT_EQ(fp, fpGet); 110 ASSERT_EQ(lr, lrGet); 111 #endif 112 ASSERT_EQ(sp, spGet); 113 ASSERT_EQ(pc, pcGet); 114 ASSERT_FALSE(dfxRegs->PrintRegs().empty()); 115 ASSERT_FALSE(dfxRegs->PrintSpecialRegs().empty()); 116 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) 117 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_FP), "fp"); 118 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_LR), "lr"); 119 #endif 120 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_PC), "pc"); 121 ASSERT_EQ(dfxRegs->GetSpecialRegsNameByIndex(REG_SP), "sp"); 122 GTEST_LOG_(INFO) << "DfxRegsTest002: end."; 123 } 124 125 /** 126 * @tc.name: DfxRegsTest003 127 * @tc.desc: test DfxRegs CreateFromUcontext 128 * @tc.type: FUNC 129 */ 130 HWTEST_F(DfxRegsTest, DfxRegsTest003, TestSize.Level2) 131 { 132 GTEST_LOG_(INFO) << "DfxRegsTest003: start."; 133 134 ucontext_t context; 135 #if defined(__arm__) 136 context.uc_mcontext.arm_r0 = 0; // 0 : the 1st register of arm 137 context.uc_mcontext.arm_r1 = 1; // 1 : the 2st register of arm 138 context.uc_mcontext.arm_r2 = 2; // 2 : the 3st register of arm 139 context.uc_mcontext.arm_r3 = 3; // 3 : the 4st register of arm 140 context.uc_mcontext.arm_r4 = 4; // 4 : the 5st register of arm 141 context.uc_mcontext.arm_r5 = 5; // 5 : the 6st register of arm 142 context.uc_mcontext.arm_r6 = 6; // 6 : the 7st register of arm 143 context.uc_mcontext.arm_r7 = 7; // 7 : the 8st register of arm 144 context.uc_mcontext.arm_r8 = 8; // 8 : the 9st register of arm 145 context.uc_mcontext.arm_r9 = 9; // 9 : the 10st register of arm 146 context.uc_mcontext.arm_r10 = 10; // 10 : the 11st register of arm 147 context.uc_mcontext.arm_fp = 11; // 11 : the 12st register of arm 148 context.uc_mcontext.arm_ip = 12; // 12 : the 13st register of arm 149 context.uc_mcontext.arm_sp = 13; // 13 : the 14st register of arm 150 context.uc_mcontext.arm_lr = 14; // 14 : the 15st register of arm 151 context.uc_mcontext.arm_pc = 15; // 15 : the 16st register of arm 152 #elif defined(__aarch64__) 153 for (int i = 0; i < 31; i++) { 154 context.uc_mcontext.regs[i] = i; 155 } 156 context.uc_mcontext.sp = 31; // 31 : the 32st register of aarch64 157 context.uc_mcontext.pc = 32; // 32 : the 33st register of aarch64 158 #elif defined(__x86_64__) 159 context.uc_mcontext.gregs[REG_RAX] = 0; // 0 : the 1st register of x86_64 160 context.uc_mcontext.gregs[REG_RDX] = 1; // 1 : the 2st register of x86_64 161 context.uc_mcontext.gregs[REG_RCX] = 2; // 2 : the 3st register of x86_64 162 context.uc_mcontext.gregs[REG_RBX] = 3; // 3 : the 4st register of x86_64 163 context.uc_mcontext.gregs[REG_RSI] = 4; // 4 : the 5st register of x86_64 164 context.uc_mcontext.gregs[REG_RDI] = 5; // 5 : the 6st register of x86_64 165 context.uc_mcontext.gregs[REG_RBP] = 6; // 6 : the 7st register of x86_64 166 context.uc_mcontext.gregs[REG_RSP] = 7; // 7 : the 8st register of x86_64 167 context.uc_mcontext.gregs[REG_R8] = 8; // 8 : the 9st register of x86_64 168 context.uc_mcontext.gregs[REG_R9] = 9; // 9 : the 10st register of x86_64 169 context.uc_mcontext.gregs[REG_R10] = 10; // 10 : the 11st register of x86_64 170 context.uc_mcontext.gregs[REG_R11] = 11; // 11 : the 12st register of x86_64 171 context.uc_mcontext.gregs[REG_R12] = 12; // 12 : the 13st register of x86_64 172 context.uc_mcontext.gregs[REG_R13] = 13; // 13 : the 14st register of x86_64 173 context.uc_mcontext.gregs[REG_R14] = 14; // 14 : the 15st register of x86_64 174 context.uc_mcontext.gregs[REG_R15] = 15; // 15 : the 16st register of x86_64 175 context.uc_mcontext.gregs[REG_RIP] = 16; // 16 : the 17st register of x86_64 176 #endif 177 auto dfxRegs = DfxRegs::CreateFromUcontext(context); 178 for (size_t i = 0; i < REG_LAST; i++) { 179 ASSERT_EQ((*dfxRegs.get())[i], i); 180 } 181 GTEST_LOG_(INFO) << "DfxRegsTest003: end."; 182 } 183 184 /** 185 * @tc.name: DfxRegsTest004 186 * @tc.desc: test DfxRegs SetFromQutMiniRegs SetFromFpMiniRegs 187 * @tc.type: FUNC 188 */ 189 HWTEST_F(DfxRegsTest, DfxRegsTest004, TestSize.Level2) 190 { 191 GTEST_LOG_(INFO) << "DfxRegsTest004: start."; 192 #if defined(__arm__) 193 uintptr_t pushRegs[QUT_MINI_REGS_SIZE]; 194 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) { 195 pushRegs[i] = i + 1; 196 } 197 uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11, 198 REG_SP, REG_PC, REG_LR}; 199 uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC}; 200 auto dfxregsArm = std::make_shared<DfxRegsArm>(); 201 dfxregsArm->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE); 202 for (size_t i = 0; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) { 203 ASSERT_EQ((*dfxregsArm.get())[qutRegs[i]], pushRegs[i]); 204 } 205 dfxregsArm->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE); 206 for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) { 207 ASSERT_EQ((*dfxregsArm.get())[fpRegs[i]], pushRegs[i]); 208 } 209 210 #elif defined(__aarch64__) 211 uintptr_t pushRegs[QUT_MINI_REGS_SIZE]; 212 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) { 213 pushRegs[i] = i; 214 } 215 uintptr_t qutRegs[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28, 216 REG_FP, REG_SP, REG_AARCH64_PC, REG_LR}; 217 uintptr_t fpRegs[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC}; 218 auto dfxregsArm64 = std::make_shared<DfxRegsArm64>(); 219 dfxregsArm64->SetFromQutMiniRegs(pushRegs, QUT_MINI_REGS_SIZE); 220 for (size_t i = 1; i < sizeof(qutRegs) / sizeof(qutRegs[0]); ++i) { 221 ASSERT_EQ((*dfxregsArm64.get())[qutRegs[i]], pushRegs[i]); 222 } 223 dfxregsArm64->SetFromFpMiniRegs(pushRegs, FP_MINI_REGS_SIZE); 224 for (size_t i = 0; i < sizeof(fpRegs) / sizeof(fpRegs[0]); ++i) { 225 ASSERT_EQ((*dfxregsArm64.get())[fpRegs[i]], pushRegs[i]); 226 } 227 #endif 228 GTEST_LOG_(INFO) << "DfxRegsTest004: end."; 229 } 230 231 /** 232 * @tc.name: DfxRegsTest005 233 * @tc.desc: test DfxRegs CreateFromRegs 234 * @tc.type: FUNC 235 */ 236 HWTEST_F(DfxRegsTest, DfxRegsTest005, TestSize.Level2) 237 { 238 GTEST_LOG_(INFO) << "DfxRegsTest005: start."; 239 #if defined(__arm__) 240 uintptr_t regs[QUT_MINI_REGS_SIZE]; 241 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) { 242 regs[i] = i + 1; 243 } 244 uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_ARM_R4, REG_ARM_R7, REG_ARM_R10, REG_ARM_R11, 245 REG_SP, REG_PC, REG_LR}; 246 uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_ARM_R7, REG_FP, REG_SP, REG_PC}; 247 auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0])); 248 for (size_t i = 0; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) { 249 ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]); 250 } 251 dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0])); 252 for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) { 253 ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]); 254 } 255 256 #elif defined(__aarch64__) 257 uintptr_t regs[QUT_MINI_REGS_SIZE]; 258 for (size_t i = 0; i < QUT_MINI_REGS_SIZE; ++i) { 259 regs[i] = i; 260 } 261 uintptr_t minimal[QUT_MINI_REGS_SIZE] = {REG_AARCH64_X0, REG_AARCH64_X20, REG_AARCH64_X28, 262 REG_FP, REG_SP, REG_PC, REG_LR}; 263 uintptr_t framePointer[FP_MINI_REGS_SIZE] = {REG_FP, REG_LR, REG_SP, REG_PC}; 264 auto dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, regs, sizeof(regs) / sizeof(regs[0])); 265 for (size_t i = 1; i < sizeof(framePointer) / sizeof(framePointer[0]); ++i) { 266 ASSERT_EQ((*dfxRegs.get())[framePointer[i]], regs[i]); 267 } 268 dfxRegs = DfxRegs::CreateFromRegs(UnwindMode::MINIMAL_UNWIND, regs, sizeof(regs) / sizeof(regs[0])); 269 for (size_t i = 0; i < sizeof(minimal) / sizeof(minimal[0]); ++i) { 270 ASSERT_EQ((*dfxRegs.get())[minimal[i]], regs[i]); 271 } 272 #endif 273 GTEST_LOG_(INFO) << "DfxRegsTest005: end."; 274 } 275 276 277 /** 278 * @tc.name: DfxRegsTest006 279 * @tc.desc: test DfxRegs CreateRemoteRegs 280 * @tc.type: FUNC 281 */ 282 HWTEST_F(DfxRegsTest, DfxRegsTest006, TestSize.Level2) 283 { 284 GTEST_LOG_(INFO) << "DfxRegsTest006: start."; 285 static pid_t pid = getpid(); 286 pid_t child = fork(); 287 if (child == 0) { 288 DfxPtrace::Attach(pid); 289 auto dfxRegs = DfxRegs::CreateRemoteRegs(pid); 290 constexpr size_t maxIdx = 100; 291 ASSERT_NE(dfxRegs->GetReg(0), nullptr); 292 ASSERT_EQ(dfxRegs->GetReg(maxIdx), nullptr); 293 uintptr_t value = 0; 294 dfxRegs->SetReg(maxIdx, &value); 295 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) 296 uintptr_t fp = 0x80; 297 dfxRegs->SetFp(fp); 298 ASSERT_EQ(dfxRegs->GetFp(), fp); 299 #endif 300 DfxPtrace::Detach(pid); 301 _exit(0); 302 } 303 int status; 304 int ret = wait(&status); 305 ASSERT_EQ(status, 0); 306 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 307 GTEST_LOG_(INFO) << "DfxRegsTest006: end."; 308 } 309 } 310 } // namespace HiviewDFX 311 } // namespace OHOS 312