Home | History | Annotate | Download | only in simpleperf
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "perf_regs.h"
     18 
     19 #include <unordered_map>
     20 #include <android-base/logging.h>
     21 #include <android-base/stringprintf.h>
     22 #include <android-base/strings.h>
     23 
     24 ArchType ScopedCurrentArch::current_arch = GetBuildArch();
     25 
     26 ArchType GetArchType(const std::string& arch) {
     27   if (arch == "x86" || arch == "i686") {
     28     return ARCH_X86_32;
     29   } else if (arch == "x86_64") {
     30     return ARCH_X86_64;
     31   } else if (arch == "aarch64") {
     32     return ARCH_ARM64;
     33   } else if (android::base::StartsWith(arch, "arm")) {
     34     return ARCH_ARM;
     35   }
     36   LOG(ERROR) << "unsupported arch: " << arch;
     37   return ARCH_UNSUPPORTED;
     38 }
     39 
     40 uint64_t GetSupportedRegMask(ArchType arch) {
     41   switch (arch) {
     42     case ARCH_X86_32:
     43       return ((1ULL << PERF_REG_X86_32_MAX) - 1);
     44     case ARCH_X86_64:
     45       return (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) &
     46               ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) & ~(1ULL << PERF_REG_X86_GS));
     47     case ARCH_ARM:
     48       return ((1ULL << PERF_REG_ARM_MAX) - 1);
     49     case ARCH_ARM64:
     50       return ((1ULL << PERF_REG_ARM64_MAX) - 1);
     51     default:
     52       return 0;
     53   }
     54   return 0;
     55 }
     56 
     57 static std::unordered_map<size_t, std::string> x86_reg_map = {
     58     {PERF_REG_X86_AX, "ax"},       {PERF_REG_X86_BX, "bx"}, {PERF_REG_X86_CX, "cx"},
     59     {PERF_REG_X86_DX, "dx"},       {PERF_REG_X86_SI, "si"}, {PERF_REG_X86_DI, "di"},
     60     {PERF_REG_X86_BP, "bp"},       {PERF_REG_X86_SP, "sp"}, {PERF_REG_X86_IP, "ip"},
     61     {PERF_REG_X86_FLAGS, "flags"}, {PERF_REG_X86_CS, "cs"}, {PERF_REG_X86_SS, "ss"},
     62     {PERF_REG_X86_DS, "ds"},       {PERF_REG_X86_ES, "es"}, {PERF_REG_X86_FS, "fs"},
     63     {PERF_REG_X86_GS, "gs"},
     64 };
     65 
     66 static std::unordered_map<size_t, std::string> arm_reg_map = {
     67     {PERF_REG_ARM_FP, "fp"}, {PERF_REG_ARM_IP, "ip"}, {PERF_REG_ARM_SP, "sp"},
     68     {PERF_REG_ARM_LR, "lr"}, {PERF_REG_ARM_PC, "pc"},
     69 };
     70 
     71 static std::unordered_map<size_t, std::string> arm64_reg_map = {
     72     {PERF_REG_ARM64_LR, "lr"}, {PERF_REG_ARM64_SP, "sp"}, {PERF_REG_ARM64_PC, "pc"},
     73 };
     74 
     75 std::string GetRegName(size_t regno, ArchType arch) {
     76   // Cast regno to int type to avoid -Werror=type-limits.
     77   int reg = static_cast<int>(regno);
     78   switch (arch) {
     79     case ARCH_X86_64: {
     80       if (reg >= PERF_REG_X86_R8 && reg <= PERF_REG_X86_R15) {
     81         return android::base::StringPrintf("r%d", reg - PERF_REG_X86_R8 + 8);
     82       }
     83     }  // go through
     84     case ARCH_X86_32: {
     85       auto it = x86_reg_map.find(reg);
     86       CHECK(it != x86_reg_map.end()) << "unknown reg " << reg;
     87       return it->second;
     88     }
     89     case ARCH_ARM: {
     90       if (reg >= PERF_REG_ARM_R0 && reg <= PERF_REG_ARM_R10) {
     91         return android::base::StringPrintf("r%d", reg - PERF_REG_ARM_R0);
     92       }
     93       auto it = arm_reg_map.find(reg);
     94       CHECK(it != arm_reg_map.end()) << "unknown reg " << reg;
     95       return it->second;
     96     }
     97     case ARCH_ARM64: {
     98       if (reg >= PERF_REG_ARM64_X0 && reg <= PERF_REG_ARM64_X29) {
     99         return android::base::StringPrintf("r%d", reg - PERF_REG_ARM64_X0);
    100       }
    101       auto it = arm64_reg_map.find(reg);
    102       CHECK(it != arm64_reg_map.end()) << "unknown reg " << reg;
    103       return it->second;
    104     }
    105     default:
    106       return "unknown";
    107   }
    108 }
    109 
    110 RegSet CreateRegSet(uint64_t valid_mask, const std::vector<uint64_t>& valid_regs) {
    111   RegSet regs;
    112   regs.valid_mask = valid_mask;
    113   for (int i = 0, j = 0; i < 64; ++i) {
    114     if ((valid_mask >> i) & 1) {
    115       regs.data[i] = valid_regs[j++];
    116     }
    117   }
    118   return regs;
    119 }
    120 
    121 bool GetRegValue(const RegSet& regs, size_t regno, uint64_t* value) {
    122   CHECK_LT(regno, 64U);
    123   if ((regs.valid_mask >> regno) & 1) {
    124     *value = regs.data[regno];
    125     return true;
    126   }
    127   return false;
    128 }
    129 
    130 bool GetSpRegValue(const RegSet& regs, ArchType arch, uint64_t* value) {
    131   size_t regno;
    132   switch (arch) {
    133     case ARCH_X86_32:
    134       regno = PERF_REG_X86_SP;
    135       break;
    136     case ARCH_X86_64:
    137       regno = PERF_REG_X86_SP;
    138       break;
    139     case ARCH_ARM:
    140       regno = PERF_REG_ARM_SP;
    141       break;
    142     case ARCH_ARM64:
    143       regno = PERF_REG_ARM64_SP;
    144       break;
    145     default:
    146       return false;
    147   }
    148   return GetRegValue(regs, regno, value);
    149 }
    150