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