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