summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2018-03-21 14:34:29 -0700
committerYabin Cui <yabinc@google.com>2018-08-02 16:58:24 -0700
commit6c1666307e1088fa392f0b0e211fed2c6f99c8ce (patch)
tree5505987113d5618200a46d633034e81b343dd629
parentb8d86c0051a0113659edf2bf7ea80b6d318e01f5 (diff)
downloadextras-6c1666307e1088fa392f0b0e211fed2c6f99c8ce.tar.gz
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/80438359 Test: run CtsSimpelperfTestCases. Change-Id: Ib5ebd0b6f981b00c2a256d17cdfd0e725d75a272 (cherry picked from commit 8cd9233b017d3fd0389c2650fcbbae74ef8ced12)
-rw-r--r--simpleperf/cmd_kmem.cpp3
-rw-r--r--simpleperf/cmd_report.cpp3
-rw-r--r--simpleperf/cmd_report_test.cpp5
-rw-r--r--simpleperf/get_test_data.h3
-rw-r--r--simpleperf/record.cpp5
-rw-r--r--simpleperf/record.h1
-rw-r--r--simpleperf/testdata/perf_with_big_trace_data.databin0 -> 491147 bytes
-rw-r--r--simpleperf/tracing.cpp20
8 files changed, 32 insertions, 8 deletions
diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp
index 6ae908d6..5d58c394 100644
--- a/simpleperf/cmd_kmem.cpp
+++ b/simpleperf/cmd_kmem.cpp
@@ -611,7 +611,8 @@ bool KmemCommand::ProcessRecord(std::unique_ptr<Record> record) {
slab_sample_tree_builder_->ProcessSampleRecord(
*static_cast<const SampleRecord*>(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<TracingDataRecord*>(record.get());
ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size));
}
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp
index 9aee30ac..6a757f09 100644
--- a/simpleperf/cmd_report.cpp
+++ b/simpleperf/cmd_report.cpp
@@ -882,7 +882,8 @@ bool ReportCommand::ProcessRecord(std::unique_ptr<Record> record) {
} else {
ProcessSampleRecordInTraceOffCpuMode(std::move(record), attr_id);
}
- } 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<TracingDataRecord*>(record.get());
if (!ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size))) {
return false;
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index 28f226d2..6ebbf31e 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -486,6 +486,11 @@ TEST_F(ReportCommandTest, report_offcpu_time) {
ASSERT_TRUE(found);
}
+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 05b724ee..5d0a4f24 100644
--- a/simpleperf/get_test_data.h
+++ b/simpleperf/get_test_data.h
@@ -117,4 +117,7 @@ static const std::string PERF_DATA_WITH_CALLCHAIN_RECORD = "perf_with_callchain_
// generated by `simpleperf record -g --no-unwind`.
static const std::string PERF_DATA_NO_UNWIND = "perf_no_unwind.data";
+// generated by `simpleperf record -e (about 200 tracepoint events) sleep 1`.
+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 a03f3771..5fd762c7 100644
--- a/simpleperf/record.cpp
+++ b/simpleperf/record.cpp
@@ -51,6 +51,7 @@ static std::string RecordTypeToString(int record_type) {
{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);
@@ -990,7 +991,7 @@ TracingDataRecord::TracingDataRecord(char* p) : Record(p) {
}
TracingDataRecord::TracingDataRecord(const std::vector<char>& 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()];
@@ -1193,6 +1194,8 @@ std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32
return std::unique_ptr<Record>(new CallChainRecord(p));
case SIMPLE_PERF_RECORD_UNWINDING_RESULT:
return std::unique_ptr<Record>(new UnwindingResultRecord(p));
+ case SIMPLE_PERF_RECORD_TRACING_DATA:
+ return std::unique_ptr<Record>(new TracingDataRecord(p));
default:
return std::unique_ptr<Record>(new UnknownRecord(p));
}
diff --git a/simpleperf/record.h b/simpleperf/record.h
index b862e401..f9041c51 100644
--- a/simpleperf/record.h
+++ b/simpleperf/record.h
@@ -50,6 +50,7 @@ enum user_record_type {
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
--- /dev/null
+++ b/simpleperf/testdata/perf_with_big_trace_data.data
Binary files 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 <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -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<size_t>(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 =