summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2016-03-28 17:47:52 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-03-28 17:47:53 +0000
commit7c4bbdc60586231e9601c6b199ec68317269ddd6 (patch)
treed9a7c2c6f82e9eae9676bf980a55ede3f7ade426
parent9fbb28cc4a05cbc9d571664cc31896899011bcde (diff)
parente435e7d8706ff234fdc69e9a9424fb2b08806658 (diff)
downloadextras-7c4bbdc60586231e9601c6b199ec68317269ddd6.tar.gz
Merge "Simpleperf: remove dependency on global current_arch." into nyc-dev
-rw-r--r--simpleperf/cmd_dumprecord.cpp7
-rw-r--r--simpleperf/cmd_record.cpp2
-rw-r--r--simpleperf/cmd_report.cpp9
-rw-r--r--simpleperf/dwarf_unwind.cpp8
-rw-r--r--simpleperf/dwarf_unwind.h2
-rw-r--r--simpleperf/event_selection_set.cpp4
-rw-r--r--simpleperf/nonlinux_support/nonlinux_support.cpp3
-rw-r--r--simpleperf/perf_regs.cpp59
-rw-r--r--simpleperf/perf_regs.h24
-rw-r--r--simpleperf/record.cpp3
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++]);
}
}