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 #ifndef HIPERF_CALLSTACK_TEST_H
16 #define HIPERF_CALLSTACK_TEST_H
17
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 #include <iterator>
21 #include <link.h>
22 #include <random>
23 #include <sys/mman.h>
24
25 #include <hilog/log.h>
26
27 #include "call_stack.h"
28 #include "debug_logger.h"
29 #include "utilities.h"
30
31 namespace OHOS {
32 namespace Developtools {
33 namespace NativeDaemon {
34 static const std::string PATH_RESOURCE_TEST_DWARF_DATA = "resource/testdata/dwarf/";
35 /*
36 create from
37 ./hiperf_example_cmd --thread 1 --time 60 --stack 10
38 ./hiperf_host dump --userdata > dump.txt
39 */
40 static const std::string TEST_DWARF_ELF = "hiperf_example_cmd";
41 static const std::string TEST_DWARF_USER_REGS_0 = "user_regs.dump";
42 static const std::string TEST_DWARF_USER_DATA_0 = "user_data.dump";
43
44 static const int PERF_REG_ARM_SP_IDX = 13;
45 static const int PERF_REG_ARM_PC_IDX = 15;
46
47 struct mmapDumpInfo {
48 std::string fileName;
49 uint64_t begin = 0;
50 uint64_t len = 0;
51 uint64_t pgoff = 0;
52 };
53 /*
54 record mmap2: type 10, misc 2, size 107
55 pid 643, tid 643, addr 0x454000, len 0x3000
56 pgoff 0x0, maj 179, min 7, ino 4868, ino_generation 6874019636378171493
57 prot 1, flags 2, filename /data/local/tmp/hiperf_example_cmd
58
59 record mmap2: type 10, misc 2, size 107
60 pid 643, tid 643, addr 0x457000, len 0x5000
61 pgoff 0x2000, maj 179, min 7, ino 4868, ino_generation 7237954708011182952
62 prot 5, flags 2, filename /data/local/tmp/hiperf_example_cmd
63
64 record mmap2: type 10, misc 2, size 107
65 pid 643, tid 643, addr 0x45c000, len 0x1000
66 pgoff 0x6000, maj 179, min 7, ino 4868, ino_generation 7237954708011182952
67 prot 1, flags 2, filename /data/local/tmp/hiperf_example_cmd
68
69 record mmap2: type 10, misc 2, size 107
70 pid 643, tid 643, addr 0x45d000, len 0x1000
71 pgoff 0x6000, maj 179, min 7, ino 4868, ino_generation 7237954708011182952
72 prot 3, flags 2, filename /data/local/tmp/hiperf_example_cmd
73 */
74 static const std::vector<mmapDumpInfo> TEST_DWARF_MMAP = {
75 {"/data/local/tmp/hiperf_example_cmd", 0x454000, 0x3000, 0x0},
76 {"/data/local/tmp/hiperf_example_cmd", 0x457000, 0x5000, 0x2000},
77 {"/data/local/tmp/hiperf_example_cmd", 0x45c000, 0x1000, 0x6000},
78 {"/data/local/tmp/hiperf_example_cmd", 0x45d000, 0x1000, 0x6000},
79
80 };
81
82 /*
83 UnwindStep:unwind:0: ip 0x45765e sp 0xb6ca1c68
84 UnwindStep:unwind:1: ip 0x45768a sp 0xb6ca1c78
85 UnwindStep:unwind:2: ip 0x4576ce sp 0xb6ca1c88
86 UnwindStep:unwind:3: ip 0x457712 sp 0xb6ca1c98
87 UnwindStep:unwind:4: ip 0x457756 sp 0xb6ca1ca8
88 UnwindStep:unwind:5: ip 0x45779a sp 0xb6ca1cb8
89 UnwindStep:unwind:6: ip 0x4577de sp 0xb6ca1cc8
90 UnwindStep:unwind:7: ip 0x457822 sp 0xb6ca1cd8
91 UnwindStep:unwind:8: ip 0x457866 sp 0xb6ca1ce8
92 UnwindStep:unwind:9: ip 0x4578aa sp 0xb6ca1cf8
93 UnwindStep:unwind:10: ip 0x4578ee sp 0xb6ca1d08
94 UnwindStep:unwind:11: ip 0x45793c sp 0xb6ca1d18
95 UnwindStep:unwind:12: ip 0x457ffe sp 0xb6ca1d28
96 UnwindStep:unwind:13: ip 0xb6f01f73 sp 0xb6ca1d38
97 */
98 struct frame {
99 uint64_t ip = 0;
100 uint64_t sp = 0;
101 };
102 static const std::vector<frame> TEST_DWARF_FRAMES = {
103 {0x4575BC, 0xB6CA1C18}, // base ip sp
104 {0x45765e, 0xb6ca1c68}, {0x45768a, 0xb6ca1c78}, {0x4576ce, 0xb6ca1c88},
105 {0x457712, 0xb6ca1c98}, {0x457756, 0xb6ca1ca8}, {0x45779a, 0xb6ca1cb8},
106 {0x4577de, 0xb6ca1cc8}, {0x457822, 0xb6ca1cd8}, {0x457866, 0xb6ca1ce8},
107 {0x4578aa, 0xb6ca1cf8}, {0x4578ee, 0xb6ca1d08}, {0x45793c, 0xb6ca1d18},
108 {0x457ffe, 0xb6ca1d28}, {0xb6f01f73, 0xb6ca1d38},
109 };
110
111 // data convert funcion
112 template<class T>
LoadFromFile(const std::string & fileName,std::vector<T> & data)113 void LoadFromFile(const std::string &fileName, std::vector<T> &data)
114 {
115 FILE *fp_cin = fopen(fileName.c_str(), "r");
116 if (fp_cin == nullptr) {
117 HLOGE("fopen fail!");
118 return;
119 }
120 std::unique_ptr<FILE, decltype(&fclose)> fp(fp_cin, fclose);
121 if (fp == nullptr) {
122 HLOGE("make file unique ptr fail!");
123 return;
124 }
125 struct stat sb = {};
126 ASSERT_NE(fstat(fileno(fp.get()), &sb), -1);
127 ASSERT_NE(sb.st_size, 0);
128 ASSERT_EQ(sb.st_size % sizeof(T), 0u);
129 data.resize(sb.st_size / sizeof(T));
130 size_t ret;
131 if ((ret = fread(data.data(), sizeof(T), data.size(), fp.get())) < 0) {
132 const int errBufSize = 256;
133 char errBuf[errBufSize] = { 0 };
134 strerror_r(errno, errBuf, errBufSize);
135 HLOGE("fread fail! errno(%d:%s)", errno, errBuf);
136 return;
137 }
138 ASSERT_EQ(ret, data.size());
139 }
140
MakeMaps(VirtualThread & thread)141 static void MakeMaps(VirtualThread &thread)
142 {
143 for (const mmapDumpInfo &mmap : TEST_DWARF_MMAP) {
144 thread.CreateMapItem(mmap.fileName, mmap.begin, mmap.len, mmap.pgoff);
145 }
146 }
147 } // namespace NativeDaemon
148 } // namespace Developtools
149 } // namespace OHOS
150 #endif
151