diff options
author | Yabin Cui <yabinc@google.com> | 2016-03-28 17:47:52 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-03-28 17:47:53 +0000 |
commit | 7c4bbdc60586231e9601c6b199ec68317269ddd6 (patch) | |
tree | d9a7c2c6f82e9eae9676bf980a55ede3f7ade426 | |
parent | 9fbb28cc4a05cbc9d571664cc31896899011bcde (diff) | |
parent | e435e7d8706ff234fdc69e9a9424fb2b08806658 (diff) | |
download | extras-7c4bbdc60586231e9601c6b199ec68317269ddd6.tar.gz |
Merge "Simpleperf: remove dependency on global current_arch." into nyc-dev
-rw-r--r-- | simpleperf/cmd_dumprecord.cpp | 7 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_report.cpp | 9 | ||||
-rw-r--r-- | simpleperf/dwarf_unwind.cpp | 8 | ||||
-rw-r--r-- | simpleperf/dwarf_unwind.h | 2 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 4 | ||||
-rw-r--r-- | simpleperf/nonlinux_support/nonlinux_support.cpp | 3 | ||||
-rw-r--r-- | simpleperf/perf_regs.cpp | 59 | ||||
-rw-r--r-- | simpleperf/perf_regs.h | 24 | ||||
-rw-r--r-- | simpleperf/record.cpp | 3 |
10 files changed, 72 insertions, 49 deletions
diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index 13f40d4c..f19cfd3a 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -39,7 +39,7 @@ class DumpRecordCommand : public Command { : Command("dump", "dump perf record file", "Usage: simpleperf dumprecord [options] [perf_record_file]\n" " Dump different parts of a perf record file. Default file is perf.data.\n"), - record_filename_("perf.data") { + record_filename_("perf.data"), record_file_arch_(GetBuildArch()) { } bool Run(const std::vector<std::string>& args); @@ -53,6 +53,7 @@ class DumpRecordCommand : public Command { std::string record_filename_; std::unique_ptr<RecordFileReader> record_file_reader_; + ArchType record_file_arch_; }; bool DumpRecordCommand::Run(const std::vector<std::string>& args) { @@ -65,10 +66,12 @@ bool DumpRecordCommand::Run(const std::vector<std::string>& args) { } std::string arch = record_file_reader_->ReadFeatureString(FEAT_ARCH); if (!arch.empty()) { - if (!SetCurrentArch(arch)) { + record_file_arch_ = GetArchType(arch); + if (record_file_arch_ == ARCH_UNSUPPORTED) { return false; } } + ScopedCurrentArch scoped_arch(record_file_arch_); DumpFileHeader(); DumpAttrSection(); DumpDataSection(); diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index e6efff59..910bc3e9 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -688,7 +688,7 @@ void RecordCommand::UnwindRecord(Record* record) { ThreadEntry* thread = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid); RegSet regs = CreateRegSet(r.regs_user_data.reg_mask, r.regs_user_data.regs); std::vector<char>& stack = r.stack_user_data.data; - std::vector<uint64_t> unwind_ips = UnwindCallChain(*thread, regs, stack); + std::vector<uint64_t> unwind_ips = UnwindCallChain(GetBuildArch(), *thread, regs, stack); r.callchain_data.ips.push_back(PERF_CONTEXT_USER); r.callchain_data.ips.insert(r.callchain_data.ips.end(), unwind_ips.begin(), unwind_ips.end()); r.regs_user_data.abi = 0; diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index b9821605..3d778abb 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -270,6 +270,7 @@ class ReportCommand : public Command { " --vmlinux <file>\n" " Parse kernel symbols from <file>.\n"), record_filename_("perf.data"), + record_file_arch_(GetBuildArch()), use_branch_address_(false), accumulate_callchain_(false), print_callgraph_(false), @@ -302,6 +303,7 @@ class ReportCommand : public Command { uint64_t parent_period, bool last); std::string record_filename_; + ArchType record_file_arch_; std::unique_ptr<RecordFileReader> record_file_reader_; perf_event_attr event_attr_; std::vector<std::unique_ptr<Displayable>> displayable_items_; @@ -336,6 +338,7 @@ bool ReportCommand::Run(const std::vector<std::string>& args) { if (!ReadFeaturesFromRecordFile()) { return false; } + ScopedCurrentArch scoped_arch(record_file_arch_); ReadSampleTreeFromRecordFile(); // 3. Show collected information. @@ -565,7 +568,8 @@ void ReportCommand::ProcessSampleRecord(const SampleRecord& r) { RegSet regs = CreateRegSet(r.regs_user_data.reg_mask, r.regs_user_data.regs); std::vector<char> stack(r.stack_user_data.data.begin(), r.stack_user_data.data.begin() + r.stack_user_data.data.size()); - std::vector<uint64_t> unwind_ips = UnwindCallChain(*sample->thread, regs, stack); + std::vector<uint64_t> unwind_ips = + UnwindCallChain(ScopedCurrentArch::GetCurrentArch(), *sample->thread, regs, stack); if (!unwind_ips.empty()) { ips.push_back(PERF_CONTEXT_USER); ips.insert(ips.end(), unwind_ips.begin(), unwind_ips.end()); @@ -633,7 +637,8 @@ bool ReportCommand::ReadFeaturesFromRecordFile() { std::string arch = record_file_reader_->ReadFeatureString(PerfFileFormat::FEAT_ARCH); if (!arch.empty()) { - if (!SetCurrentArch(arch)) { + record_file_arch_ = GetArchType(arch); + if (record_file_arch_ == ARCH_UNSUPPORTED) { return false; } } diff --git a/simpleperf/dwarf_unwind.cpp b/simpleperf/dwarf_unwind.cpp index fd84febe..ae2e1a1f 100644 --- a/simpleperf/dwarf_unwind.cpp +++ b/simpleperf/dwarf_unwind.cpp @@ -94,15 +94,15 @@ static ucontext_t BuildUContextFromRegs(const RegSet& regs __attribute__((unused return ucontext; } -std::vector<uint64_t> UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, - const std::vector<char>& stack) { +std::vector<uint64_t> UnwindCallChain(ArchType arch, const ThreadEntry& thread, + const RegSet& regs, const std::vector<char>& stack) { std::vector<uint64_t> result; - if (GetCurrentArch() != GetBuildArch()) { + if (arch != GetBuildArch()) { LOG(ERROR) << "can't unwind data recorded on a different architecture"; return result; } uint64_t sp_reg_value; - if (!GetSpRegValue(regs, &sp_reg_value)) { + if (!GetSpRegValue(regs, arch, &sp_reg_value)) { LOG(ERROR) << "can't get sp reg value"; return result; } diff --git a/simpleperf/dwarf_unwind.h b/simpleperf/dwarf_unwind.h index 671013ea..4e3ffd1b 100644 --- a/simpleperf/dwarf_unwind.h +++ b/simpleperf/dwarf_unwind.h @@ -23,7 +23,7 @@ struct ThreadEntry; -std::vector<uint64_t> UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, +std::vector<uint64_t> UnwindCallChain(ArchType arch, const ThreadEntry& thread, const RegSet& regs, const std::vector<char>& stack); #endif // SIMPLE_PERF_DWARF_UNWIND_H_ diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index d99966a2..fad8b1e1 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -45,7 +45,7 @@ bool IsDwarfCallChainSamplingSupported() { perf_event_attr attr = CreateDefaultPerfEventAttr(*type); attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER; attr.exclude_callchain_user = 1; - attr.sample_regs_user = GetSupportedRegMask(); + attr.sample_regs_user = GetSupportedRegMask(GetBuildArch()); attr.sample_stack_user = 8192; return IsEventAttrSupportedByKernel(attr); } @@ -166,7 +166,7 @@ bool EventSelectionSet::EnableDwarfCallChainSampling(uint32_t dump_stack_size) { selection.event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER; selection.event_attr.exclude_callchain_user = 1; - selection.event_attr.sample_regs_user = GetSupportedRegMask(); + selection.event_attr.sample_regs_user = GetSupportedRegMask(GetBuildArch()); selection.event_attr.sample_stack_user = dump_stack_size; } return true; diff --git a/simpleperf/nonlinux_support/nonlinux_support.cpp b/simpleperf/nonlinux_support/nonlinux_support.cpp index a2489956..7551d364 100644 --- a/simpleperf/nonlinux_support/nonlinux_support.cpp +++ b/simpleperf/nonlinux_support/nonlinux_support.cpp @@ -20,7 +20,8 @@ #include "dwarf_unwind.h" #include "environment.h" -std::vector<uint64_t> UnwindCallChain(const ThreadEntry&, const RegSet&, const std::vector<char>&) { +std::vector<uint64_t> UnwindCallChain(ArchType, const ThreadEntry&, const RegSet&, + const std::vector<char>&) { return std::vector<uint64_t>(); } diff --git a/simpleperf/perf_regs.cpp b/simpleperf/perf_regs.cpp index 1f29971c..29d144e7 100644 --- a/simpleperf/perf_regs.cpp +++ b/simpleperf/perf_regs.cpp @@ -21,30 +21,24 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> -static ArchType current_arch = GetBuildArch(); +ArchType ScopedCurrentArch::current_arch = GetBuildArch(); -ArchType GetCurrentArch() { - return current_arch; -} - -bool SetCurrentArch(const std::string& arch) { +ArchType GetArchType(const std::string& arch) { if (arch == "x86" || arch == "i686") { - current_arch = ARCH_X86_32; + 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: @@ -78,10 +72,10 @@ 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 regno) { +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 (GetCurrentArch()) { + switch (arch) { case ARCH_X86_64: { if (reg >= PERF_REG_X86_R8 && reg <= PERF_REG_X86_R15) { return android::base::StringPrintf("r%d", reg - PERF_REG_X86_R8 + 8); @@ -133,18 +127,23 @@ bool GetRegValue(const RegSet& regs, size_t regno, uint64_t* value) { return false; } -bool GetSpRegValue(const RegSet& regs, uint64_t* value) { +bool GetSpRegValue(const RegSet& regs, ArchType arch, uint64_t* value) { size_t regno; -#if defined(__i386__) - regno = PERF_REG_X86_SP; -#elif defined(__x86_64__) - regno = PERF_REG_X86_SP; -#elif defined(__aarch64__) - regno = PERF_REG_ARM64_SP; -#elif defined(__arm__) - regno = PERF_REG_ARM_SP; -#else - return false; -#endif + 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); } diff --git a/simpleperf/perf_regs.h b/simpleperf/perf_regs.h index 47451c0c..9fc610f8 100644 --- a/simpleperf/perf_regs.h +++ b/simpleperf/perf_regs.h @@ -55,12 +55,26 @@ constexpr ArchType GetBuildArch() { #endif } -ArchType GetCurrentArch(); -bool SetCurrentArch(const std::string& arch); +ArchType GetArchType(const std::string& arch); +uint64_t GetSupportedRegMask(ArchType arch); +std::string GetRegName(size_t regno, ArchType arch); -uint64_t GetSupportedRegMask(); +class ScopedCurrentArch { + public: + ScopedCurrentArch(ArchType arch) : saved_arch(current_arch) { + current_arch = arch; + } + ~ScopedCurrentArch() { + current_arch = saved_arch; + } + static ArchType GetCurrentArch() { + return current_arch; + } -std::string GetRegName(size_t regno); + private: + ArchType saved_arch; + static ArchType current_arch; +}; struct RegSet { uint64_t valid_mask; @@ -70,6 +84,6 @@ struct RegSet { RegSet CreateRegSet(uint64_t valid_mask, const std::vector<uint64_t>& valid_regs); bool GetRegValue(const RegSet& regs, size_t regno, uint64_t* value); -bool GetSpRegValue(const RegSet& regs, uint64_t* value); +bool GetSpRegValue(const RegSet& regs, ArchType arch, uint64_t* value); #endif // SIMPLE_PERF_PERF_REGS_H_ diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index 5c048fba..fca2403d 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -505,7 +505,8 @@ void SampleRecord::DumpData(size_t indent) const { PrintIndented(indent, "user regs: abi=%" PRId64 "\n", regs_user_data.abi); for (size_t i = 0, pos = 0; i < 64; ++i) { if ((regs_user_data.reg_mask >> i) & 1) { - PrintIndented(indent + 1, "reg (%s) 0x%016" PRIx64 "\n", GetRegName(i).c_str(), + PrintIndented(indent + 1, "reg (%s) 0x%016" PRIx64 "\n", + GetRegName(i, ScopedCurrentArch::GetCurrentArch()).c_str(), regs_user_data.regs[pos++]); } } |