diff options
author | Yabin Cui <yabinc@google.com> | 2023-04-07 14:01:09 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2023-04-17 11:21:19 -0700 |
commit | fcca320717c7ab5e6cfd268dca389c410433479a (patch) | |
tree | 3effd5ecac4ad5cbe21166d5cde8a115c4761b4e /simpleperf | |
parent | 06ed3efac24ba19a837b6a4110f15b7c78ab42d0 (diff) | |
download | extras-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.cpp | 15 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 11 | ||||
-rw-r--r-- | simpleperf/event_attr.cpp | 7 | ||||
-rw-r--r-- | simpleperf/event_attr.h | 1 | ||||
-rw-r--r-- | simpleperf/record.cpp | 4 | ||||
-rw-r--r-- | simpleperf/record_test.cpp | 4 |
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); |