1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 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 <dlfcn.h> 17 #include <fcntl.h> 18 #include <gtest/gtest.h> 19 #include <vector> 20 #include <sys/syscall.h> 21 #include <sys/mman.h> 22 #include "token_setproc.h" 23 #include "accesstoken_kit.h" 24 #include "buffer_splitter.h" 25 #include "common.h" 26 #include "test_common.h" 27 #include "logging.h" 28 #include "parameters.h" 29 #include <fstream> 30 #include <iostream> 31 #include <thread> 32 33 #pragma clang optimize off 34 35 using namespace testing::ext; 36 using namespace OHOS::Security::AccessToken; 37 38 namespace { 39 constexpr int DEFAULT_MALLOC_SIZE = 10; 40 constexpr int DEFAULT_CALLOC_SIZE = 100; 41 constexpr int DEFAULT_REALLOC_SIZE = 1000; 42 constexpr int DATA_SIZE = 50; 43 constexpr int SLEEP_TIME = 10; 44 constexpr int WAIT_FLUSH = 15; 45 constexpr int HOOK_TIME = 10; 46 constexpr int SLEEP_FIVE = 5; 47 48 const std::string DEFAULT_NATIVE_DAEMON_CLIENT_PATH("/data/local/tmp/native_daemon_client"); 49 constexpr int SHARE_MEMORY_SIZE = 1000 * 4096; 50 constexpr int BUFFER_SIZE = 100 * 1024; 51 #ifdef __aarch64__ 52 constexpr int DEFAULT_DEPTH = 32; 53 constexpr int CALLOC_DEPTH = 13; 54 constexpr int REALLOC_DEPTH = 10; 55 constexpr int MALLOC_VEC_SIZE = 5; 56 constexpr int FREE_VEC_SIZE = 4; 57 constexpr int MALLOC_GET_DATE_SIZE = 3; 58 constexpr int FREE_GET_DATA_SIZE = 2; 59 #endif 60 [[maybe_unused]] constexpr int WAIT_TIME = 5; 61 constexpr int START_JS_REPORT = 1; 62 std::unique_ptr<uint8_t[]> g_buffer = std::make_unique<uint8_t[]>(BUFFER_SIZE); 63 const std::string DEFAULT_PATH("/data/local/tmp/"); 64 const std::string TEST_PROC_NAME = "hiview"; 65 static AccessTokenID g_selfTokenId; 66 static TEST_COMMON::MockNativeToken* g_mock = nullptr; 67 #ifdef __aarch64__ 68 const std::string DEFAULT_LIBA_PATH("/system/lib64/liba.z.so"); 69 const std::string DEFAULT_LIBB_PATH("/system/lib64/libb.z.so"); 70 const std::string DEFAULT_LIBNATIVETEST_PATH("/data/local/tmp/libnativetest_so.z.so"); 71 const int LIBA_MALLOC_SIZE = 888; 72 const int LIBB_MALLOC_SIZE = 666; 73 #endif 74 75 typedef char* (*DepthMallocSo)(int depth, int mallocSize); 76 typedef void (*DepthFreeSo)(int depth, char *p); 77 78 using StaticSpace = struct { 79 int data[DATA_SIZE]; 80 }; 81 82 class CheckHookDataTest : public ::testing::Test { 83 public: SetUpTestCase()84 static void SetUpTestCase() 85 { 86 g_selfTokenId = GetSelfTokenID(); 87 TEST_COMMON::SetTestEvironment(g_selfTokenId); 88 g_mock = new (std::nothrow) TEST_COMMON::MockNativeToken(TEST_PROC_NAME); 89 } 90 TearDownTestCase()91 static void TearDownTestCase() 92 { 93 if (g_mock != nullptr) { 94 delete g_mock; 95 g_mock = nullptr; 96 } 97 SetSelfTokenID(g_selfTokenId); 98 TEST_COMMON::ResetTestEvironment(); 99 } StartDaemonProcessArgs()100 void StartDaemonProcessArgs() 101 { 102 outFile_ = DEFAULT_PATH + "hooktest_"+ outFileType_ + mode_[modeIndex_] + ".txt"; 103 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 104 return; 105 } 106 int processNum = fork(); 107 if (processNum == 0) { 108 int waitProcMills = 300; 109 OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0"); 110 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills)); 111 OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "1"); 112 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills)); 113 command_.push_back(const_cast<char*>(DEFAULT_NATIVE_DAEMON_CLIENT_PATH.c_str())); 114 command_.push_back(const_cast<char*>("-s")); 115 command_.push_back(const_cast<char*>("-fn")); 116 command_.push_back(const_cast<char*>(outFile_.c_str())); 117 command_.push_back(const_cast<char*>("-sms")); 118 command_.push_back(const_cast<char*>(std::to_string(SHARE_MEMORY_SIZE).c_str())); 119 command_.push_back(const_cast<char*>("-p")); 120 command_.push_back(const_cast<char*>(std::to_string(hookPid_).c_str())); 121 command_.push_back(const_cast<char*>("-d")); 122 command_.push_back(const_cast<char*>(std::to_string(HOOK_TIME).c_str())); 123 if (modeIndex_ == 0) { 124 command_.push_back(const_cast<char*>("-df")); 125 } 126 if (unwindDepth_ > 0) { 127 command_.push_back(const_cast<char*>("-msd")); 128 command_.push_back(const_cast<char*>(std::to_string(unwindDepth_).c_str())); 129 } 130 if (statisticsInterval_ > 0) { 131 command_.push_back(const_cast<char*>("-si")); 132 command_.push_back(const_cast<char*>(std::to_string(statisticsInterval_).c_str())); 133 } 134 if (sampleInterval_ > 0) { 135 command_.push_back(const_cast<char*>("-spi")); 136 command_.push_back(const_cast<char*>(std::to_string(sampleInterval_).c_str())); 137 } 138 if (!offlineSymbolization_) { 139 command_.push_back(const_cast<char*>("-os")); 140 } 141 if (callframeCompress_) { 142 command_.push_back(const_cast<char*>("-cc")); 143 } 144 if (!stringCompress_) { 145 command_.push_back(const_cast<char*>("-sc")); 146 } 147 if (responseLibraryMode_) { 148 command_.push_back(const_cast<char*>("-r")); 149 } 150 if (saveFile_) { 151 command_.push_back(const_cast<char*>("-sf")); 152 } 153 if (isHookStandalone_) { 154 command_.push_back(const_cast<char*>("-hsa")); 155 } 156 if (mallocFreeMatchingInterval_ > 0) { 157 command_.push_back(const_cast<char*>("-mfmi")); 158 command_.push_back(const_cast<char*>(std::to_string(mallocFreeMatchingInterval_).c_str())); 159 } 160 if (dumpdata_) { 161 command_.push_back(const_cast<char*>("-dd")); 162 } 163 if (nmd_) { 164 command_.push_back(const_cast<char*>("-nmd")); 165 } 166 if (jsReport_) { 167 command_.push_back(const_cast<char*>("-jr")); 168 command_.push_back(const_cast<char*>(std::to_string(START_JS_REPORT).c_str())); 169 command_.push_back(const_cast<char*>("-mjsd")); 170 command_.push_back(const_cast<char*>(std::to_string(jsMaxDepth_).c_str())); 171 } 172 command_.push_back(nullptr); 173 execv(DEFAULT_NATIVE_DAEMON_CLIENT_PATH.c_str(), command_.data()); 174 _exit(1); 175 } else { 176 daemonPid_ = processNum; 177 } 178 } 179 StringSplit(const std::string & str,char delim=';')180 std::vector<std::string>& StringSplit(const std::string& str, char delim = ';') 181 { 182 std::stringstream ss(str); 183 std::string item; 184 static std::vector<std::string> elems; 185 elems.clear(); 186 while (std::getline(ss, item, delim)) { 187 if (!item.empty()) { 188 elems.push_back(item); 189 } 190 } 191 return elems; 192 } 193 StopProcess(int processNum)194 void StopProcess(int processNum) 195 { 196 std::string stopCmd = "kill -9 " + std::to_string(processNum); 197 system(stopCmd.c_str()); 198 } 199 ReadFile(std::string file)200 int32_t ReadFile(std::string file) 201 { 202 int fd = -1; 203 ssize_t bytesRead = 0; 204 char filePath[PATH_MAX + 1] = {0}; 205 206 if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s", file.c_str()) < 0) { 207 const int bufSize = 256; 208 char buf[bufSize] = { 0 }; 209 strerror_r(errno, buf, bufSize); 210 PROFILER_LOG_ERROR(LOG_CORE, "snprintf_s(%s) error, errno(%d:%s)", file.c_str(), errno, buf); 211 return -1; 212 } 213 214 char* realPath = realpath(filePath, nullptr); 215 if (realPath == nullptr) { 216 const int bufSize = 256; 217 char buf[bufSize] = { 0 }; 218 strerror_r(errno, buf, bufSize); 219 PROFILER_LOG_ERROR(LOG_CORE, "realpath(%s) failed, errno(%d:%s)", file.c_str(), errno, buf); 220 return -1; 221 } 222 223 fd = open(realPath, O_RDONLY | O_CLOEXEC); 224 if (fd == -1) { 225 const int bufSize = 256; 226 char buf[bufSize] = { 0 }; 227 strerror_r(errno, buf, bufSize); 228 PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, realPath, errno, buf); 229 return -1; 230 } 231 if (g_buffer == nullptr) { 232 PROFILER_LOG_ERROR(LOG_CORE, "%s:empty address, g_buffer is NULL", __func__); 233 close(fd); 234 return -1; 235 } 236 bytesRead = read(fd, g_buffer.get(), BUFFER_SIZE - 1); 237 if (bytesRead <= 0) { 238 close(fd); 239 PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to read(%s), errno=%d", __func__, realPath, errno); 240 return -1; 241 } 242 close(fd); 243 free(realPath); 244 245 return bytesRead; 246 } 247 DepthFree(int depth,void * p)248 void DepthFree(int depth, void *p) 249 { 250 StaticSpace staticeData; 251 if (depth == 0) { 252 staticeData.data[0] = 1; 253 free(p); 254 return; 255 } 256 return (DepthFree(depth - 1, p)); 257 } 258 DepthMalloc(int depth)259 char *DepthMalloc(int depth) 260 { 261 StaticSpace staticeData; 262 if (depth == 0) { 263 staticeData.data[0] = 1; 264 return reinterpret_cast<char *>(malloc(DEFAULT_MALLOC_SIZE)); 265 } 266 return (DepthMalloc(depth - 1)); 267 } 268 ApplyForMalloc(int depth)269 void ApplyForMalloc(int depth) 270 { 271 char *p = DepthMalloc(depth); 272 if (!p) { 273 const int bufSize = 256; 274 char buf[bufSize] = { 0 }; 275 strerror_r(errno, buf, bufSize); 276 PROFILER_LOG_ERROR(LOG_CORE, "ApplyForMalloc: malloc failure, errno(%d:%s)", errno, buf); 277 return; 278 } 279 DepthFree(depth, p); 280 } 281 282 #ifdef __aarch64__ DlopenAndCloseSo(std::string filePath,int size,int depth)283 void DlopenAndCloseSo(std::string filePath, int size, int depth) 284 { 285 char *ptr = nullptr; 286 void *handle = nullptr; 287 DepthMallocSo mallocFunc = nullptr; 288 DepthFreeSo freeFunc = nullptr; 289 290 handle = dlopen(filePath.data(), RTLD_LAZY); 291 if (handle == nullptr) { 292 fprintf(stderr, "library not exist!\n"); 293 exit(0); 294 } 295 mallocFunc = (DepthMallocSo)dlsym(handle, "DepthMallocSo"); 296 freeFunc = (DepthFreeSo)dlsym(handle, "DepthFreeSo"); 297 if (mallocFunc == nullptr || freeFunc == nullptr) { 298 fprintf(stderr, "function not exist!\n"); 299 exit(0); 300 } 301 ptr = mallocFunc(depth, size); 302 *ptr = 'a'; 303 freeFunc(depth, ptr); 304 if (handle != nullptr) { 305 usleep(100000); // sleep 100000 us 306 dlclose(handle); 307 } 308 } 309 #endif 310 StartMallocProcess()311 void StartMallocProcess() 312 { 313 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 314 return; 315 } 316 int processNum = fork(); 317 if (processNum == 0) { 318 while (1) { 319 ApplyForMalloc(unwindDepth_); 320 usleep(5000); // sleep 5000 us 321 } 322 } else { 323 hookPid_ = processNum; 324 } 325 } 326 327 #ifdef __aarch64__ StartDlopenProcess()328 void StartDlopenProcess() 329 { 330 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 331 return; 332 } 333 int processNum = fork(); 334 if (processNum == 0) { 335 const std::vector<std::string> VEC_SO_PATH { DEFAULT_LIBA_PATH, DEFAULT_LIBB_PATH}; 336 std::string cmdCopyLib{"cp " + DEFAULT_LIBNATIVETEST_PATH + " " + DEFAULT_LIBA_PATH}; 337 system(cmdCopyLib.c_str()); 338 cmdCopyLib = "cp " + DEFAULT_LIBA_PATH + " " + DEFAULT_LIBB_PATH; 339 system(cmdCopyLib.c_str()); 340 while (true) { 341 DlopenAndCloseSo(VEC_SO_PATH[0], LIBA_MALLOC_SIZE, unwindDepth_); 342 DlopenAndCloseSo(VEC_SO_PATH[1], LIBB_MALLOC_SIZE, unwindDepth_); 343 } 344 } else { 345 hookPid_ = processNum; 346 } 347 } 348 #endif 349 DepthCalloc(int depth,int callocSize)350 char* DepthCalloc(int depth, int callocSize) 351 { 352 StaticSpace staticeData; 353 if (depth == 0) { 354 staticeData.data[0] = 1; 355 return reinterpret_cast<char *>(calloc(sizeof(char), callocSize)); 356 } 357 return (DepthCalloc(depth - 1, callocSize)); 358 } 359 ApplyForCalloc(int depth)360 void ApplyForCalloc(int depth) 361 { 362 int callocSize = DEFAULT_CALLOC_SIZE / sizeof(char); 363 char *p = DepthCalloc(depth, callocSize); 364 if (!p) { 365 const int bufSize = 256; 366 char buf[bufSize] = { 0 }; 367 strerror_r(errno, buf, bufSize); 368 PROFILER_LOG_ERROR(LOG_CORE, "ApplyForCalloc: calloc failure, errno(%d:%s)", errno, buf); 369 return; 370 } 371 DepthFree(depth, p); 372 } 373 StartCallocProcess(int depth)374 void StartCallocProcess(int depth) 375 { 376 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 377 return; 378 } 379 int processNum = fork(); 380 if (processNum == 0) { 381 int firstSleep = 3; // avoid malloc before sending kill -36 signal 382 int secondSleep = 2; 383 sleep(firstSleep); 384 sleep(secondSleep); 385 auto ret = malloc(DEFAULT_MALLOC_SIZE); 386 free(ret); 387 while (1) { 388 ApplyForCalloc(depth); 389 usleep(5000); // sleep 5000 us 390 } 391 } else { 392 hookPid_ = processNum; 393 } 394 } 395 DepthRealloc(int depth,void * p,int reallocSize)396 char *DepthRealloc(int depth, void *p, int reallocSize) 397 { 398 StaticSpace staticeData; 399 if (depth == 0) { 400 staticeData.data[0] = 1; 401 return reinterpret_cast<char *>(realloc(p, reallocSize)); 402 } 403 return (DepthRealloc(depth - 1, p, reallocSize)); 404 } 405 ApplyForRealloc(int depth)406 void ApplyForRealloc(int depth) 407 { 408 int reallocSize = DEFAULT_REALLOC_SIZE; 409 char *p = reinterpret_cast<char *>(malloc(DEFAULT_MALLOC_SIZE)); 410 if (!p) { 411 const int bufSize = 256; 412 char buf[bufSize] = { 0 }; 413 strerror_r(errno, buf, bufSize); 414 PROFILER_LOG_ERROR(LOG_CORE, "ApplyForRealloc: malloc failure, errno(%d:%s)", errno, buf); 415 return; 416 } 417 char *np = DepthRealloc(depth, p, reallocSize); 418 if (!np) { 419 free(p); 420 const int bufSize = 256; 421 char buf[bufSize] = { 0 }; 422 strerror_r(errno, buf, bufSize); 423 PROFILER_LOG_ERROR(LOG_CORE, "ApplyForRealloc: realloc failure, errno(%d:%s)", errno, buf); 424 return; 425 } 426 DepthFree(depth, np); 427 } 428 StartReallocProcess(int depth)429 void StartReallocProcess(int depth) 430 { 431 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 432 return; 433 } 434 int processNum = fork(); 435 if (processNum == 0) { 436 while (1) { 437 ApplyForRealloc(depth); 438 usleep(5000); // sleep 5000 us 439 } 440 } else { 441 hookPid_ = processNum; 442 } 443 } 444 Getdata(BufferSplitter & totalbuffer,std::vector<std::string> & hookVec,char delimiter)445 bool Getdata(BufferSplitter& totalbuffer, std::vector<std::string>& hookVec, char delimiter) 446 { 447 totalbuffer.NextWord(delimiter); 448 if (!totalbuffer.CurWord()) { 449 return false; 450 } 451 std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize()); 452 hookVec.push_back(curWord); 453 return true; 454 } 455 StartAndStopHook()456 void StartAndStopHook() 457 { 458 #ifdef COVERAGE_TEST 459 const int coverageSleepTime = 5; // sleep 5s 460 sleep(coverageSleepTime); 461 462 #endif 463 StartDaemonProcessArgs(); 464 StopProcess(hookPid_); 465 StopProcess(daemonPid_); 466 sleep(SLEEP_FIVE); 467 } 468 int daemonPid_ = -1; 469 int hookPid_ = -1; 470 int modeIndex_ = 0; 471 int unwindDepth_ = 0; 472 int statisticsInterval_ = 0; 473 int sampleInterval_ = 0; 474 int jsReport_ = 0; 475 int jsMaxDepth_ = 0; 476 int mallocFreeMatchingInterval_ = 0; 477 bool offlineSymbolization_ = false; 478 bool callframeCompress_ = false; 479 bool stringCompress_ = false; 480 bool rawString_ = false; 481 bool responseLibraryMode_ = false; 482 bool saveFile_ = false; 483 bool isHookStandalone_ = true; 484 bool dumpdata_ = false; 485 bool nmd_ = false; 486 std::string outFile_ = ""; 487 std::string outFileType_ = ""; 488 std::string mode_[2] = {"dwarf", "fp"}; 489 std::vector<char*> command_; 490 }; 491 492 /** 493 * @tc.name: native hook 494 * @tc.desc: Test hook malloc normal process. 495 * @tc.type: FUNC 496 */ 497 #ifdef __aarch64__ 498 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0080, Function | MediumTest | Level1) 499 { 500 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 501 unwindDepth_ = 30; 502 outFileType_ = "malloc_"; 503 modeIndex_ = i; // 0 is dwarf, 1 is fp mode 504 saveFile_ = true; 505 isHookStandalone_ = false; 506 StartMallocProcess(); 507 sleep(1); 508 StartDaemonProcessArgs(); 509 sleep(WAIT_FLUSH); 510 StopProcess(hookPid_); 511 syscall(SYS_tkill, daemonPid_, 2); 512 513 int32_t ret = ReadFile(outFile_); 514 ASSERT_NE(ret, -1); 515 516 BufferSplitter totalbuffer(const_cast<char*>((char*)g_buffer.get()), ret + 1); 517 std::vector<std::string> hookVec; 518 std::string addr = ""; 519 int depth = 0; 520 int addrPos = 3; 521 bool isFirstHook = true; 522 do { 523 char delimiter = ';'; 524 Getdata(totalbuffer, hookVec, delimiter); 525 526 if (hookVec.size() < 6) { 527 continue; 528 } 529 if (hookVec[0] == "malloc" && !isFirstHook) { 530 for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { 531 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 532 } 533 delimiter = '\n'; 534 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 535 ASSERT_EQ(static_cast<int>(hookVec.size()), MALLOC_VEC_SIZE); 536 ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); 537 ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_MALLOC_SIZE); // 4: fifth hook data, default malloc size 538 539 addr = hookVec[addrPos]; 540 depth = 0; 541 } else if (hookVec[0] == "free" && !isFirstHook) { 542 for (int i = 0; i < FREE_GET_DATA_SIZE; i++) { 543 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 544 } 545 delimiter = '\n'; 546 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 547 ASSERT_EQ(static_cast<int>(hookVec.size()), FREE_VEC_SIZE); 548 EXPECT_STREQ(hookVec[addrPos].c_str(), addr.c_str()); 549 EXPECT_EQ(depth, DEFAULT_DEPTH); 550 551 isFirstHook = false; 552 addr = ""; 553 depth = 0; 554 } else { 555 depth++; 556 } 557 558 hookVec.clear(); 559 } while (totalbuffer.NextLine()); 560 } 561 } 562 563 /** 564 * @tc.name: native hook 565 * @tc.desc: Test hook calloc normal process. 566 * @tc.type: FUNC 567 */ 568 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0090, Function | MediumTest | Level3) 569 { 570 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 571 int setDepth = 1; 572 unwindDepth_ = 100; 573 outFileType_ = "calloc_"; 574 modeIndex_ = i; 575 saveFile_ = true; 576 isHookStandalone_ = false; 577 StartCallocProcess(setDepth); 578 sleep(1); 579 StartDaemonProcessArgs(); 580 sleep(WAIT_FLUSH); 581 StopProcess(hookPid_); 582 syscall(SYS_tkill, daemonPid_, 2); 583 584 int32_t ret = ReadFile(outFile_); 585 ASSERT_NE(ret, -1); 586 587 BufferSplitter totalbuffer(const_cast<char*>((char*)g_buffer.get()), ret + 1); 588 std::vector<std::string> hookVec; 589 std::string addr = ""; 590 int depth = 0; 591 int addrPos = 3; 592 bool isFirstHook = true; 593 do { 594 char delimiter = ';'; 595 Getdata(totalbuffer, hookVec, delimiter); 596 597 if (hookVec.size() < 6) { 598 continue; 599 } 600 if (hookVec[0] == "malloc" && !isFirstHook) { 601 for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { 602 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 603 } 604 delimiter = '\n'; 605 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 606 ASSERT_EQ(static_cast<int>(hookVec.size()), MALLOC_VEC_SIZE); 607 ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); 608 ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_CALLOC_SIZE); // 4: fifth hook data, default malloc size 609 610 addr = hookVec[addrPos]; 611 depth = 0; 612 } else if (hookVec[0] == "free" && !isFirstHook) { 613 for (int i = 0; i < FREE_GET_DATA_SIZE; i++) { 614 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 615 } 616 delimiter = '\n'; 617 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 618 ASSERT_EQ(static_cast<int>(hookVec.size()), FREE_VEC_SIZE); 619 EXPECT_STREQ(hookVec[addrPos].c_str(), addr.c_str()); 620 EXPECT_GE(depth, CALLOC_DEPTH); 621 622 isFirstHook = false; 623 addr = ""; 624 depth = 0; 625 } else { 626 depth++; 627 } 628 629 hookVec.clear(); 630 } while (totalbuffer.NextLine()); 631 } 632 } 633 634 /** 635 * @tc.name: native hook 636 * @tc.desc: Test hook realloc normal process. 637 * @tc.type: FUNC 638 */ 639 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0100, Function | MediumTest | Level3) 640 { 641 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 642 int setDepth = 100; 643 outFileType_ = "realloc_"; 644 modeIndex_ = i; 645 saveFile_ = true; 646 isHookStandalone_ = false; 647 StartReallocProcess(setDepth); 648 sleep(1); 649 StartDaemonProcessArgs(); 650 sleep(WAIT_FLUSH); 651 StopProcess(hookPid_); 652 syscall(SYS_tkill, daemonPid_, 2); 653 654 int32_t ret = ReadFile(outFile_); 655 ASSERT_NE(ret, -1); 656 657 BufferSplitter totalbuffer(const_cast<char*>((char*)g_buffer.get()), ret + 1); 658 std::vector<std::string> hookVec; 659 std::string mallocAddr = ""; 660 std::string reallocAddr = ""; 661 int depth = 0; 662 int addrPos = 3; 663 bool isFirstHook = true; 664 bool isRealloc = false; 665 do { 666 char delimiter = ';'; 667 Getdata(totalbuffer, hookVec, delimiter); 668 669 if (hookVec.size() < 6) { 670 continue; 671 } 672 if (hookVec[0] == "malloc" && !isFirstHook) { 673 for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { 674 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 675 } 676 delimiter = '\n'; 677 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 678 ASSERT_EQ(static_cast<int>(hookVec.size()), MALLOC_VEC_SIZE); 679 680 if (isRealloc) { 681 reallocAddr = hookVec[addrPos]; 682 // 4: fifth hook data, default malloc size 683 ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); 684 ASSERT_GE(atoi(hookVec[4].c_str()), DEFAULT_REALLOC_SIZE); 685 EXPECT_GE(depth, REALLOC_DEPTH); 686 isFirstHook = false; 687 } else { 688 mallocAddr = hookVec[addrPos]; 689 // 4: fifth hook data, default malloc size 690 ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); 691 ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_MALLOC_SIZE); 692 } 693 694 isRealloc = true; 695 depth = 0; 696 } else if (hookVec[0] == "free" && !isFirstHook) { 697 for (int i = 0; i < FREE_GET_DATA_SIZE; i++) { 698 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 699 } 700 delimiter = '\n'; 701 EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); 702 ASSERT_EQ(static_cast<int>(hookVec.size()), FREE_VEC_SIZE); 703 704 if (isRealloc) { 705 EXPECT_STREQ(hookVec[addrPos].c_str(), reallocAddr.c_str()); 706 reallocAddr = ""; 707 } else { 708 EXPECT_STREQ(hookVec[addrPos].c_str(), mallocAddr.c_str()); 709 mallocAddr = ""; 710 } 711 712 isRealloc = false; 713 depth = 0; 714 } else { 715 depth++; 716 } 717 718 hookVec.clear(); 719 } while (totalbuffer.NextLine()); 720 } 721 } 722 723 /** 724 * @tc.name: native hook 725 * @tc.desc: Test hook dlopen normal process. just for arm64 726 * @tc.type: FUNC 727 */ 728 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0110, Function | MediumTest | Level3) 729 { 730 for (size_t i = 1; i < 2; ++i) { 731 unwindDepth_ = 6; 732 outFileType_ = "dlopen_"; 733 modeIndex_ = i; 734 saveFile_ = true; 735 isHookStandalone_ = false; 736 StartDlopenProcess(); 737 sleep(1); 738 StartDaemonProcessArgs(); 739 sleep(WAIT_FLUSH); 740 StopProcess(hookPid_); 741 syscall(SYS_tkill, daemonPid_, 2); 742 743 std::ifstream infile; 744 infile.open(outFile_, std::ios::in); 745 ASSERT_TRUE(infile.is_open()); 746 std::string buf; 747 uint8_t mallocPos = 0; 748 uint8_t mallocSizePos = 6; 749 uint8_t libUnwindDepth = 3; 750 while (getline(infile, buf)) 751 { 752 std::vector<std::string>& resultVec = StringSplit(buf); 753 if (resultVec.size() < static_cast<size_t>(mallocSizePos)) { 754 continue; 755 } 756 if (resultVec[mallocPos] == "malloc") { 757 if (resultVec[mallocSizePos] == std::to_string(LIBA_MALLOC_SIZE)) { 758 std::cout << buf << std::endl; 759 for (size_t i = 0; i < libUnwindDepth; i++) { 760 getline(infile, buf); 761 } 762 std::cout << buf << std::endl; 763 EXPECT_TRUE((buf.find("liba.z.so") != std::string::npos) || 764 (buf.find("libb.z.so") != std::string::npos)); 765 } else if (resultVec[mallocSizePos] == std::to_string(LIBB_MALLOC_SIZE)) { 766 std::cout << buf << std::endl; 767 for (size_t i = 0; i < libUnwindDepth; i++) { 768 getline(infile, buf); 769 } 770 std::cout << buf << std::endl; 771 EXPECT_TRUE((buf.find("liba.z.so") != std::string::npos) || 772 (buf.find("libb.z.so") != std::string::npos)); 773 } 774 } 775 } 776 } 777 } 778 779 /** 780 * @tc.name: native hook 781 * @tc.desc: Test hook statistics data normal process. 782 * @tc.type: FUNC 783 */ 784 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0120, Function | MediumTest | Level1) 785 { 786 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 787 unwindDepth_ = 10; 788 statisticsInterval_ = 1; 789 outFileType_ = "statistics_interval_"; 790 modeIndex_ = i; 791 StartMallocProcess(); 792 sleep(1); 793 StartDaemonProcessArgs(); 794 sleep(WAIT_FLUSH); 795 StopProcess(hookPid_); 796 syscall(SYS_tkill, daemonPid_, 2); 797 798 std::ifstream infile; 799 infile.open(outFile_, std::ios::in); 800 ASSERT_TRUE(infile.is_open()); 801 std::string buf; 802 std::string expectCallStackId; 803 std::string statisticsCallStackId; 804 while (getline(infile, buf)) { 805 if (buf.find("stack_map") != std::string::npos) { 806 if (!expectCallStackId.empty()) { 807 continue; 808 } 809 getline(infile, buf); // read stack_map id 810 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 811 expectCallStackId = resultVec[1]; 812 std::cout << "expectCallStackId: " << expectCallStackId << std::endl; 813 } else if (buf.find("statistics_event") != std::string::npos) { 814 getline(infile, buf); // read statistics_event pid 815 getline(infile, buf); // read statistics_event callstack_id 816 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 817 statisticsCallStackId = resultVec[1]; 818 std::cout << "statisticsCallStackId: " << statisticsCallStackId << std::endl; 819 if (expectCallStackId == statisticsCallStackId) { 820 break; 821 } 822 } 823 } 824 getline(infile, buf); // read statistics_event apply_count 825 if (buf.find("type") != std::string::npos) { 826 getline(infile, buf); 827 } 828 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 829 ASSERT_FALSE(resultVec.empty()); 830 if (!resultVec.empty() && resultVec.size() > 1) { 831 ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); 832 uint16_t applyCount = std::atoi(resultVec[1].c_str()); 833 std::cout << "applyCount: " << applyCount << std::endl; 834 EXPECT_TRUE(applyCount > 0); 835 } 836 sleep(SLEEP_TIME); 837 } 838 } 839 #endif 840 841 /** 842 * @tc.name: native hook 843 * @tc.desc: Test hook offline symbolization data normal process. 844 * @tc.type: FUNC 845 */ 846 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0130, Function | MediumTest | Level1) 847 { 848 for (size_t i = 0; i < 2; ++i) { 849 unwindDepth_ = 10; 850 outFileType_ = "offline_symbolization_"; 851 modeIndex_ = i; 852 offlineSymbolization_ = true; 853 StartMallocProcess(); 854 sleep(1); 855 StartDaemonProcessArgs(); 856 sleep(WAIT_FLUSH); 857 StopProcess(hookPid_); 858 syscall(SYS_tkill, daemonPid_, 2); 859 860 std::ifstream infile; 861 infile.open(outFile_, std::ios::in); 862 ASSERT_TRUE(infile.is_open()); 863 std::string buf; 864 std::string symTable; 865 std::string strTable; 866 std::string ipString; 867 while (getline(infile, buf)) { 868 if (buf.find("stack_map") != std::string::npos) { 869 getline(infile, buf); // read stack map id 870 getline(infile, buf); // read stack map ip 871 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 872 ipString = resultVec[0]; 873 // delete whitespace characters 874 ipString.erase(std::remove(ipString.begin(), ipString.end(), ' '), ipString.end()); 875 EXPECT_TRUE(ipString == "ip"); 876 } else if (buf.find("sym_table") != std::string::npos) { 877 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 878 symTable = resultVec[1]; 879 EXPECT_TRUE(symTable.size() > 0); 880 } else if (buf.find("str_table") != std::string::npos) { 881 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 882 strTable = resultVec[1]; 883 EXPECT_TRUE(strTable.size() > 0); 884 if (ipString == "ip" && symTable.size()) { 885 break; 886 } 887 } 888 } 889 } 890 } 891 892 /** 893 * @tc.name: native hook 894 * @tc.desc: Test hook callframe compress normal process. 895 * @tc.type: FUNC 896 */ 897 #ifdef __aarch64__ 898 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0140, Function | MediumTest | Level3) 899 { 900 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 901 unwindDepth_ = 6; 902 outFileType_ = "callframecompress_"; 903 modeIndex_ = i; 904 callframeCompress_ = true; 905 StartMallocProcess(); 906 sleep(1); 907 StartDaemonProcessArgs(); 908 sleep(WAIT_FLUSH); 909 StopProcess(hookPid_); 910 syscall(SYS_tkill, daemonPid_, 2); 911 912 std::ifstream infile; 913 infile.open(outFile_, std::ios::in); 914 ASSERT_TRUE(infile.is_open()); 915 std::string buf; 916 bool findSymbolName; 917 bool findfilePath; 918 bool findFrameMap; 919 bool findStackMap; 920 while (getline(infile, buf)) 921 { 922 if (!findSymbolName || buf.find("symbol_name") != std::string::npos) { 923 findSymbolName = true; 924 } else if (!findfilePath || buf.find("file_path") != std::string::npos) { 925 findfilePath = true; 926 } else if (!findFrameMap || buf.find("frame_map") != std::string::npos) { 927 findFrameMap = true; 928 } else if (!findStackMap || buf.find("stack_map") != std::string::npos) { 929 findStackMap = true; 930 if (findSymbolName && findfilePath && findFrameMap) { 931 break; 932 } 933 } 934 } 935 EXPECT_TRUE(findSymbolName); 936 EXPECT_TRUE(findfilePath); 937 EXPECT_TRUE(findFrameMap); 938 EXPECT_TRUE(findStackMap); 939 } 940 } 941 942 /** 943 * @tc.name: native hook 944 * @tc.desc: Test hook string compress normal process. 945 * @tc.type: FUNC 946 */ 947 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0150, Function | MediumTest | Level3) 948 { 949 for (size_t i = 0; i < 2; ++i) { 950 unwindDepth_ = 6; 951 outFileType_ = "stringcompress_"; 952 modeIndex_ = i; 953 stringCompress_ = true; 954 StartMallocProcess(); 955 sleep(1); 956 StartDaemonProcessArgs(); 957 sleep(WAIT_FLUSH); 958 StopProcess(hookPid_); 959 syscall(SYS_tkill, daemonPid_, 2); 960 961 std::ifstream infile; 962 infile.open(outFile_, std::ios::in); 963 ASSERT_TRUE(infile.is_open()); 964 std::string buf; 965 bool findFrameInfo; 966 bool findSymbolNameId; 967 while (getline(infile, buf)) 968 { 969 if (!findFrameInfo || buf.find("frame_info") != std::string::npos) { 970 findFrameInfo = true; 971 } else if (!findSymbolNameId || buf.find("symbol_name_id") != std::string::npos) { 972 findSymbolNameId = true; 973 if (findFrameInfo) { 974 break; 975 } 976 } 977 } 978 EXPECT_TRUE(findFrameInfo); 979 EXPECT_TRUE(findSymbolNameId); 980 } 981 } 982 983 /** 984 * @tc.name: native hook 985 * @tc.desc: Test hook raw string normal process. 986 * @tc.type: FUNC 987 */ 988 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Level3) 989 { 990 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 991 unwindDepth_ = 6; 992 outFileType_ = "rawstring_"; 993 modeIndex_ = i; 994 rawString_ = true; 995 StartMallocProcess(); 996 sleep(1); 997 StartDaemonProcessArgs(); 998 sleep(WAIT_FLUSH); 999 StopProcess(hookPid_); 1000 syscall(SYS_tkill, daemonPid_, 2); 1001 1002 std::ifstream infile; 1003 infile.open(outFile_, std::ios::in); 1004 ASSERT_TRUE(infile.is_open()); 1005 std::string buf; 1006 bool findFrameInfo; 1007 bool findSymbolName; 1008 while (getline(infile, buf)) 1009 { 1010 if (!findFrameInfo || buf.find("frame_info") != std::string::npos) { 1011 findFrameInfo = true; 1012 } else if (!findSymbolName || buf.find("symbol_name") != std::string::npos) { 1013 findSymbolName = true; 1014 if (findFrameInfo) { 1015 break; 1016 } 1017 } 1018 } 1019 EXPECT_TRUE(findFrameInfo); 1020 EXPECT_TRUE(findSymbolName); 1021 } 1022 } 1023 1024 /** 1025 * @tc.name: native hook 1026 * @tc.desc: Test hook raw responseLibraryMode normal process. 1027 * @tc.type: FUNC 1028 */ 1029 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Level3) 1030 { 1031 for (size_t i = 1; i < 2; ++i) { // 1 is fp mode, response_library_mode only fp mode is used 1032 unwindDepth_ = 6; 1033 outFileType_ = "responseLibraryMode"; 1034 modeIndex_ = i; 1035 responseLibraryMode_ = true; 1036 StartMallocProcess(); 1037 sleep(1); 1038 StartDaemonProcessArgs(); 1039 sleep(WAIT_FLUSH); 1040 StopProcess(hookPid_); 1041 syscall(SYS_tkill, daemonPid_, 2); 1042 1043 std::ifstream infile; 1044 infile.open(outFile_, std::ios::in); 1045 ASSERT_TRUE(infile.is_open()); 1046 std::string buf; 1047 uint16_t ipCount = 0; 1048 1049 while (getline(infile, buf)) { 1050 if (buf.find("stack_map") != std::string::npos) { 1051 while (getline(infile, buf)) { 1052 if (buf.find("ip") != std::string::npos) { 1053 ++ipCount; 1054 continue; 1055 } else if (buf.find("}") != std::string::npos) { 1056 break; 1057 } 1058 } 1059 } 1060 if (ipCount > 0) { 1061 break; 1062 } 1063 } 1064 EXPECT_TRUE(ipCount == 1); // response_library_mode callstack depth only is 1 1065 } 1066 } 1067 1068 /** 1069 * @tc.name: native hook 1070 * @tc.desc: Test hook statistics data normal process. 1071 * @tc.type: FUNC 1072 */ 1073 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0180, Function | MediumTest | Level1) 1074 { 1075 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1076 unwindDepth_ = 10; 1077 statisticsInterval_ = 1; 1078 sampleInterval_ = 256; 1079 outFileType_ = "sample_interval_"; 1080 modeIndex_ = i; 1081 StartMallocProcess(); 1082 sleep(1); 1083 StartDaemonProcessArgs(); 1084 sleep(WAIT_FLUSH); 1085 StopProcess(hookPid_); 1086 syscall(SYS_tkill, daemonPid_, 2); 1087 1088 std::ifstream infile; 1089 infile.open(outFile_, std::ios::in); 1090 ASSERT_TRUE(infile.is_open()); 1091 std::string buf; 1092 std::string expectCallStackId; 1093 std::string statisticsCallStackId; 1094 while (getline(infile, buf)) { 1095 if (buf.find("stack_map") != std::string::npos) { 1096 if (!expectCallStackId.empty()) { 1097 continue; 1098 } 1099 getline(infile, buf); // read stack_map id 1100 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1101 expectCallStackId = resultVec[1]; 1102 std::cout << "expectCallStackId: " << expectCallStackId << std::endl; 1103 } else if (buf.find("statistics_event") != std::string::npos) { 1104 getline(infile, buf); // read statistics_event pid 1105 getline(infile, buf); // read statistics_event callstack_id 1106 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1107 statisticsCallStackId = resultVec[1]; 1108 std::cout << "statisticsCallStackId: " << statisticsCallStackId << std::endl; 1109 if (expectCallStackId == statisticsCallStackId) { 1110 break; 1111 } 1112 } 1113 } 1114 getline(infile, buf); // read statistics_event apply_count 1115 if (buf.find("type") != std::string::npos) { 1116 getline(infile, buf); 1117 } 1118 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1119 ASSERT_FALSE(resultVec.empty()); 1120 ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); 1121 uint16_t applyCount = std::atoi(resultVec[1].c_str()); 1122 std::cout << "applyCount: " << applyCount << std::endl; 1123 EXPECT_TRUE(applyCount > 0); 1124 sleep(SLEEP_TIME); 1125 } 1126 } 1127 1128 /** 1129 * @tc.name: native hook 1130 * @tc.desc: Test hook alloc free matching interval normal process. 1131 * @tc.type: FUNC 1132 */ 1133 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0190, Function | MediumTest | Level3) 1134 { 1135 for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1136 unwindDepth_ = 6; 1137 outFileType_ = "mallocFreeMatchingInterval_"; 1138 modeIndex_ = i; 1139 mallocFreeMatchingInterval_ = 2; 1140 StartMallocProcess(); 1141 sleep(1); 1142 StartDaemonProcessArgs(); 1143 sleep(WAIT_FLUSH); 1144 StopProcess(hookPid_); 1145 syscall(SYS_tkill, daemonPid_, 2); 1146 1147 std::ifstream infile; 1148 infile.open(outFile_, std::ios::in); 1149 ASSERT_TRUE(infile.is_open()); 1150 std::string buf; 1151 bool findSymbolName; 1152 bool findfilePath; 1153 bool findFrameMap; 1154 bool findStackMap; 1155 while (getline(infile, buf)) 1156 { 1157 if (!findSymbolName || buf.find("symbol_name") != std::string::npos) { 1158 findSymbolName = true; 1159 } else if (!findfilePath || buf.find("file_path") != std::string::npos) { 1160 findfilePath = true; 1161 } else if (!findFrameMap || buf.find("frame_map") != std::string::npos) { 1162 findFrameMap = true; 1163 } else if (!findStackMap || buf.find("stack_map") != std::string::npos) { 1164 findStackMap = true; 1165 if (findSymbolName && findfilePath && findFrameMap) { 1166 break; 1167 } 1168 } 1169 } 1170 EXPECT_TRUE(findSymbolName); 1171 EXPECT_TRUE(findfilePath); 1172 EXPECT_TRUE(findFrameMap); 1173 EXPECT_TRUE(findStackMap); 1174 } 1175 } 1176 1177 1178 /** 1179 * @tc.name: native hook 1180 * @tc.desc: Test hook js statistics data normal process. 1181 * @tc.type: FUNC 1182 */ 1183 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Level1) 1184 { 1185 for (size_t i = 1; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1186 unwindDepth_ = 10; 1187 statisticsInterval_ = 1; 1188 jsReport_ = 1; 1189 jsMaxDepth_ = 10; 1190 outFileType_ = "js_report_"; 1191 modeIndex_ = i; 1192 StartMallocProcess(); 1193 sleep(1); 1194 StartDaemonProcessArgs(); 1195 sleep(WAIT_FLUSH); 1196 StopProcess(hookPid_); 1197 syscall(SYS_tkill, daemonPid_, 2); 1198 1199 std::ifstream infile; 1200 infile.open(outFile_, std::ios::in); 1201 ASSERT_TRUE(infile.is_open()); 1202 std::string buf; 1203 std::string expectCallStackId; 1204 std::string statisticsCallStackId; 1205 while (getline(infile, buf)) { 1206 if (buf.find("stack_map") != std::string::npos) { 1207 if (!expectCallStackId.empty()) { 1208 continue; 1209 } 1210 getline(infile, buf); // read stack_map id 1211 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1212 expectCallStackId = resultVec[1]; 1213 std::cout << "expectCallStackId: " << expectCallStackId << std::endl; 1214 } else if (buf.find("statistics_event") != std::string::npos) { 1215 getline(infile, buf); // read statistics_event pid 1216 getline(infile, buf); // read statistics_event callstack_id 1217 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1218 statisticsCallStackId = resultVec[1]; 1219 std::cout << "statisticsCallStackId: " << statisticsCallStackId << std::endl; 1220 if (expectCallStackId == statisticsCallStackId) { 1221 break; 1222 } 1223 } 1224 } 1225 getline(infile, buf); // read statistics_event apply_count 1226 if (buf.find("type") != std::string::npos) { 1227 getline(infile, buf); 1228 } 1229 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1230 ASSERT_FALSE(resultVec.empty()); 1231 ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); 1232 uint16_t applyCount = std::atoi(resultVec[1].c_str()); 1233 std::cout << "applyCount: " << applyCount << std::endl; 1234 EXPECT_TRUE(applyCount > 0); 1235 sleep(SLEEP_TIME); 1236 } 1237 } 1238 #endif 1239 1240 /** 1241 * @tc.name: native hook 1242 * @tc.desc: Test no data queue normal process. 1243 * @tc.type: FUNC 1244 */ 1245 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0210, Function | MediumTest | Level1) 1246 { 1247 for (size_t i = 1; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1248 unwindDepth_ = 10; 1249 statisticsInterval_ = 1; 1250 sampleInterval_ = 256; 1251 offlineSymbolization_ = true; 1252 outFileType_ = "no_data_queue_"; 1253 modeIndex_ = i; 1254 StartMallocProcess(); 1255 sleep(1); 1256 StartDaemonProcessArgs(); 1257 sleep(WAIT_FLUSH); 1258 StopProcess(hookPid_); 1259 syscall(SYS_tkill, daemonPid_, 2); 1260 1261 std::ifstream infile; 1262 infile.open(outFile_, std::ios::in); 1263 ASSERT_TRUE(infile.is_open()); 1264 std::string buf; 1265 std::string expectCallStackId; 1266 std::string statisticsCallStackId; 1267 while (getline(infile, buf)) { 1268 if (buf.find("stack_map") != std::string::npos) { 1269 if (!expectCallStackId.empty()) { 1270 continue; 1271 } 1272 getline(infile, buf); // read stack_map id 1273 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1274 expectCallStackId = resultVec[1]; 1275 std::cout << "expectCallStackId: " << expectCallStackId << std::endl; 1276 } else if (buf.find("statistics_event") != std::string::npos) { 1277 getline(infile, buf); // read statistics_event pid 1278 getline(infile, buf); // read statistics_event callstack_id 1279 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1280 statisticsCallStackId = resultVec[1]; 1281 std::cout << "statisticsCallStackId: " << statisticsCallStackId << std::endl; 1282 if (expectCallStackId == statisticsCallStackId) { 1283 break; 1284 } 1285 } 1286 } 1287 getline(infile, buf); // read statistics_event apply_count 1288 if (buf.find("type") != std::string::npos) { 1289 getline(infile, buf); 1290 } 1291 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1292 ASSERT_FALSE(resultVec.empty()); 1293 ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); 1294 uint16_t applyCount = std::atoi(resultVec[1].c_str()); 1295 std::cout << "applyCount: " << applyCount << std::endl; 1296 EXPECT_TRUE(applyCount > 0); 1297 sleep(SLEEP_TIME); 1298 } 1299 } 1300 1301 /** 1302 * @tc.name: native hook 1303 * @tc.desc: Test dumpdata normal process. 1304 * @tc.type: FUNC 1305 */ 1306 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0220, Function | MediumTest | Level1) 1307 { 1308 for (size_t i = 1; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1309 unwindDepth_ = 10; 1310 statisticsInterval_ = 1; 1311 modeIndex_ = i; 1312 dumpdata_ = true; 1313 StartMallocProcess(); 1314 sleep(1); 1315 StartDaemonProcessArgs(); 1316 sleep(WAIT_FLUSH); 1317 StopProcess(hookPid_); 1318 syscall(SYS_tkill, daemonPid_, 2); 1319 1320 std::ifstream infile; 1321 outFile_ = "/data/local/tmp/test_dump_file.htrace"; 1322 infile.open(outFile_, std::ios::in); 1323 ASSERT_TRUE(infile.is_open()); 1324 std::string buf; 1325 std::string expectCallStackId; 1326 std::string statisticsCallStackId; 1327 while (getline(infile, buf)) { 1328 if (buf.find("stack_map") != std::string::npos) { 1329 if (!expectCallStackId.empty()) { 1330 continue; 1331 } 1332 getline(infile, buf); // read stack_map id 1333 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1334 expectCallStackId = resultVec[1]; 1335 std::cout << "expectCallStackId: " << expectCallStackId << std::endl; 1336 } else if (buf.find("statistics_event") != std::string::npos) { 1337 getline(infile, buf); // read statistics_event pid 1338 getline(infile, buf); // read statistics_event callstack_id 1339 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1340 statisticsCallStackId = resultVec[1]; 1341 std::cout << "statisticsCallStackId: " << statisticsCallStackId << std::endl; 1342 if (expectCallStackId == statisticsCallStackId) { 1343 break; 1344 } 1345 } 1346 } 1347 getline(infile, buf); // read statistics_event apply_count 1348 if (buf.find("type") != std::string::npos) { 1349 getline(infile, buf); 1350 } 1351 std::vector<std::string>& resultVec = StringSplit(buf, ':'); 1352 ASSERT_FALSE(resultVec.empty()); 1353 ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); 1354 uint16_t applyCount = std::atoi(resultVec[1].c_str()); 1355 std::cout << "applyCount: " << applyCount << std::endl; 1356 EXPECT_TRUE(applyCount > 0); 1357 sleep(SLEEP_TIME); 1358 } 1359 } 1360 1361 /** 1362 * @tc.name: native hook 1363 * @tc.desc: Test nmd normal process. 1364 * @tc.type: FUNC 1365 */ 1366 #ifdef __aarch64__ 1367 HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0230, Function | MediumTest | Level1) 1368 { 1369 for (size_t i = 1; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode 1370 modeIndex_ = i; 1371 dumpdata_ = true; 1372 nmd_ = true; 1373 StartMallocProcess(); 1374 sleep(1); 1375 StartDaemonProcessArgs(); 1376 sleep(WAIT_FLUSH); 1377 StopProcess(hookPid_); 1378 syscall(SYS_tkill, daemonPid_, 2); 1379 1380 std::ifstream infile; 1381 outFile_ = "/data/local/tmp/test_dump_file0.htrace"; 1382 infile.open(outFile_, std::ios::in); 1383 ASSERT_TRUE(infile.is_open()); 1384 std::string buf; 1385 bool nmdResult = false; 1386 while (getline(infile, buf)) { 1387 if (buf.find("End jemalloc ohos statistics") != std::string::npos) { 1388 nmdResult = true; 1389 } 1390 } 1391 EXPECT_TRUE(nmdResult); 1392 sleep(SLEEP_TIME); 1393 } 1394 } 1395 #endif 1396 } 1397 1398 #pragma clang optimize on