summaryrefslogtreecommitdiff
path: root/simpleperf
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2023-04-07 14:01:09 -0700
committerYabin Cui <yabinc@google.com>2023-04-17 11:21:19 -0700
commitfcca320717c7ab5e6cfd268dca389c410433479a (patch)
tree3effd5ecac4ad5cbe21166d5cde8a115c4761b4e /simpleperf
parent06ed3efac24ba19a837b6a4110f15b7c78ab42d0 (diff)
downloadextras-fcca320717c7ab5e6cfd268dca389c410433479a.tar.gz
simpleperf: Remove stack and reg fields in samples after unwinding
perf_data_converter doesn't support stack and regs fields. This is to create recording file parseable by perf_data_converter. Bug: 273341791 Test: run simpleperf_unit_test Change-Id: Ie05c683eb2f3eec3e08e482b82cbc0be4abe834a
Diffstat (limited to 'simpleperf')
-rw-r--r--simpleperf/cmd_record.cpp15
-rw-r--r--simpleperf/cmd_record_test.cpp11
-rw-r--r--simpleperf/event_attr.cpp7
-rw-r--r--simpleperf/event_attr.h1
-rw-r--r--simpleperf/record.cpp4
-rw-r--r--simpleperf/record_test.cpp4
6 files changed, 39 insertions, 3 deletions
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 974be878..912d3e77 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -1371,6 +1371,12 @@ bool RecordCommand::SetEventSelectionFlags() {
bool RecordCommand::CreateAndInitRecordFile() {
EventAttrIds attrs = event_selection_set_.GetEventAttrWithId();
+ bool remove_regs_and_stacks = unwind_dwarf_callchain_ && !post_unwind_;
+ if (remove_regs_and_stacks) {
+ for (auto& attr : attrs) {
+ ReplaceRegAndStackWithCallChain(attr.attr);
+ }
+ }
record_file_writer_ = CreateRecordFile(record_filename_, attrs);
if (record_file_writer_ == nullptr) {
return false;
@@ -1841,6 +1847,15 @@ bool RecordCommand::PostUnwindRecords() {
if (!reader) {
return false;
}
+ // Write new event attrs without regs and stacks fields.
+ EventAttrIds attrs = reader->AttrSection();
+ for (auto& attr : attrs) {
+ ReplaceRegAndStackWithCallChain(attr.attr);
+ }
+ if (!record_file_writer_->WriteAttrSection(attrs)) {
+ return false;
+ }
+
sample_record_count_ = 0;
auto callback = [this](std::unique_ptr<Record> record) {
return SaveRecordAfterUnwinding(record.get());
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index 3882a32c..395bfd19 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -257,7 +257,16 @@ TEST(record_cmd, dwarf_callchain_sampling) {
ASSERT_TRUE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf"}));
ASSERT_TRUE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf,16384"}));
ASSERT_FALSE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf,65536"}));
- ASSERT_TRUE(RunRecordCmd({"-p", pid, "-g"}));
+ TemporaryFile tmpfile;
+ ASSERT_TRUE(RunRecordCmd({"-p", pid, "-g"}, tmpfile.path));
+ auto reader = RecordFileReader::CreateInstance(tmpfile.path);
+ ASSERT_TRUE(reader);
+ const EventAttrIds& attrs = reader->AttrSection();
+ ASSERT_GT(attrs.size(), 0);
+ // Check that reg and stack fields are removed after unwinding.
+ for (const auto& attr : attrs) {
+ ASSERT_EQ(attr.attr.sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER), 0);
+ }
}
TEST(record_cmd, system_wide_dwarf_callchain_sampling) {
diff --git a/simpleperf/event_attr.cpp b/simpleperf/event_attr.cpp
index 4aaaff10..b8acc341 100644
--- a/simpleperf/event_attr.cpp
+++ b/simpleperf/event_attr.cpp
@@ -254,4 +254,11 @@ std::string GetEventNameByAttr(const perf_event_attr& attr) {
return name;
}
+void ReplaceRegAndStackWithCallChain(perf_event_attr& attr) {
+ attr.sample_type &= ~(PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER);
+ attr.exclude_callchain_user = 0;
+ attr.sample_regs_user = 0;
+ attr.sample_stack_user = 0;
+}
+
} // namespace simpleperf
diff --git a/simpleperf/event_attr.h b/simpleperf/event_attr.h
index a4b989ae..5521f328 100644
--- a/simpleperf/event_attr.h
+++ b/simpleperf/event_attr.h
@@ -48,6 +48,7 @@ bool IsCpuSupported(const perf_event_attr& attr);
// Return event name with modifier if the event is found, otherwise return "unknown".
// This function is slow for using linear search, so only used when reporting.
std::string GetEventNameByAttr(const perf_event_attr& attr);
+void ReplaceRegAndStackWithCallChain(perf_event_attr& attr);
inline bool operator==(const perf_event_attr& attr1, const perf_event_attr& attr2) {
return memcmp(&attr1, &attr2, sizeof(perf_event_attr)) == 0;
diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp
index 40d3287a..c364b2fc 100644
--- a/simpleperf/record.cpp
+++ b/simpleperf/record.cpp
@@ -713,8 +713,10 @@ SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip
void SampleRecord::ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips) {
uint32_t size_added_in_callchain = sizeof(uint64_t) * (ips.size() + 1);
uint32_t size_reduced_in_reg_stack =
- regs_user_data.reg_nr * sizeof(uint64_t) + stack_user_data.size + sizeof(uint64_t);
+ (regs_user_data.reg_nr + 1) * sizeof(uint64_t) + stack_user_data.size + sizeof(uint64_t) * 2;
+
uint32_t new_size = size() + size_added_in_callchain - size_reduced_in_reg_stack;
+ sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER);
BuildBinaryWithNewCallChain(new_size, ips);
}
diff --git a/simpleperf/record_test.cpp b/simpleperf/record_test.cpp
index ddecc9bd..8d9d151a 100644
--- a/simpleperf/record_test.cpp
+++ b/simpleperf/record_test.cpp
@@ -104,11 +104,13 @@ TEST_F(RecordTest, SampleRecord_exclude_kernel_callchain) {
}
TEST_F(RecordTest, SampleRecord_ReplaceRegAndStackWithCallChain) {
- event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
+ event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
SampleRecord expected(event_attr, 0, 1, 2, 3, 4, 5, 6, {}, {1, PERF_CONTEXT_USER, 2, 3, 4, 5}, {},
0);
for (size_t stack_size : {8, 1024}) {
+ event_attr.sample_type |= PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {}, {1}, std::vector<char>(stack_size), 10);
+ event_attr.sample_type &= ~(PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER);
r.ReplaceRegAndStackWithCallChain({2, 3, 4, 5});
CheckRecordMatchBinary(r);
CheckRecordEqual(r, expected);