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