OSDN Git Service

simpleperf: check perf event limit.
[android-x86/system-extras.git] / simpleperf / perf_regs.cpp
index 6a63876..29d144e 100644 (file)
 #include "perf_regs.h"
 
 #include <unordered_map>
-#include <base/logging.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
-constexpr ArchType GetBuildArch() {
-#if defined(__i386__)
-  return ARCH_X86_32;
-#elif defined(__x86_64__)
-  return ARCH_X86_64;
-#elif defined(__aarch64__)
-  return ARCH_ARM64;
-#elif defined(__arm__)
-  return ARCH_ARM;
-#else
-  return ARCH_UNSUPPORTED;
-#endif
-}
-
-static ArchType current_arch = GetBuildArch();
+ArchType ScopedCurrentArch::current_arch = GetBuildArch();
 
-ArchType GetCurrentArch() {
-  return current_arch;
-}
-
-bool SetCurrentArch(const std::string& arch) {
-  if (arch == "x86") {
-    current_arch = ARCH_X86_32;
+ArchType GetArchType(const std::string& arch) {
+  if (arch == "x86" || arch == "i686") {
+    return ARCH_X86_32;
   } else if (arch == "x86_64") {
-    current_arch = ARCH_X86_64;
+    return ARCH_X86_64;
   } else if (arch == "aarch64") {
-    current_arch = ARCH_ARM64;
+    return ARCH_ARM64;
   } else if (android::base::StartsWith(arch, "arm")) {
-    current_arch = ARCH_ARM;
-  } else {
-    LOG(ERROR) << "unsupported arch: " << arch;
-    return false;
+    return ARCH_ARM;
   }
-  return true;
+  LOG(ERROR) << "unsupported arch: " << arch;
+  return ARCH_UNSUPPORTED;
 }
 
-uint64_t GetSupportedRegMask() {
-  switch (GetCurrentArch()) {
+uint64_t GetSupportedRegMask(ArchType arch) {
+  switch (arch) {
     case ARCH_X86_32:
       return ((1ULL << PERF_REG_X86_32_MAX) - 1);
     case ARCH_X86_64:
@@ -92,11 +72,13 @@ static std::unordered_map<size_t, std::string> arm64_reg_map = {
     {PERF_REG_ARM64_LR, "lr"}, {PERF_REG_ARM64_SP, "sp"}, {PERF_REG_ARM64_PC, "pc"},
 };
 
-std::string GetRegName(size_t reg) {
-  switch (GetCurrentArch()) {
+std::string GetRegName(size_t regno, ArchType arch) {
+  // Cast regno to int type to avoid -Werror=type-limits.
+  int reg = static_cast<int>(regno);
+  switch (arch) {
     case ARCH_X86_64: {
       if (reg >= PERF_REG_X86_R8 && reg <= PERF_REG_X86_R15) {
-        return android::base::StringPrintf("r%zu", reg - PERF_REG_X86_R8 + 8);
+        return android::base::StringPrintf("r%d", reg - PERF_REG_X86_R8 + 8);
       }
     }  // go through
     case ARCH_X86_32: {
@@ -106,7 +88,7 @@ std::string GetRegName(size_t reg) {
     }
     case ARCH_ARM: {
       if (reg >= PERF_REG_ARM_R0 && reg <= PERF_REG_ARM_R10) {
-        return android::base::StringPrintf("r%zu", reg - PERF_REG_ARM_R0);
+        return android::base::StringPrintf("r%d", reg - PERF_REG_ARM_R0);
       }
       auto it = arm_reg_map.find(reg);
       CHECK(it != arm_reg_map.end()) << "unknown reg " << reg;
@@ -114,13 +96,54 @@ std::string GetRegName(size_t reg) {
     }
     case ARCH_ARM64: {
       if (reg >= PERF_REG_ARM64_X0 && reg <= PERF_REG_ARM64_X29) {
-        return android::base::StringPrintf("r%zu", reg - PERF_REG_ARM64_X0);
+        return android::base::StringPrintf("r%d", reg - PERF_REG_ARM64_X0);
       }
       auto it = arm64_reg_map.find(reg);
       CHECK(it != arm64_reg_map.end()) << "unknown reg " << reg;
       return it->second;
     }
-    case ARCH_UNSUPPORTED:
+    default:
       return "unknown";
   }
 }
+
+RegSet CreateRegSet(uint64_t valid_mask, const std::vector<uint64_t>& valid_regs) {
+  RegSet regs;
+  regs.valid_mask = valid_mask;
+  for (int i = 0, j = 0; i < 64; ++i) {
+    if ((valid_mask >> i) & 1) {
+      regs.data[i] = valid_regs[j++];
+    }
+  }
+  return regs;
+}
+
+bool GetRegValue(const RegSet& regs, size_t regno, uint64_t* value) {
+  CHECK_LT(regno, 64U);
+  if ((regs.valid_mask >> regno) & 1) {
+    *value = regs.data[regno];
+    return true;
+  }
+  return false;
+}
+
+bool GetSpRegValue(const RegSet& regs, ArchType arch, uint64_t* value) {
+  size_t regno;
+  switch (arch) {
+    case ARCH_X86_32:
+      regno = PERF_REG_X86_SP;
+      break;
+    case ARCH_X86_64:
+      regno = PERF_REG_X86_SP;
+      break;
+    case ARCH_ARM:
+      regno = PERF_REG_ARM_SP;
+      break;
+    case ARCH_ARM64:
+      regno = PERF_REG_ARM64_SP;
+      break;
+    default:
+      return false;
+  }
+  return GetRegValue(regs, regno, value);
+}