xref: /developtools/hiperf/src/register.cpp (revision 48f512ce)
148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci
1648f512ceSopenharmony_ci// for libunwind.h empty struct has size 0 in c, size 1 in c++
1748f512ceSopenharmony_ci#include "register.h"
1848f512ceSopenharmony_ci#if !is_mingw
1948f512ceSopenharmony_ci#include <sys/utsname.h>
2048f512ceSopenharmony_ci#endif
2148f512ceSopenharmony_ci#if HAVE_LIBUNWIND
2248f512ceSopenharmony_ci#include <libunwind.h>
2348f512ceSopenharmony_ci#endif
2448f512ceSopenharmony_ci#include "debug_logger.h"
2548f512ceSopenharmony_ci
2648f512ceSopenharmony_ci
2748f512ceSopenharmony_cinamespace OHOS {
2848f512ceSopenharmony_cinamespace Developtools {
2948f512ceSopenharmony_cinamespace HiPerf {
3048f512ceSopenharmony_cistatic ArchType g_deviceArchType = ArchType::ARCH_UNKNOWN;
3148f512ceSopenharmony_ci// order is IP , SP for ut
3248f512ceSopenharmony_cistatic const std::map<size_t, const std::string> PERF_REG_NAME_MAP = {
3348f512ceSopenharmony_ci#if defined(target_cpu_x86_64)
3448f512ceSopenharmony_ci    {PERF_REG_X86_IP, "PERF_REG_X86_IP"},
3548f512ceSopenharmony_ci    {PERF_REG_X86_SP, "PERF_REG_X86_SP"},
3648f512ceSopenharmony_ci#elif defined(target_cpu_arm)
3748f512ceSopenharmony_ci    {PERF_REG_ARM_PC, "PERF_REG_ARM_PC"},
3848f512ceSopenharmony_ci    {PERF_REG_ARM_SP, "PERF_REG_ARM_SP"},
3948f512ceSopenharmony_ci#elif defined(target_cpu_arm64)
4048f512ceSopenharmony_ci    {PERF_REG_ARM64_PC, "PERF_REG_ARM64_PC"},
4148f512ceSopenharmony_ci    {PERF_REG_ARM64_SP, "PERF_REG_ARM64_SP"},
4248f512ceSopenharmony_ci#endif
4348f512ceSopenharmony_ci};
4448f512ceSopenharmony_ci
4548f512ceSopenharmony_ci// these copy from kerne uapi perf_regs.h
4648f512ceSopenharmony_ciuint64_t GetSupportedRegMask(ArchType arch)
4748f512ceSopenharmony_ci{
4848f512ceSopenharmony_ci    uint64_t result = 0;
4948f512ceSopenharmony_ci    switch (arch) {
5048f512ceSopenharmony_ci        case ArchType::ARCH_X86:
5148f512ceSopenharmony_ci            result = ((1ULL << PERF_REG_X86_32_MAX) - 1);
5248f512ceSopenharmony_ci            break;
5348f512ceSopenharmony_ci        case ArchType::ARCH_X86_64:
5448f512ceSopenharmony_ci            result = ((1ULL << PERF_REG_X86_64_MAX) - 1);
5548f512ceSopenharmony_ci            result &= ~((1ULL << PERF_REG_X86_DS) | (1ULL << PERF_REG_X86_ES) |
5648f512ceSopenharmony_ci                        (1ULL << PERF_REG_X86_FS) | (1ULL << PERF_REG_X86_GS));
5748f512ceSopenharmony_ci            break;
5848f512ceSopenharmony_ci        case ArchType::ARCH_ARM:
5948f512ceSopenharmony_ci            result = ((1ULL << PERF_REG_ARM_MAX) - 1);
6048f512ceSopenharmony_ci            break;
6148f512ceSopenharmony_ci        case ArchType::ARCH_ARM64:
6248f512ceSopenharmony_ci            result = ((1ULL << PERF_REG_ARM64_MAX) - 1);
6348f512ceSopenharmony_ci            break;
6448f512ceSopenharmony_ci        default:
6548f512ceSopenharmony_ci            result = std::numeric_limits<uint64_t>::max();
6648f512ceSopenharmony_ci            HLOGE("unsupport arch %d", arch);
6748f512ceSopenharmony_ci            break;
6848f512ceSopenharmony_ci    }
6948f512ceSopenharmony_ci    return result;
7048f512ceSopenharmony_ci}
7148f512ceSopenharmony_ci
7248f512ceSopenharmony_ci#if HAVE_LIBUNWIND
7348f512ceSopenharmony_ciconst std::map<int, int> LibUnwindRegMap = {
7448f512ceSopenharmony_ci#if defined(target_cpu_x86_64)
7548f512ceSopenharmony_ci    {UNW_X86_64_RAX, PERF_REG_X86_AX},  {UNW_X86_64_RDX, PERF_REG_X86_DX},
7648f512ceSopenharmony_ci    {UNW_X86_64_RCX, PERF_REG_X86_CX},  {UNW_X86_64_RBX, PERF_REG_X86_BX},
7748f512ceSopenharmony_ci    {UNW_X86_64_RSI, PERF_REG_X86_SI},  {UNW_X86_64_RDI, PERF_REG_X86_DI},
7848f512ceSopenharmony_ci    {UNW_X86_64_RBP, PERF_REG_X86_BP},  {UNW_X86_64_RSP, PERF_REG_X86_SP},
7948f512ceSopenharmony_ci    {UNW_X86_64_R8, PERF_REG_X86_R8},   {UNW_X86_64_R9, PERF_REG_X86_R9},
8048f512ceSopenharmony_ci    {UNW_X86_64_R10, PERF_REG_X86_R10}, {UNW_X86_64_R11, PERF_REG_X86_R11},
8148f512ceSopenharmony_ci    {UNW_X86_64_R12, PERF_REG_X86_R12}, {UNW_X86_64_R13, PERF_REG_X86_R13},
8248f512ceSopenharmony_ci    {UNW_X86_64_R14, PERF_REG_X86_R14}, {UNW_X86_64_R15, PERF_REG_X86_R15},
8348f512ceSopenharmony_ci    {UNW_X86_64_RIP, PERF_REG_X86_IP},
8448f512ceSopenharmony_ci#elif defined(target_cpu_arm64)
8548f512ceSopenharmony_ci    {UNW_AARCH64_X0, PERF_REG_ARM64_X0},   {UNW_AARCH64_X1, PERF_REG_ARM64_X1},
8648f512ceSopenharmony_ci    {UNW_AARCH64_X2, PERF_REG_ARM64_X2},   {UNW_AARCH64_X3, PERF_REG_ARM64_X3},
8748f512ceSopenharmony_ci    {UNW_AARCH64_X4, PERF_REG_ARM64_X4},   {UNW_AARCH64_X5, PERF_REG_ARM64_X5},
8848f512ceSopenharmony_ci    {UNW_AARCH64_X6, PERF_REG_ARM64_X6},   {UNW_AARCH64_X7, PERF_REG_ARM64_X7},
8948f512ceSopenharmony_ci    {UNW_AARCH64_X8, PERF_REG_ARM64_X8},   {UNW_AARCH64_X9, PERF_REG_ARM64_X9},
9048f512ceSopenharmony_ci    {UNW_AARCH64_X10, PERF_REG_ARM64_X10}, {UNW_AARCH64_X11, PERF_REG_ARM64_X11},
9148f512ceSopenharmony_ci    {UNW_AARCH64_X12, PERF_REG_ARM64_X12}, {UNW_AARCH64_X13, PERF_REG_ARM64_X13},
9248f512ceSopenharmony_ci    {UNW_AARCH64_X14, PERF_REG_ARM64_X14}, {UNW_AARCH64_X15, PERF_REG_ARM64_X15},
9348f512ceSopenharmony_ci    {UNW_AARCH64_X16, PERF_REG_ARM64_X16}, {UNW_AARCH64_X17, PERF_REG_ARM64_X17},
9448f512ceSopenharmony_ci    {UNW_AARCH64_X18, PERF_REG_ARM64_X18}, {UNW_AARCH64_X19, PERF_REG_ARM64_X19},
9548f512ceSopenharmony_ci    {UNW_AARCH64_X20, PERF_REG_ARM64_X20}, {UNW_AARCH64_X21, PERF_REG_ARM64_X21},
9648f512ceSopenharmony_ci    {UNW_AARCH64_X22, PERF_REG_ARM64_X22}, {UNW_AARCH64_X23, PERF_REG_ARM64_X23},
9748f512ceSopenharmony_ci    {UNW_AARCH64_X24, PERF_REG_ARM64_X24}, {UNW_AARCH64_X25, PERF_REG_ARM64_X25},
9848f512ceSopenharmony_ci    {UNW_AARCH64_X26, PERF_REG_ARM64_X26}, {UNW_AARCH64_X27, PERF_REG_ARM64_X27},
9948f512ceSopenharmony_ci    {UNW_AARCH64_X28, PERF_REG_ARM64_X28}, {UNW_AARCH64_X29, PERF_REG_ARM64_X29},
10048f512ceSopenharmony_ci    {UNW_AARCH64_X30, PERF_REG_ARM64_LR},  {UNW_AARCH64_SP, PERF_REG_ARM64_SP},
10148f512ceSopenharmony_ci    {UNW_AARCH64_PC, PERF_REG_ARM64_PC},
10248f512ceSopenharmony_ci#elif defined(target_cpu_arm)
10348f512ceSopenharmony_ci    {UNW_ARM_R0, PERF_REG_ARM_R0},  {UNW_ARM_R1, PERF_REG_ARM_R1},   {UNW_ARM_R2, PERF_REG_ARM_R2},
10448f512ceSopenharmony_ci    {UNW_ARM_R3, PERF_REG_ARM_R3},  {UNW_ARM_R4, PERF_REG_ARM_R4},   {UNW_ARM_R5, PERF_REG_ARM_R5},
10548f512ceSopenharmony_ci    {UNW_ARM_R6, PERF_REG_ARM_R6},  {UNW_ARM_R7, PERF_REG_ARM_R7},   {UNW_ARM_R8, PERF_REG_ARM_R8},
10648f512ceSopenharmony_ci    {UNW_ARM_R9, PERF_REG_ARM_R9},  {UNW_ARM_R10, PERF_REG_ARM_R10}, {UNW_ARM_R11, PERF_REG_ARM_FP},
10748f512ceSopenharmony_ci    {UNW_ARM_R12, PERF_REG_ARM_IP}, {UNW_ARM_R13, PERF_REG_ARM_SP},  {UNW_ARM_R14, PERF_REG_ARM_LR},
10848f512ceSopenharmony_ci    {UNW_ARM_R15, PERF_REG_ARM_PC},
10948f512ceSopenharmony_ci#else
11048f512ceSopenharmony_ci#error not support
11148f512ceSopenharmony_ci#endif
11248f512ceSopenharmony_ci};
11348f512ceSopenharmony_ci
11448f512ceSopenharmony_ciint LibunwindRegIdToPerfReg(int libUnwindReg)
11548f512ceSopenharmony_ci{
11648f512ceSopenharmony_ci    if (LibUnwindRegMap.count(libUnwindReg)) {
11748f512ceSopenharmony_ci        return LibUnwindRegMap.at(libUnwindReg);
11848f512ceSopenharmony_ci    } else {
11948f512ceSopenharmony_ci        HLOGE("unwind: invalid reg id %d", libUnwindReg);
12048f512ceSopenharmony_ci        return -EINVAL;
12148f512ceSopenharmony_ci    }
12248f512ceSopenharmony_ci}
12348f512ceSopenharmony_ci#endif
12448f512ceSopenharmony_ci
12548f512ceSopenharmony_ciconst std::string UpdatePerfContext(uint64_t addr, perf_callchain_context &perfCallchainContext)
12648f512ceSopenharmony_ci{
12748f512ceSopenharmony_ci    if (PERF_CONTEXT_NAME.count(addr) != 0) {
12848f512ceSopenharmony_ci        perfCallchainContext = static_cast<perf_callchain_context>(addr);
12948f512ceSopenharmony_ci        return StringPrintf("%s: %" PRIx64 "", PERF_CONTEXT_NAME.at(addr).c_str(), addr);
13048f512ceSopenharmony_ci    } else {
13148f512ceSopenharmony_ci        perfCallchainContext = PERF_CONTEXT_MAX;
13248f512ceSopenharmony_ci        return StringPrintf("unknow context: %" PRIx64 "", addr);
13348f512ceSopenharmony_ci    }
13448f512ceSopenharmony_ci}
13548f512ceSopenharmony_ci
13648f512ceSopenharmony_ciconst std::string GetArchName(ArchType arch)
13748f512ceSopenharmony_ci{
13848f512ceSopenharmony_ci    switch (arch) {
13948f512ceSopenharmony_ci        case ArchType::ARCH_X86:
14048f512ceSopenharmony_ci            return "X86_32";
14148f512ceSopenharmony_ci        case ArchType::ARCH_X86_64:
14248f512ceSopenharmony_ci            return "X86_64";
14348f512ceSopenharmony_ci        case ArchType::ARCH_ARM:
14448f512ceSopenharmony_ci            return "ARM";
14548f512ceSopenharmony_ci        case ArchType::ARCH_ARM64:
14648f512ceSopenharmony_ci            return "ARM64";
14748f512ceSopenharmony_ci        default:
14848f512ceSopenharmony_ci            return "Unsupport";
14948f512ceSopenharmony_ci    }
15048f512ceSopenharmony_ci}
15148f512ceSopenharmony_ci
15248f512ceSopenharmony_cisize_t RegisterGetIP(ArchType arch)
15348f512ceSopenharmony_ci{
15448f512ceSopenharmony_ci    switch (arch) {
15548f512ceSopenharmony_ci        case ArchType::ARCH_X86:
15648f512ceSopenharmony_ci        case ArchType::ARCH_X86_64:
15748f512ceSopenharmony_ci            return PERF_REG_X86_IP;
15848f512ceSopenharmony_ci        case ArchType::ARCH_ARM:
15948f512ceSopenharmony_ci            return PERF_REG_ARM_PC;
16048f512ceSopenharmony_ci        case ArchType::ARCH_ARM64:
16148f512ceSopenharmony_ci            return PERF_REG_ARM64_PC;
16248f512ceSopenharmony_ci        default:
16348f512ceSopenharmony_ci            return std::numeric_limits<size_t>::max();
16448f512ceSopenharmony_ci    }
16548f512ceSopenharmony_ci}
16648f512ceSopenharmony_ci
16748f512ceSopenharmony_cisize_t RegisterGetSP(ArchType arch)
16848f512ceSopenharmony_ci{
16948f512ceSopenharmony_ci    switch (arch) {
17048f512ceSopenharmony_ci        case ArchType::ARCH_X86:
17148f512ceSopenharmony_ci        case ArchType::ARCH_X86_64:
17248f512ceSopenharmony_ci            return PERF_REG_X86_SP;
17348f512ceSopenharmony_ci        case ArchType::ARCH_ARM:
17448f512ceSopenharmony_ci            return PERF_REG_ARM_SP;
17548f512ceSopenharmony_ci        case ArchType::ARCH_ARM64:
17648f512ceSopenharmony_ci            return PERF_REG_ARM64_SP;
17748f512ceSopenharmony_ci        default:
17848f512ceSopenharmony_ci            return std::numeric_limits<size_t>::max();
17948f512ceSopenharmony_ci    }
18048f512ceSopenharmony_ci}
18148f512ceSopenharmony_ci
18248f512ceSopenharmony_ciconst std::string RegisterGetName(size_t registerIndex)
18348f512ceSopenharmony_ci{
18448f512ceSopenharmony_ci    std::string name;
18548f512ceSopenharmony_ci    name.append("PerfReg[");
18648f512ceSopenharmony_ci    name.append(std::to_string(registerIndex));
18748f512ceSopenharmony_ci    if (PERF_REG_NAME_MAP.count(registerIndex) > 0) {
18848f512ceSopenharmony_ci        name.append(":");
18948f512ceSopenharmony_ci        name.append(PERF_REG_NAME_MAP.at(registerIndex));
19048f512ceSopenharmony_ci    }
19148f512ceSopenharmony_ci    name.append("]");
19248f512ceSopenharmony_ci    return name;
19348f512ceSopenharmony_ci}
19448f512ceSopenharmony_ci
19548f512ceSopenharmony_cibool RegisterGetValue(uint64_t &value, const u64 registers[], const size_t registerIndex,
19648f512ceSopenharmony_ci                      const size_t registerNumber)
19748f512ceSopenharmony_ci{
19848f512ceSopenharmony_ci    if (registerIndex >= registerNumber) {
19948f512ceSopenharmony_ci        HLOGE("registerIndex is %zu, max is %zu", registerIndex, registerNumber);
20048f512ceSopenharmony_ci        return false;
20148f512ceSopenharmony_ci    }
20248f512ceSopenharmony_ci    value = registers[registerIndex];
20348f512ceSopenharmony_ci    return true;
20448f512ceSopenharmony_ci}
20548f512ceSopenharmony_ci
20648f512ceSopenharmony_ciArchType GetArchTypeFromUname(const std::string &machine)
20748f512ceSopenharmony_ci{
20848f512ceSopenharmony_ci    if (StringStartsWith(machine, "arm")) {
20948f512ceSopenharmony_ci        if (machine == "armv8l") {
21048f512ceSopenharmony_ci            // 32 bit elf run in 64 bit cpu
21148f512ceSopenharmony_ci            return ArchType::ARCH_ARM64;
21248f512ceSopenharmony_ci        }
21348f512ceSopenharmony_ci        return ArchType::ARCH_ARM;
21448f512ceSopenharmony_ci    } else if (machine == "aarch64") {
21548f512ceSopenharmony_ci        return ArchType::ARCH_ARM64;
21648f512ceSopenharmony_ci    } else if (machine == "x86_64") {
21748f512ceSopenharmony_ci        return ArchType::ARCH_X86_64;
21848f512ceSopenharmony_ci    } else if (machine == "x86" || machine == "i686") {
21948f512ceSopenharmony_ci        return ArchType::ARCH_X86;
22048f512ceSopenharmony_ci    } else {
22148f512ceSopenharmony_ci        HLOGE("unsupport machine %s", machine.c_str());
22248f512ceSopenharmony_ci        return ArchType::ARCH_UNKNOWN;
22348f512ceSopenharmony_ci    }
22448f512ceSopenharmony_ci}
22548f512ceSopenharmony_ci
22648f512ceSopenharmony_ciArchType GetArchTypeFromABI(bool abi32)
22748f512ceSopenharmony_ci{
22848f512ceSopenharmony_ci    if (g_deviceArchType == ArchType::ARCH_UNKNOWN) {
22948f512ceSopenharmony_ci        g_deviceArchType = GetDeviceArch();
23048f512ceSopenharmony_ci    }
23148f512ceSopenharmony_ci    if (abi32) {
23248f512ceSopenharmony_ci        if (g_deviceArchType == ArchType::ARCH_ARM64) {
23348f512ceSopenharmony_ci            return ArchType::ARCH_ARM;
23448f512ceSopenharmony_ci        } else if (g_deviceArchType == ArchType::ARCH_X86_64) {
23548f512ceSopenharmony_ci            return ArchType::ARCH_X86;
23648f512ceSopenharmony_ci        }
23748f512ceSopenharmony_ci    }
23848f512ceSopenharmony_ci    return g_deviceArchType;
23948f512ceSopenharmony_ci}
24048f512ceSopenharmony_ci
24148f512ceSopenharmony_ciArchType SetDeviceArch(ArchType arch)
24248f512ceSopenharmony_ci{
24348f512ceSopenharmony_ci    HLOGD("g_deviceArchType change to  %s", GetArchName(arch).c_str());
24448f512ceSopenharmony_ci    g_deviceArchType = arch;
24548f512ceSopenharmony_ci    return g_deviceArchType;
24648f512ceSopenharmony_ci}
24748f512ceSopenharmony_ci
24848f512ceSopenharmony_ciArchType GetDeviceArch()
24948f512ceSopenharmony_ci{
25048f512ceSopenharmony_ci#if defined(is_mingw) && is_mingw
25148f512ceSopenharmony_ci    return g_deviceArchType;
25248f512ceSopenharmony_ci#else
25348f512ceSopenharmony_ci    if (g_deviceArchType != ArchType::ARCH_UNKNOWN) {
25448f512ceSopenharmony_ci        return g_deviceArchType;
25548f512ceSopenharmony_ci    } else {
25648f512ceSopenharmony_ci        utsname systemName;
25748f512ceSopenharmony_ci        if ((uname(&systemName)) != 0) {
25848f512ceSopenharmony_ci            // fallback
25948f512ceSopenharmony_ci            g_deviceArchType = BUILD_ARCH_TYPE;
26048f512ceSopenharmony_ci        } else {
26148f512ceSopenharmony_ci            g_deviceArchType = GetArchTypeFromUname(systemName.machine);
26248f512ceSopenharmony_ci            HLOGD("machine arch is %s : %s", systemName.machine,
26348f512ceSopenharmony_ci                  GetArchName(g_deviceArchType).c_str());
26448f512ceSopenharmony_ci            if (g_deviceArchType == ArchType::ARCH_UNKNOWN) {
26548f512ceSopenharmony_ci                g_deviceArchType = BUILD_ARCH_TYPE;
26648f512ceSopenharmony_ci            }
26748f512ceSopenharmony_ci        }
26848f512ceSopenharmony_ci    }
26948f512ceSopenharmony_ci    return g_deviceArchType;
27048f512ceSopenharmony_ci#endif
27148f512ceSopenharmony_ci}
27248f512ceSopenharmony_ci
27348f512ceSopenharmony_civoid UpdateRegForABI(ArchType arch, u64 *regs)
27448f512ceSopenharmony_ci{
27548f512ceSopenharmony_ci    if (g_deviceArchType == ArchType::ARCH_ARM64 and arch == ArchType::ARCH_ARM) {
27648f512ceSopenharmony_ci        // arm in arm64
27748f512ceSopenharmony_ci        regs[PERF_REG_ARM_PC] = regs[PERF_REG_ARM64_PC];
27848f512ceSopenharmony_ci    }
27948f512ceSopenharmony_ci}
28048f512ceSopenharmony_ci} // namespace HiPerf
28148f512ceSopenharmony_ci} // namespace Developtools
28248f512ceSopenharmony_ci} // namespace OHOS
283