diff options
author | Yabin Cui <yabinc@google.com> | 2015-07-13 12:23:54 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2015-07-13 15:52:53 -0700 |
commit | 76769e502d8f0ebf5d2c81b00246727fb0a59925 (patch) | |
tree | bff1eec2973b5258dcf4532770725c38389c4d0f /simpleperf/perf_regs.cpp | |
parent | 60bbb93d988a5f797b316341b9447ca9ef011603 (diff) | |
download | extras-76769e502d8f0ebf5d2c81b00246727fb0a59925.tar.gz |
Simpleperf: Support dwarf callgraph recording.
1. add OS_RELEASE and ARCH feature in perf.data. ARCH feature is used when parsing
recorded user registers.
2. support `--call-graph dwarf` option in record command.
Bug: 22229391
Change-Id: I56dbdd101338658ce6a9b59aa8be90e712e007f5
Diffstat (limited to 'simpleperf/perf_regs.cpp')
-rw-r--r-- | simpleperf/perf_regs.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/simpleperf/perf_regs.cpp b/simpleperf/perf_regs.cpp new file mode 100644 index 00000000..8480576b --- /dev/null +++ b/simpleperf/perf_regs.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perf_regs.h" + +#include <unordered_map> +#include <base/logging.h> +#include <base/stringprintf.h> +#include <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_INVALID; +#endif +} + +static ArchType current_arch = GetBuildArch(); + +ArchType GetCurrentArch() { + return current_arch; +} + +bool SetCurrentArch(const std::string& arch) { + if (arch == "x86") { + current_arch = ARCH_X86_32; + } else if (arch == "x86_64") { + current_arch = ARCH_X86_64; + } else if (arch == "aarch64") { + current_arch = ARCH_ARM64; + } else if (android::base::StartsWith(arch, "arm")) { + current_arch = ARCH_ARM; + } else { + LOG(ERROR) << "unknown arch: " << arch; + return false; + } + return true; +} + +uint64_t GetSupportedRegMask() { + switch (GetCurrentArch()) { + case ARCH_X86_32: + return ((1ULL << PERF_REG_X86_32_MAX) - 1); + case ARCH_X86_64: + return (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) & + ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) & ~(1ULL << PERF_REG_X86_GS)); + case ARCH_ARM: + return ((1ULL << PERF_REG_ARM_MAX) - 1); + case ARCH_ARM64: + return ((1ULL << PERF_REG_ARM64_MAX) - 1); + } + return 0; +} + +static std::unordered_map<size_t, std::string> x86_reg_map = { + {PERF_REG_X86_AX, "ax"}, {PERF_REG_X86_BX, "bx"}, {PERF_REG_X86_CX, "cx"}, + {PERF_REG_X86_DX, "dx"}, {PERF_REG_X86_SI, "si"}, {PERF_REG_X86_DI, "di"}, + {PERF_REG_X86_BP, "bp"}, {PERF_REG_X86_SP, "sp"}, {PERF_REG_X86_IP, "ip"}, + {PERF_REG_X86_FLAGS, "flags"}, {PERF_REG_X86_CS, "cs"}, {PERF_REG_X86_SS, "ss"}, + {PERF_REG_X86_DS, "ds"}, {PERF_REG_X86_ES, "es"}, {PERF_REG_X86_FS, "fs"}, + {PERF_REG_X86_GS, "gs"}, +}; + +static std::unordered_map<size_t, std::string> arm_reg_map = { + {PERF_REG_ARM_FP, "fp"}, {PERF_REG_ARM_IP, "ip"}, {PERF_REG_ARM_SP, "sp"}, + {PERF_REG_ARM_LR, "lr"}, {PERF_REG_ARM_PC, "pc"}, +}; + +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()) { + 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); + } + } // go through + case ARCH_X86_32: { + auto it = x86_reg_map.find(reg); + CHECK(it != x86_reg_map.end()) << "unknown reg " << reg; + return it->second; + } + 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); + } + auto it = arm_reg_map.find(reg); + CHECK(it != arm_reg_map.end()) << "unknown reg " << reg; + return it->second; + } + 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); + } + auto it = arm64_reg_map.find(reg); + CHECK(it != arm64_reg_map.end()) << "unknown reg " << reg; + return it->second; + } + } + return std::string(); +} |