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 22 #include "dfx_memory.h" 23 #include "dfx_regs.h" 24 #include "dfx_regs_get.h" 25 #include "dfx_ptrace.h" 26 #include "dwarf_define.h" 27 #include "stack_util.h" 28 29 using namespace OHOS::HiviewDFX; 30 using namespace testing::ext; 31 using namespace std; 32 33 namespace OHOS { 34 namespace HiviewDFX { 35 class DfxMemoryTest : public testing::Test { 36 public: SetUpTestCase(void)37 static void SetUpTestCase(void) {} TearDownTestCase(void)38 static void TearDownTestCase(void) {} SetUp()39 void SetUp() {} TearDown()40 void TearDown() {} 41 }; 42 43 namespace { 44 /** 45 * @tc.name: DfxMemoryTest001 46 * @tc.desc: test DfxMemory class ReadReg 47 * @tc.type: FUNC 48 */ 49 HWTEST_F(DfxMemoryTest, DfxMemoryTest001, TestSize.Level2) 50 { 51 GTEST_LOG_(INFO) << "DfxMemoryTest001: start."; 52 uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}; 53 UnwindContext ctx; 54 ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs); 55 auto acc = std::make_shared<DfxAccessorsLocal>(); 56 auto memory = std::make_shared<DfxMemory>(acc); 57 memory->SetCtx(&ctx); 58 uintptr_t value; 59 bool ret = memory->ReadReg(0, &value); 60 EXPECT_EQ(true, ret) << "DfxMemoryTest001: ret" << ret; 61 EXPECT_EQ(static_cast<uintptr_t>(0x1), value) << "DfxMemoryTest001: value" << value; 62 GTEST_LOG_(INFO) << "DfxMemoryTest001: end."; 63 } 64 65 /** 66 * @tc.name: DfxMemoryTest002 67 * @tc.desc: test DfxMemory class Read 68 * @tc.type: FUNC 69 */ 70 HWTEST_F(DfxMemoryTest, DfxMemoryTest002, TestSize.Level2) 71 { 72 GTEST_LOG_(INFO) << "DfxMemoryTest002: start."; 73 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 74 75 uintptr_t addr = (uintptr_t)(&values[0]); 76 uintptr_t value; 77 auto acc = std::make_shared<DfxAccessorsLocal>(); 78 auto memory = std::make_shared<DfxMemory>(acc); 79 bool ret = memory->ReadUptr(addr, &value, false); 80 EXPECT_EQ(true, ret) << "DfxMemoryTest002: ret:" << ret; 81 82 83 uint64_t tmp; 84 memory->Read(addr, &tmp, sizeof(uint8_t), false); 85 ASSERT_EQ(tmp, 0x01); 86 87 memory->Read(addr, &tmp, sizeof(uint16_t), false); 88 ASSERT_EQ(tmp, 0x0201); 89 90 memory->Read(addr, &tmp, sizeof(uint32_t), false); 91 ASSERT_EQ(tmp, 0x04030201); 92 93 memory->Read(addr, &tmp, sizeof(uint64_t), false); 94 ASSERT_EQ(tmp, 0x0807060504030201); 95 96 GTEST_LOG_(INFO) << "DfxMemoryTest002: end."; 97 } 98 99 /** 100 * @tc.name: DfxMemoryTest003 101 * @tc.desc: test DfxMemory class Read 102 * @tc.type: FUNC 103 */ 104 HWTEST_F(DfxMemoryTest, DfxMemoryTest003, TestSize.Level2) 105 { 106 GTEST_LOG_(INFO) << "DfxMemoryTest003: start."; 107 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 108 UnwindContext ctx; 109 auto acc = std::make_shared<DfxAccessorsLocal>(); 110 ASSERT_EQ(GetSelfStackRange(ctx.stackBottom, ctx.stackTop), 0); 111 auto memory = std::make_shared<DfxMemory>(acc); 112 memory->SetCtx(&ctx); 113 uintptr_t addr = (uintptr_t)(&values[0]); 114 uintptr_t value; 115 ASSERT_TRUE(memory->ReadUptr(addr, &value, false)); 116 #if defined(__arm__) 117 ASSERT_EQ(value, 0x04030201); 118 #elif defined(__aarch64__) 119 ASSERT_EQ(value, 0x0807060504030201); 120 #endif 121 122 uint64_t tmp; 123 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint8_t), false)); 124 ASSERT_EQ(tmp, 0x01); 125 126 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint16_t), false)); 127 ASSERT_EQ(tmp, 0x0201); 128 129 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint32_t), false)); 130 ASSERT_EQ(tmp, 0x04030201); 131 132 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint64_t), false)); 133 ASSERT_EQ(tmp, 0x0807060504030201); 134 135 GTEST_LOG_(INFO) << "DfxMemoryTest003: end."; 136 } 137 138 /** 139 * @tc.name: DfxMemoryTest004 140 * @tc.desc: test DfxMemory class Read 141 * @tc.type: FUNC 142 */ 143 HWTEST_F(DfxMemoryTest, DfxMemoryTest004, TestSize.Level2) 144 { 145 GTEST_LOG_(INFO) << "DfxMemoryTest004: start."; 146 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 147 UnwindContext ctx; 148 auto acc = std::make_shared<DfxAccessorsLocal>(); 149 ASSERT_EQ(GetSelfStackRange(ctx.stackBottom, ctx.stackTop), 0); 150 auto memory = std::make_shared<DfxMemory>(acc); 151 memory->SetCtx(&ctx); 152 uintptr_t addr = (uintptr_t)(&values[0]); 153 uint8_t tmp8; 154 ASSERT_TRUE(memory->ReadU8(addr, &tmp8, false)); 155 ASSERT_EQ(tmp8, 0x01); 156 uint16_t tmp16; 157 ASSERT_TRUE(memory->ReadU16(addr, &tmp16, false)); 158 ASSERT_EQ(tmp16, 0x0201); 159 uint32_t tmp32; 160 ASSERT_TRUE(memory->ReadU32(addr, &tmp32, false)); 161 ASSERT_EQ(tmp32, 0x04030201); 162 uint64_t tmp64; 163 ASSERT_TRUE(memory->ReadU64(addr, &tmp64, false)); 164 ASSERT_EQ(tmp64, 0x0807060504030201); 165 GTEST_LOG_(INFO) << "DfxMemoryTest004: end."; 166 } 167 168 /** 169 * @tc.name: DfxMemoryTest005 170 * @tc.desc: test DfxMemory class Read 171 * @tc.type: FUNC 172 */ 173 HWTEST_F(DfxMemoryTest, DfxMemoryTest005, TestSize.Level2) 174 { 175 GTEST_LOG_(INFO) << "DfxMemoryTest005: start."; 176 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 177 UnwindContext ctx; 178 auto acc = std::make_shared<DfxAccessorsLocal>(); 179 ASSERT_EQ(GetSelfStackRange(ctx.stackBottom, ctx.stackTop), 0); 180 auto memory = std::make_shared<DfxMemory>(acc); 181 memory->SetCtx(&ctx); 182 uintptr_t addr = (uintptr_t)(&values[0]); 183 uintptr_t valuePrel32; 184 ASSERT_TRUE(memory->ReadPrel31(addr, &valuePrel32)); 185 ASSERT_EQ(valuePrel32, 0x04030201 + addr); 186 char testStr[] = "Test ReadString Func"; 187 std::string resultStr; 188 uintptr_t addrStr = (uintptr_t)(&testStr[0]); 189 ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), false)); 190 ASSERT_EQ(testStr, resultStr); 191 ASSERT_EQ(memory->ReadUleb128(addr), 1U); 192 ASSERT_EQ(memory->ReadSleb128(addr), 2); 193 GTEST_LOG_(INFO) << "DfxMemoryTest005: end."; 194 } 195 196 /** 197 * @tc.name: DfxMemoryTest006 198 * @tc.desc: test DfxMemory class Read 199 * @tc.type: FUNC 200 */ 201 HWTEST_F(DfxMemoryTest, DfxMemoryTest006, TestSize.Level2) 202 { 203 GTEST_LOG_(INFO) << "DfxMemoryTest006: start."; 204 UnwindContext ctx; 205 auto acc = std::make_shared<DfxAccessorsLocal>(); 206 ASSERT_EQ(GetSelfStackRange(ctx.stackBottom, ctx.stackTop), 0); 207 auto memory = std::make_shared<DfxMemory>(acc); 208 memory->SetCtx(&ctx); 209 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_absptr), sizeof(uintptr_t)); 210 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata1), 1); 211 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata2), 2); 212 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata4), 4); 213 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata8), 8); 214 GTEST_LOG_(INFO) << "DfxMemoryTest006: end."; 215 } 216 217 /** 218 * @tc.name: DfxMemoryTest007 219 * @tc.desc: test DfxMemory class ReadReg in remote case 220 * @tc.type: FUNC 221 */ 222 HWTEST_F(DfxMemoryTest, DfxMemoryTest007, TestSize.Level2) 223 { 224 GTEST_LOG_(INFO) << "DfxMemoryTest007: start."; 225 uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}; 226 UnwindContext ctx; 227 ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs); 228 auto acc = std::make_shared<DfxAccessorsRemote>(); 229 auto memory = std::make_shared<DfxMemory>(acc); 230 memory->SetCtx(&ctx); 231 uintptr_t value; 232 bool ret = memory->ReadReg(0, &value); 233 EXPECT_EQ(true, ret) << "DfxMemoryTest007: ret" << ret; 234 EXPECT_EQ(static_cast<uintptr_t>(0x1), value) << "DfxMemoryTest007: value" << value; 235 GTEST_LOG_(INFO) << "DfxMemoryTest007: end."; 236 } 237 /** 238 * @tc.name: DfxMemoryTest008 239 * @tc.desc: test DfxMemory class Read in remote case 240 * @tc.type: FUNC 241 */ 242 HWTEST_F(DfxMemoryTest, DfxMemoryTest008, TestSize.Level2) 243 { 244 GTEST_LOG_(INFO) << "DfxMemoryTest008: start."; 245 static pid_t pid = getpid(); 246 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 247 pid_t child = fork(); 248 if (child == 0) { 249 GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid(); 250 DfxPtrace::Attach(pid); 251 uintptr_t value; 252 UnwindContext ctx; 253 ctx.pid = pid; 254 auto acc = std::make_shared<DfxAccessorsRemote>(); 255 auto memory = std::make_shared<DfxMemory>(acc); 256 memory->SetCtx(&ctx); 257 uintptr_t addr = (uintptr_t)(&values[0]); 258 bool ret = memory->ReadUptr(addr, &value, false); 259 EXPECT_EQ(true, ret) << "DfxMemoryTest008: ret:" << ret; 260 uint64_t tmp; 261 memory->Read(addr, &tmp, sizeof(uint8_t), false); 262 EXPECT_EQ(tmp, 0x01); 263 264 memory->Read(addr, &tmp, sizeof(uint16_t), false); 265 EXPECT_EQ(tmp, 0x0201); 266 267 memory->Read(addr, &tmp, sizeof(uint32_t), false); 268 EXPECT_EQ(tmp, 0x04030201); 269 270 memory->Read(addr, &tmp, sizeof(uint64_t), false); 271 EXPECT_EQ(tmp, 0x0807060504030201); 272 DfxPtrace::Detach(pid); 273 _exit(0); 274 } 275 int status; 276 int ret = wait(&status); 277 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 278 GTEST_LOG_(INFO) << "DfxMemoryTest008: end."; 279 } 280 281 /** 282 * @tc.name: DfxMemoryTest009 283 * @tc.desc: test DfxMemory class Read in remote case 284 * @tc.type: FUNC 285 */ 286 HWTEST_F(DfxMemoryTest, DfxMemoryTest009, TestSize.Level2) 287 { 288 GTEST_LOG_(INFO) << "DfxMemoryTest009: start."; 289 static pid_t pid = getpid(); 290 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 291 pid_t child = fork(); 292 if (child == 0) { 293 GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid(); 294 DfxPtrace::Attach(pid); 295 UnwindContext ctx; 296 ctx.pid = pid; 297 auto acc = std::make_shared<DfxAccessorsRemote>(); 298 auto memory = std::make_shared<DfxMemory>(acc); 299 memory->SetCtx(&ctx); 300 uintptr_t addr = (uintptr_t)(&values[0]); 301 uintptr_t value; 302 ASSERT_TRUE(memory->ReadUptr(addr, &value, false)); 303 #if defined(__arm__) 304 ASSERT_EQ(value, 0x04030201); 305 #elif defined(__aarch64__) 306 ASSERT_EQ(value, 0x0807060504030201); 307 #endif 308 309 uint64_t tmp; 310 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint8_t), false)); 311 ASSERT_EQ(tmp, 0x01); 312 313 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint16_t), false)); 314 ASSERT_EQ(tmp, 0x0201); 315 316 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint32_t), false)); 317 ASSERT_EQ(tmp, 0x04030201); 318 319 ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint64_t), false)); 320 ASSERT_EQ(tmp, 0x0807060504030201); 321 DfxPtrace::Detach(pid); 322 _exit(0); 323 } 324 int status; 325 int ret = wait(&status); 326 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 327 GTEST_LOG_(INFO) << "DfxMemoryTest009: end."; 328 } 329 330 /** 331 * @tc.name: DfxMemoryTest010 332 * @tc.desc: test DfxMemory class Read in remote case 333 * @tc.type: FUNC 334 */ 335 HWTEST_F(DfxMemoryTest, DfxMemoryTest010, TestSize.Level2) 336 { 337 GTEST_LOG_(INFO) << "DfxMemoryTest010: start."; 338 static pid_t pid = getpid(); 339 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 340 pid_t child = fork(); 341 if (child == 0) { 342 GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid(); 343 DfxPtrace::Attach(pid); 344 345 UnwindContext ctx; 346 ctx.pid = pid; 347 auto acc = std::make_shared<DfxAccessorsRemote>(); 348 auto memory = std::make_shared<DfxMemory>(acc); 349 memory->SetCtx(&ctx); 350 uintptr_t addr = (uintptr_t)(&values[0]); 351 uint8_t tmp8; 352 ASSERT_TRUE(memory->ReadU8(addr, &tmp8, false)); 353 ASSERT_EQ(tmp8, 0x01); 354 uint16_t tmp16; 355 ASSERT_TRUE(memory->ReadU16(addr, &tmp16, false)); 356 ASSERT_EQ(tmp16, 0x0201); 357 uint32_t tmp32; 358 ASSERT_TRUE(memory->ReadU32(addr, &tmp32, false)); 359 ASSERT_EQ(tmp32, 0x04030201); 360 uint64_t tmp64; 361 ASSERT_TRUE(memory->ReadU64(addr, &tmp64, false)); 362 ASSERT_EQ(tmp64, 0x0807060504030201); 363 DfxPtrace::Detach(pid); 364 _exit(0); 365 } 366 int status; 367 int ret = wait(&status); 368 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 369 GTEST_LOG_(INFO) << "DfxMemoryTest010: end."; 370 } 371 372 /** 373 * @tc.name: DfxMemoryTest011 374 * @tc.desc: test DfxMemory class Read in remote case 375 * @tc.type: FUNC 376 */ 377 HWTEST_F(DfxMemoryTest, DfxMemoryTest011, TestSize.Level2) 378 { 379 GTEST_LOG_(INFO) << "DfxMemoryTest011: start."; 380 static pid_t pid = getpid(); 381 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 382 char testStr[] = "Test ReadString Func"; 383 pid_t child = fork(); 384 if (child == 0) { 385 GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid(); 386 DfxPtrace::Attach(getppid()); 387 UnwindContext ctx; 388 ctx.pid = getppid(); 389 auto acc = std::make_shared<DfxAccessorsRemote>(); 390 auto memory = std::make_shared<DfxMemory>(acc); 391 memory->SetCtx(&ctx); 392 uintptr_t addr = (uintptr_t)(&values[0]); 393 std::string resultStr; 394 uintptr_t addrStr = (uintptr_t)(&testStr[0]); 395 ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), false)); 396 ASSERT_EQ(testStr, resultStr); 397 ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), true)); 398 ASSERT_EQ(testStr, resultStr); 399 ASSERT_EQ(memory->ReadUleb128(addr), 1U); 400 ASSERT_EQ(memory->ReadSleb128(addr), 2); 401 DfxPtrace::Detach(pid); 402 _exit(0); 403 } 404 int status; 405 int ret = wait(&status); 406 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 407 GTEST_LOG_(INFO) << "DfxMemoryTest011: end."; 408 } 409 410 /** 411 * @tc.name: DfxMemoryTest012 412 * @tc.desc: test DfxMemory class Read in remote case 413 * @tc.type: FUNC 414 */ 415 HWTEST_F(DfxMemoryTest, DfxMemoryTest012, TestSize.Level2) 416 { 417 GTEST_LOG_(INFO) << "DfxMemoryTest012: start."; 418 static pid_t pid = getpid(); 419 pid_t child = fork(); 420 if (child == 0) { 421 GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid(); 422 DfxPtrace::Attach(pid); 423 UnwindContext ctx; 424 ctx.pid = pid; 425 auto acc = std::make_shared<DfxAccessorsRemote>(); 426 auto memory = std::make_shared<DfxMemory>(acc); 427 memory->SetCtx(&ctx); 428 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_absptr), sizeof(uintptr_t)); 429 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata1), 1); 430 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata2), 2); 431 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata4), 4); 432 ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata8), 8); 433 DfxPtrace::Detach(pid); 434 _exit(0); 435 } 436 int status; 437 int ret = wait(&status); 438 GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret; 439 GTEST_LOG_(INFO) << "DfxMemoryTest012: end."; 440 } 441 442 /** 443 * @tc.name: DfxMemoryTest013 444 * @tc.desc: test DfxMemory class Read in error case 445 * @tc.type: FUNC 446 */ 447 HWTEST_F(DfxMemoryTest, DfxMemoryTest013, TestSize.Level2) 448 { 449 GTEST_LOG_(INFO) << "DfxMemoryTest013: start."; 450 auto acc = std::make_shared<DfxAccessorsLocal>(); 451 auto memory = std::make_shared<DfxMemory>(acc); 452 uintptr_t val; 453 EXPECT_FALSE(memory->ReadReg(0, &val)); 454 uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}; 455 UnwindContext ctx; 456 ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs); 457 memory->SetCtx(&ctx); 458 EXPECT_FALSE(memory->ReadReg(-1, &val)); 459 460 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 461 uintptr_t addr = (uintptr_t)(&values[0]); 462 EXPECT_FALSE(memory->ReadMem(addr, nullptr)); 463 EXPECT_FALSE(memory->ReadUptr(addr, nullptr, false)); 464 EXPECT_FALSE(memory->Read(addr, nullptr, sizeof(uint8_t), false)); 465 EXPECT_FALSE(memory->ReadU8(addr, nullptr, false)); 466 EXPECT_FALSE(memory->ReadU16(addr, nullptr, false)); 467 EXPECT_FALSE(memory->ReadU32(addr, nullptr, false)); 468 EXPECT_FALSE(memory->ReadU64(addr, nullptr, false)); 469 GTEST_LOG_(INFO) << "DfxMemoryTest013: end."; 470 } 471 472 } 473 } // namespace HiviewDFX 474 } // namespace OHOS 475