• 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 #ifndef HIPERF_REGISTER_H
16 #define HIPERF_REGISTER_H
17 
18 #include <linux/perf_event.h>
19 
20 #include <cinttypes>
21 #include <string>
22 
23 #include "utilities.h"
24 
25 namespace OHOS {
26 namespace Developtools {
27 namespace NativeDaemon {
28 // these define copy from kernel uapi
29 enum perf_event_x86_regs {
30     PERF_REG_X86_AX,
31     PERF_REG_X86_BX,
32     PERF_REG_X86_CX,
33     PERF_REG_X86_DX,
34     PERF_REG_X86_SI,
35     PERF_REG_X86_DI,
36     PERF_REG_X86_BP,
37     PERF_REG_X86_SP,
38     PERF_REG_X86_IP,
39     PERF_REG_X86_FLAGS,
40     PERF_REG_X86_CS,
41     PERF_REG_X86_SS,
42     PERF_REG_X86_DS,
43     PERF_REG_X86_ES,
44     PERF_REG_X86_FS,
45     PERF_REG_X86_GS,
46     PERF_REG_X86_R8,
47     PERF_REG_X86_R9,
48     PERF_REG_X86_R10,
49     PERF_REG_X86_R11,
50     PERF_REG_X86_R12,
51     PERF_REG_X86_R13,
52     PERF_REG_X86_R14,
53     PERF_REG_X86_R15,
54     PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
55     PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
56 };
57 
58 enum perf_event_arm64_regs {
59     PERF_REG_ARM64_X0,
60     PERF_REG_ARM64_X1,
61     PERF_REG_ARM64_X2,
62     PERF_REG_ARM64_X3,
63     PERF_REG_ARM64_X4,
64     PERF_REG_ARM64_X5,
65     PERF_REG_ARM64_X6,
66     PERF_REG_ARM64_X7,
67     PERF_REG_ARM64_X8,
68     PERF_REG_ARM64_X9,
69     PERF_REG_ARM64_X10,
70     PERF_REG_ARM64_X11,
71     PERF_REG_ARM64_X12,
72     PERF_REG_ARM64_X13,
73     PERF_REG_ARM64_X14,
74     PERF_REG_ARM64_X15,
75     PERF_REG_ARM64_X16,
76     PERF_REG_ARM64_X17,
77     PERF_REG_ARM64_X18,
78     PERF_REG_ARM64_X19,
79     PERF_REG_ARM64_X20,
80     PERF_REG_ARM64_X21,
81     PERF_REG_ARM64_X22,
82     PERF_REG_ARM64_X23,
83     PERF_REG_ARM64_X24,
84     PERF_REG_ARM64_X25,
85     PERF_REG_ARM64_X26,
86     PERF_REG_ARM64_X27,
87     PERF_REG_ARM64_X28,
88     PERF_REG_ARM64_X29,
89     PERF_REG_ARM64_LR,
90     PERF_REG_ARM64_SP,
91     PERF_REG_ARM64_PC,
92     PERF_REG_ARM64_MAX,
93 };
94 
95 enum perf_event_arm_regs {
96     PERF_REG_ARM_SP,
97     PERF_REG_ARM_PC,
98     PERF_REG_ARM_MAX,
99 };
100 
101 enum ArchType {
102     X86_32,
103     X86_64,
104     ARM,
105     ARM64,
106 };
107 
108 // order is IP , SP for ut
109 static const std::map<size_t, const std::string> PERF_REG_NAME_MAP = {
110 #if defined(target_cpu_x64)
111     {PERF_REG_X86_IP, "PERF_REG_X86_IP"},
112     {PERF_REG_X86_SP, "PERF_REG_X86_SP"},
113 #elif defined(target_cpu_arm)
114     {PERF_REG_ARM_PC, "PERF_REG_ARM_PC"},
115     {PERF_REG_ARM_SP, "PERF_REG_ARM_SP"},
116 #elif defined(target_cpu_arm64)
117     {PERF_REG_ARM64_PC, "PERF_REG_ARM64_PC"},
118     {PERF_REG_ARM64_SP, "PERF_REG_ARM64_SP"},
119 #endif
120 };
121 
122 // context name
123 static const std::map<uint64_t, const std::string> PERF_CONTEXT_NAME = {
124     {PERF_CONTEXT_HV, "PERF_CONTEXT_HV"},
125     {PERF_CONTEXT_KERNEL, "PERF_CONTEXT_KERNEL"},
126     {PERF_CONTEXT_USER, "PERF_CONTEXT_USER"},
127     {PERF_CONTEXT_GUEST, "PERF_CONTEXT_GUEST"},
128     {PERF_CONTEXT_GUEST_KERNEL, "PERF_CONTEXT_GUEST_KERNEL"},
129     {PERF_CONTEXT_GUEST_USER, "PERF_CONTEXT_GUEST_USER"},
130     {PERF_CONTEXT_MAX, "PERF_CONTEXT_MAX"},
131 };
132 
133 #if defined(target_cpu_x64)
134 constexpr ArchType BuildArchType = ArchType::X86_64;
135 #elif defined(target_cpu_arm64)
136 constexpr ArchType BuildArchType = ArchType::ARM64;
137 #elif defined(target_cpu_arm)
138 constexpr ArchType BuildArchType = ArchType::ARM;
139 #else
140 #error NOT SUPPORT ARCH
141 #endif
142 
143 const std::string UpdatePerfContext(uint64_t addr, perf_callchain_context &perfCallchainContext);
144 const std::string GetArchName(ArchType arch);
145 uint64_t GetSupportedRegMask(ArchType arch);
146 
147 // this is only for debug
148 const std::string RegisterGetName(size_t registerIndex);
149 
150 bool RegisterGetValue(uint64_t &value, const u64 registers[], const size_t registerIndex,
151     const size_t registerNumber);
152 
153 size_t RegisterGetSP();
154 size_t RegisterGetIP();
155 
156 size_t RegisterGetCount();
157 
RegisterGetSPValue(uint64_t & value,const u64 registers[],const size_t registerNumber)158 inline bool RegisterGetSPValue(uint64_t &value, const u64 registers[], const size_t registerNumber)
159 {
160     return RegisterGetValue(value, registers, RegisterGetSP(), registerNumber);
161 }
162 
RegisterGetIPValue(uint64_t & value,const u64 registers[],const size_t registerNumber)163 inline bool RegisterGetIPValue(uint64_t &value, const u64 registers[], const size_t registerNumber)
164 {
165     return RegisterGetValue(value, registers, RegisterGetIP(), registerNumber);
166 }
167 
GetArchName(ArchType arch)168 inline const std::string GetArchName(ArchType arch)
169 {
170     switch (arch) {
171         case ArchType::X86_32:
172             return "X86_32";
173         case ArchType::X86_64:
174             return "X86_64";
175         case ArchType::ARM:
176             return "ARM";
177         case ArchType::ARM64:
178             return "ARM64";
179         default:
180             return "Unsupport";
181     }
182 }
183 
RegisterGetIP()184 inline size_t RegisterGetIP()
185 {
186     switch (BuildArchType) {
187         case ArchType::X86_32:
188         case ArchType::X86_64:
189             return PERF_REG_X86_IP;
190         case ArchType::ARM:
191             return PERF_REG_ARM_PC;
192         case ArchType::ARM64:
193             return PERF_REG_ARM64_PC;
194         default: {
195             HLOGM("Registers in an unknown CPU.");
196             return std::numeric_limits<size_t>::max();
197         }
198     }
199 }
200 
RegisterGetCount()201 inline size_t RegisterGetCount()
202 {
203     switch (BuildArchType) {
204         case ArchType::X86_32:
205             return PERF_REG_X86_32_MAX;
206         case ArchType::X86_64:
207             return PERF_REG_X86_64_MAX;
208         case ArchType::ARM:
209             return PERF_REG_ARM_MAX;
210         case ArchType::ARM64:
211             return PERF_REG_ARM64_MAX;
212         default: {
213             HLOGM("Registers in an unknown CPU.");
214             return std::numeric_limits<size_t>::max();
215         }
216     }
217 }
218 
RegisterGetSP()219 inline size_t RegisterGetSP()
220 {
221     switch (BuildArchType) {
222         case ArchType::X86_32:
223         case ArchType::X86_64:
224             return PERF_REG_X86_SP;
225         case ArchType::ARM:
226             return PERF_REG_ARM_SP;
227         case ArchType::ARM64:
228             return PERF_REG_ARM64_SP;
229         default: {
230             HLOGM("Registers in an unknown CPU.");
231             return std::numeric_limits<size_t>::max();
232         }
233     }
234 }
235 
RegisterGetValue(uint64_t & value,const u64 registers[],const size_t registerIndex,const size_t registerNumber)236 inline bool RegisterGetValue(uint64_t &value, const u64 registers[], const size_t registerIndex,
237     const size_t registerNumber)
238 {
239     if (registerIndex >= registerNumber) {
240         HLOGM("registerIndex is %zu, max is %zu", registerIndex, registerNumber);
241         return false;
242     }
243     value = registers[registerIndex];
244     return true;
245 }
246 
247 int LibunwindRegIdToPrefReg(int regnum);
248 } // namespace NativeDaemon
249 } // namespace Developtools
250 } // namespace OHOS
251 #endif