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
Test: run simpleperf_unit_test.
Change-Id: Ib5ebd0b6f981b00c2a256d17cdfd0e725d75a272
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));
}
} 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;
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"
child_thread.name = parent_thread.name;
break;
}
- case PERF_RECORD_TRACING_DATA: {
+ case PERF_RECORD_TRACING_DATA:
+ case SIMPLE_PERF_RECORD_TRACING_DATA: {
const TracingDataRecord& r = *static_cast<const TracingDataRecord*>(&record);
Tracing tracing(std::vector<char>(r.data, r.data + r.data_size));
const EventType* event = FindEventTypeByName("sched:sched_stat_runtime");
// generated by `simpleperf record -a -e sched:sched_stat_runtime`.
static const std::string PERF_DATA_SCHED_STAT_RUNTIME = "perf_sched_stat_runtime.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_
{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);
}
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()];
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));
}
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
#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>
} else if (s[i] == ';') {
value = s.substr(start, i - start);
if (name == "field") {
- size_t pos = value.find('[');
- 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 =