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