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