From 29ea1421b2b7d77d4d47f6f4534428385e11dae8 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Wed, 21 Mar 2018 14:34:29 -0700 Subject: simpleperf: add SIMPLE_PERF_RECORD_TRACE_DATA record type. PERF_RECORD_TRACE_DATA can't have record size >= 64K. This causes some aborts when recording tracepoint events, as in https://github.com/android-ndk/ndk/issues/493. So fix this by adding a custom type SIMPLE_PERF_RECORD_TRACING_DATA, which isn't limited by 64K. Also fix an error parsing formats of tracepoing events. Bug: http://b/75278602 Bug: http://b/68954287 Test: run simpleperf_unit_test. Change-Id: Ib5ebd0b6f981b00c2a256d17cdfd0e725d75a272 (cherry picked from commit 8cd9233b017d3fd0389c2650fcbbae74ef8ced12) --- simpleperf/cmd_kmem.cpp | 3 ++- simpleperf/cmd_report.cpp | 3 ++- simpleperf/cmd_report_test.cpp | 5 +++++ simpleperf/get_test_data.h | 2 ++ simpleperf/record.cpp | 7 ++++++- simpleperf/record.h | 3 +++ simpleperf/testdata/perf_with_big_trace_data.data | Bin 0 -> 491147 bytes simpleperf/tracing.cpp | 20 +++++++++++++++----- 8 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 simpleperf/testdata/perf_with_big_trace_data.data diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp index 51f9a58a..59ec2c3f 100644 --- a/simpleperf/cmd_kmem.cpp +++ b/simpleperf/cmd_kmem.cpp @@ -612,7 +612,8 @@ bool KmemCommand::ProcessRecord(std::unique_ptr record) { slab_sample_tree_builder_->ProcessSampleRecord( *static_cast(record.get())); } - } else if (record->type() == PERF_RECORD_TRACING_DATA) { + } else if (record->type() == PERF_RECORD_TRACING_DATA || + record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) { const auto& r = *static_cast(record.get()); ProcessTracingData(std::vector(r.data, r.data + r.data_size)); } diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index 29cf743a..f026d32a 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -777,7 +777,8 @@ bool ReportCommand::ProcessRecord(std::unique_ptr record) { size_t attr_id = record_file_reader_->GetAttrIndexOfRecord(record.get()); sample_tree_builder_[attr_id]->ProcessSampleRecord( *static_cast(record.get())); - } else if (record->type() == PERF_RECORD_TRACING_DATA) { + } else if (record->type() == PERF_RECORD_TRACING_DATA || + record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) { const auto& r = *static_cast(record.get()); if (!ProcessTracingData(std::vector(r.data, r.data + r.data_size))) { return false; diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp index e146876b..2790c279 100644 --- a/simpleperf/cmd_report_test.cpp +++ b/simpleperf/cmd_report_test.cpp @@ -471,6 +471,11 @@ TEST_F(ReportCommandTest, full_callgraph_option) { ASSERT_EQ(content.find("skipped in brief callgraph mode"), std::string::npos); } +TEST_F(ReportCommandTest, report_big_trace_data) { + Report(PERF_DATA_WITH_BIG_TRACE_DATA); + ASSERT_TRUE(success); +} + #if defined(__linux__) #include "event_selection_set.h" diff --git a/simpleperf/get_test_data.h b/simpleperf/get_test_data.h index 963fe006..625b3dec 100644 --- a/simpleperf/get_test_data.h +++ b/simpleperf/get_test_data.h @@ -108,4 +108,6 @@ static const std::string INVALID_PERF_DATA = "invalid_perf.data"; // generated by recording an app. static const std::string PERF_DATA_WITH_WRONG_IP_IN_CALLCHAIN = "wrong_ip_callchain_perf.data"; +static const std::string PERF_DATA_WITH_BIG_TRACE_DATA = "perf_with_big_trace_data.data"; + #endif // SIMPLE_PERF_GET_TEST_DATA_H_ diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index 65e98ea6..697434b1 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -46,6 +46,9 @@ static std::string RecordTypeToString(int record_type) { {SIMPLE_PERF_RECORD_DSO, "dso"}, {SIMPLE_PERF_RECORD_SYMBOL, "symbol"}, {SIMPLE_PERF_RECORD_EVENT_ID, "event_id"}, + {SIMPLE_PERF_RECORD_CALLCHAIN, "callchain"}, + {SIMPLE_PERF_RECORD_UNWINDING_RESULT, "unwinding_result"}, + {SIMPLE_PERF_RECORD_TRACING_DATA, "tracing_data"}, }; auto it = record_type_names.find(record_type); @@ -821,7 +824,7 @@ TracingDataRecord::TracingDataRecord(const char* p) : Record(p) { } TracingDataRecord::TracingDataRecord(const std::vector& tracing_data) { - SetTypeAndMisc(PERF_RECORD_TRACING_DATA, 0); + SetTypeAndMisc(SIMPLE_PERF_RECORD_TRACING_DATA, 0); data_size = tracing_data.size(); SetSize(header_size() + sizeof(uint32_t) + Align(tracing_data.size(), 64)); char* new_binary = new char[size()]; @@ -904,6 +907,8 @@ std::unique_ptr ReadRecordFromBuffer(const perf_event_attr& attr, return std::unique_ptr(new SymbolRecord(p)); case SIMPLE_PERF_RECORD_EVENT_ID: return std::unique_ptr(new EventIdRecord(p)); + case SIMPLE_PERF_RECORD_TRACING_DATA: + return std::unique_ptr(new TracingDataRecord(p)); default: return std::unique_ptr(new UnknownRecord(p)); } diff --git a/simpleperf/record.h b/simpleperf/record.h index d6ee2ce5..cfe3191a 100644 --- a/simpleperf/record.h +++ b/simpleperf/record.h @@ -46,6 +46,9 @@ enum user_record_type { SIMPLE_PERF_RECORD_SPLIT, SIMPLE_PERF_RECORD_SPLIT_END, SIMPLE_PERF_RECORD_EVENT_ID, + SIMPLE_PERF_RECORD_CALLCHAIN, + SIMPLE_PERF_RECORD_UNWINDING_RESULT, + SIMPLE_PERF_RECORD_TRACING_DATA, }; // perf_event_header uses u16 to store record size. However, that is not diff --git a/simpleperf/testdata/perf_with_big_trace_data.data b/simpleperf/testdata/perf_with_big_trace_data.data new file mode 100644 index 00000000..5134ec52 Binary files /dev/null and b/simpleperf/testdata/perf_with_big_trace_data.data differ diff --git a/simpleperf/tracing.cpp b/simpleperf/tracing.cpp index 884a883c..df86d597 100644 --- a/simpleperf/tracing.cpp +++ b/simpleperf/tracing.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -295,14 +296,23 @@ static TracingField ParseTracingField(const std::string& s) { } else if (s[i] == ';') { value = s.substr(start, i - start); if (name == "field") { - size_t pos = value.find_first_of('['); - if (pos == std::string::npos) { + // Parse value with brackets like "comm[16]", or just a field name. + size_t left_bracket_pos = value.find('['); + if (left_bracket_pos == std::string::npos) { field.name = value; field.elem_count = 1; } else { - field.name = value.substr(0, pos); - field.elem_count = - static_cast(strtoull(&value[pos + 1], nullptr, 10)); + field.name = value.substr(0, left_bracket_pos); + field.elem_count = 1; + size_t right_bracket_pos = value.find(']', left_bracket_pos); + if (right_bracket_pos != std::string::npos) { + size_t len = right_bracket_pos - left_bracket_pos - 1; + size_t elem_count; + // Array size may not be a number, like field:u32 rates[IEEE80211_NUM_BANDS]. + if (android::base::ParseUint(value.substr(left_bracket_pos + 1, len), &elem_count)) { + field.elem_count = elem_count; + } + } } } else if (name == "offset") { field.offset = -- cgit v1.2.3 From 3231ba48934f04d61fa954e555d0f7fedc579e12 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Fri, 11 May 2018 17:30:37 -0700 Subject: simpleperf: fix *handle_SIGHUP tests. Fix record_cmd.handle_SIGHUP and omit stat_cmd.handle_SIGHUP in cts tests. Bug: http://b/79495636 Test: run CtsSimpleperfTestCases. Change-Id: I3a540207082000a1d0cdf39ab53798411a8b4d24 (cherry picked from commit 9bd7e57e5f68db6906b1d5fed9a9a76f6973f6ff) --- simpleperf/cmd_record_test.cpp | 17 +++++++++++++---- simpleperf/cmd_stat_test.cpp | 5 +++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index c3f9cb40..e942332f 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -391,12 +391,21 @@ TEST(record_cmd, support_modifier_for_clock_events) { TEST(record_cmd, handle_SIGHUP) { TemporaryFile tmpfile; - std::thread thread([]() { - sleep(1); + int pipefd[2]; + ASSERT_EQ(0, pipe(pipefd)); + int read_fd = pipefd[0]; + int write_fd = pipefd[1]; + char data[8] = {}; + std::thread thread([&]() { + android::base::ReadFully(read_fd, data, 7); kill(getpid(), SIGHUP); }); - thread.detach(); - ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "sleep", "1000000"})); + ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "--start_profiling_fd", + std::to_string(write_fd), "sleep", "1000000"})); + thread.join(); + close(write_fd); + close(read_fd); + ASSERT_STREQ(data, "STARTED"); } TEST(record_cmd, stop_when_no_more_targets) { diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp index 3cdb4ebd..3876b420 100644 --- a/simpleperf/cmd_stat_test.cpp +++ b/simpleperf/cmd_stat_test.cpp @@ -157,6 +157,11 @@ TEST(stat_cmd, no_modifier_for_clock_events) { } TEST(stat_cmd, handle_SIGHUP) { + if (!GetDefaultAppPackageName().empty()) { + // See http://b/79495636. + GTEST_LOG_(INFO) << "Omit this test in app's context."; + return; + } std::thread thread([]() { sleep(1); kill(getpid(), SIGHUP); -- cgit v1.2.3