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