summaryrefslogtreecommitdiff
path: root/simpleperf/record.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/record.cpp')
-rw-r--r--simpleperf/record.cpp562
1 files changed, 155 insertions, 407 deletions
diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp
index 4590b9ef..4e8a8822 100644
--- a/simpleperf/record.cpp
+++ b/simpleperf/record.cpp
@@ -21,7 +21,6 @@
#include <unordered_map>
#include <android-base/logging.h>
-#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include "OfflineUnwinder.h"
@@ -32,15 +31,6 @@
namespace simpleperf {
-#define CHECK_SIZE(p, end, size) \
- do { \
- if (UNLIKELY((end) - (p) < (size))) { \
- return false; \
- } \
- } while (0)
-
-#define CHECK_SIZE_U64(p, end, u64_count) CHECK_SIZE(p, end, (u64_count) * sizeof(uint64_t))
-
static std::string RecordTypeToString(int record_type) {
static std::unordered_map<int, std::string> record_type_names = {
{PERF_RECORD_MMAP, "mmap"},
@@ -55,8 +45,6 @@ static std::string RecordTypeToString(int record_type) {
{PERF_RECORD_BUILD_ID, "build_id"},
{PERF_RECORD_MMAP2, "mmap2"},
{PERF_RECORD_AUX, "aux"},
- {PERF_RECORD_SWITCH, "switch"},
- {PERF_RECORD_SWITCH_CPU_WIDE, "switch_cpu_wide"},
{PERF_RECORD_TRACING_DATA, "tracing_data"},
{PERF_RECORD_AUXTRACE_INFO, "auxtrace_info"},
{PERF_RECORD_AUXTRACE, "auxtrace"},
@@ -94,14 +82,10 @@ size_t SampleId::CreateContent(const perf_event_attr& attr, uint64_t event_id) {
return Size();
}
-bool SampleId::ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end) {
+void SampleId::ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end) {
sample_id_all = attr.sample_id_all;
sample_type = attr.sample_type;
if (sample_id_all) {
- const uint64_t sample_id_mask = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID |
- PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU |
- PERF_SAMPLE_IDENTIFIER;
- CHECK_SIZE_U64(p, end, __builtin_popcountll(sample_type & sample_id_mask));
if (sample_type & PERF_SAMPLE_TID) {
MoveFromBinaryFormat(tid_data, p);
}
@@ -121,10 +105,10 @@ bool SampleId::ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
MoveFromBinaryFormat(id_data, p);
}
}
- if (UNLIKELY(p < end)) {
+ CHECK_LE(p, end);
+ if (p < end) {
LOG(DEBUG) << "Record SampleId part has " << end - p << " bytes left\n";
}
- return true;
}
void SampleId::WriteToBinaryFormat(char*& p) const {
@@ -201,19 +185,8 @@ Record::Record(Record&& other) noexcept {
other.own_binary_ = false;
}
-bool Record::ParseHeader(char*& p, char*& end) {
- binary_ = p;
- CHECK(end != nullptr);
- CHECK_SIZE(p, end, sizeof(perf_event_header));
- header = RecordHeader(p);
- CHECK_SIZE(p, end, header.size);
- end = p + header.size;
- p += sizeof(perf_event_header);
- return true;
-}
-
void Record::Dump(size_t indent) const {
- PrintIndented(indent, "record %s: type %u, misc 0x%x, size %u\n",
+ PrintIndented(indent, "record %s: type %u, misc %u, size %u\n",
RecordTypeToString(type()).c_str(), type(), misc(), size());
DumpData(indent + 1);
sample_id.Dump(indent + 1);
@@ -237,18 +210,15 @@ void Record::UpdateBinary(char* new_binary) {
binary_ = new_binary;
}
-bool MmapRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+MmapRecord::MmapRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<const MmapRecordDataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
p += sizeof(*data);
- size_t size = Align(SafeStrlen(p, end) + 1, 8);
- CHECK_SIZE(p, end, size);
filename = p;
- p += size;
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ p += Align(strlen(filename) + 1, 8);
+ CHECK_LE(p, end);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
MmapRecord::MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
@@ -286,18 +256,15 @@ void MmapRecord::DumpData(size_t indent) const {
PrintIndented(indent, "pgoff 0x%" PRIx64 ", filename %s\n", data->pgoff, filename);
}
-bool Mmap2Record::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+Mmap2Record::Mmap2Record(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<const Mmap2RecordDataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
p += sizeof(*data);
- size_t size = Align(SafeStrlen(p, end) + 1, 8);
- CHECK_SIZE(p, end, size);
filename = p;
- p += size;
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ p += Align(strlen(filename) + 1, 8);
+ CHECK_LE(p, end);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
Mmap2Record::Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
@@ -339,18 +306,15 @@ void Mmap2Record::DumpData(size_t indent) const {
PrintIndented(indent, "prot %u, flags %u, filename %s\n", data->prot, data->flags, filename);
}
-bool CommRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+CommRecord::CommRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<const CommRecordDataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
p += sizeof(*data);
- size_t size = Align(SafeStrlen(p, end) + 1, 8);
- CHECK_SIZE(p, end, size);
comm = p;
- p += size;
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ p += Align(strlen(p) + 1, 8);
+ CHECK_LE(p, end);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
CommRecord::CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
@@ -401,14 +365,13 @@ void CommRecord::DumpData(size_t indent) const {
PrintIndented(indent, "pid %u, tid %u, comm %s\n", data->pid, data->tid, comm);
}
-bool ExitOrForkRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+ExitOrForkRecord::ExitOrForkRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<const ExitOrForkRecordDataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
p += sizeof(*data);
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ CHECK_LE(p, end);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
void ExitOrForkRecord::DumpData(size_t indent) const {
@@ -436,30 +399,23 @@ ForkRecord::ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
UpdateBinary(new_binary);
}
-bool LostRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 2);
+LostRecord::LostRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(id, p);
MoveFromBinaryFormat(lost, p);
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ CHECK_LE(p, end);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
void LostRecord::DumpData(size_t indent) const {
PrintIndented(indent, "id %" PRIu64 ", lost %" PRIu64 "\n", id, lost);
}
-bool SampleRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+SampleRecord::SampleRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
sample_type = attr.sample_type;
- read_format = attr.read_format;
- const uint64_t sample_mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | PERF_SAMPLE_TID |
- PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | PERF_SAMPLE_ID |
- PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD;
- CHECK_SIZE_U64(p, end, __builtin_popcountll(sample_type & sample_mask));
// Set a default id value to report correctly even if ID is not recorded.
id_data.id = 0;
@@ -490,98 +446,60 @@ bool SampleRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
if (sample_type & PERF_SAMPLE_PERIOD) {
MoveFromBinaryFormat(period_data, p);
}
- if (sample_type & PERF_SAMPLE_READ) {
- uint64_t nr = 1;
- if (read_format & PERF_FORMAT_GROUP) {
- CHECK_SIZE_U64(p, end, 1);
- MoveFromBinaryFormat(nr, p);
- }
- size_t u64_count = (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) ? 1 : 0;
- u64_count += (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) ? 1 : 0;
- u64_count += ((read_format & PERF_FORMAT_ID) ? 2 : 1) * nr;
- CHECK_SIZE_U64(p, end, u64_count);
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
- MoveFromBinaryFormat(read_data.time_enabled, p);
- }
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
- MoveFromBinaryFormat(read_data.time_running, p);
- }
- read_data.counts.resize(nr);
- if (read_format & PERF_FORMAT_ID) {
- read_data.ids.resize(nr);
- }
- for (uint64_t i = 0; i < nr; i++) {
- MoveFromBinaryFormat(read_data.counts[i], p);
- if (read_format & PERF_FORMAT_ID) {
- MoveFromBinaryFormat(read_data.ids[i], p);
- }
- }
- }
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(callchain_data.ip_nr, p);
- CHECK_SIZE_U64(p, end, callchain_data.ip_nr);
callchain_data.ips = reinterpret_cast<uint64_t*>(p);
p += callchain_data.ip_nr * sizeof(uint64_t);
}
if (sample_type & PERF_SAMPLE_RAW) {
- CHECK_SIZE(p, end, sizeof(uint32_t));
MoveFromBinaryFormat(raw_data.size, p);
- CHECK_SIZE(p, end, raw_data.size);
raw_data.data = p;
p += raw_data.size;
}
if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(branch_stack_data.stack_nr, p);
- CHECK_SIZE(p, end, branch_stack_data.stack_nr * sizeof(BranchStackItemType));
branch_stack_data.stack = reinterpret_cast<BranchStackItemType*>(p);
p += branch_stack_data.stack_nr * sizeof(BranchStackItemType);
}
if (sample_type & PERF_SAMPLE_REGS_USER) {
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(regs_user_data.abi, p);
if (regs_user_data.abi == 0) {
regs_user_data.reg_mask = 0;
} else {
regs_user_data.reg_mask = attr.sample_regs_user;
size_t bit_nr = __builtin_popcountll(regs_user_data.reg_mask);
- CHECK_SIZE_U64(p, end, bit_nr);
regs_user_data.reg_nr = bit_nr;
regs_user_data.regs = reinterpret_cast<uint64_t*>(p);
p += bit_nr * sizeof(uint64_t);
}
}
if (sample_type & PERF_SAMPLE_STACK_USER) {
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(stack_user_data.size, p);
if (stack_user_data.size == 0) {
stack_user_data.dyn_size = 0;
} else {
- CHECK_SIZE(p, end, stack_user_data.size + sizeof(uint64_t));
stack_user_data.data = p;
p += stack_user_data.size;
MoveFromBinaryFormat(stack_user_data.dyn_size, p);
}
}
// TODO: Add parsing of other PERF_SAMPLE_*.
- if (UNLIKELY(p < end)) {
+ CHECK_LE(p, end);
+ if (p < end) {
LOG(DEBUG) << "Record has " << end - p << " bytes left\n";
}
- return true;
}
SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, uint32_t pid,
uint32_t tid, uint64_t time, uint32_t cpu, uint64_t period,
- const PerfSampleReadType& read_data, const std::vector<uint64_t>& ips,
- const std::vector<char>& stack, uint64_t dyn_stack_size) {
+ const std::vector<uint64_t>& ips, const std::vector<char>& stack,
+ uint64_t dyn_stack_size) {
SetTypeAndMisc(PERF_RECORD_SAMPLE, PERF_RECORD_MISC_USER);
sample_type = attr.sample_type;
- read_format = attr.read_format;
CHECK_EQ(0u,
sample_type & ~(PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID |
- PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | PERF_SAMPLE_READ |
- PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER));
+ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | PERF_SAMPLE_CALLCHAIN |
+ PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER));
ip_data.ip = ip;
tid_data.pid = pid;
tid_data.tid = tid;
@@ -590,7 +508,6 @@ SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip
cpu_data.cpu = cpu;
cpu_data.res = 0;
period_data.period = period;
- this->read_data = read_data;
callchain_data.ip_nr = ips.size();
raw_data.size = 0;
branch_stack_data.stack_nr = 0;
@@ -619,13 +536,6 @@ SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip
if (sample_type & PERF_SAMPLE_PERIOD) {
size += sizeof(period_data);
}
- if (sample_type & PERF_SAMPLE_READ) {
- size_t u64_count = (read_format & PERF_FORMAT_GROUP) ? 1 : 0;
- u64_count += (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) ? 1 : 0;
- u64_count += (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) ? 1 : 0;
- u64_count += read_data.counts.size() + read_data.ids.size();
- size += sizeof(uint64_t) * u64_count;
- }
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
size += sizeof(uint64_t) * (ips.size() + 1);
}
@@ -658,24 +568,6 @@ SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip
if (sample_type & PERF_SAMPLE_PERIOD) {
MoveToBinaryFormat(period_data, p);
}
- if (sample_type & PERF_SAMPLE_READ) {
- if (read_format & PERF_FORMAT_GROUP) {
- uint64_t nr = read_data.counts.size();
- MoveToBinaryFormat(nr, p);
- }
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
- MoveToBinaryFormat(read_data.time_enabled, p);
- }
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
- MoveToBinaryFormat(read_data.time_running, p);
- }
- for (size_t i = 0; i < read_data.counts.size(); i++) {
- MoveToBinaryFormat(read_data.counts[i], p);
- if (read_format & PERF_FORMAT_ID) {
- MoveToBinaryFormat(read_data.ids[i], p);
- }
- }
- }
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
MoveToBinaryFormat(callchain_data.ip_nr, p);
callchain_data.ips = reinterpret_cast<uint64_t*>(p);
@@ -845,21 +737,6 @@ void SampleRecord::DumpData(size_t indent) const {
if (sample_type & PERF_SAMPLE_PERIOD) {
PrintIndented(indent, "period %" PRId64 "\n", period_data.period);
}
- if (sample_type & PERF_SAMPLE_READ) {
- PrintIndented(indent, "read nr=%zu\n", read_data.counts.size());
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
- PrintIndented(indent + 1, "time_enabled %" PRIu64 "\n", read_data.time_enabled);
- }
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
- PrintIndented(indent + 1, "time_running %" PRIu64 "\n", read_data.time_running);
- }
- for (size_t i = 0; i < read_data.counts.size(); i++) {
- PrintIndented(indent + 1, "count[%zu] %" PRIu64 "\n", i, read_data.counts[i]);
- if (read_format & PERF_FORMAT_ID) {
- PrintIndented(indent + 1, "id[%zu] %" PRIu64 "\n", i, read_data.ids[i]);
- }
- }
- }
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
PrintIndented(indent, "callchain nr=%" PRIu64 "\n", callchain_data.ip_nr);
for (uint64_t i = 0; i < callchain_data.ip_nr; ++i) {
@@ -993,14 +870,12 @@ std::vector<uint64_t> SampleRecord::GetCallChain(size_t* kernel_ip_count) const
return ips;
}
-bool AuxRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+AuxRecord::AuxRecord(const perf_event_attr& attr, char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<DataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
- p += sizeof(*data);
- return sample_id.ReadFromBinaryFormat(attr, p, end);
+ p += sizeof(DataType);
+ sample_id.ReadFromBinaryFormat(attr, p, end);
}
void AuxRecord::DumpData(size_t indent) const {
@@ -1009,44 +884,15 @@ void AuxRecord::DumpData(size_t indent) const {
PrintIndented(indent, "flags 0x%" PRIx64 "\n", data->flags);
}
-bool SwitchRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- return sample_id.ReadFromBinaryFormat(attr, p, end);
-}
-
-bool SwitchCpuWideRecord::Parse(const perf_event_attr& attr, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE(p, end, sizeof(tid_data));
- MoveFromBinaryFormat(tid_data, p);
- return sample_id.ReadFromBinaryFormat(attr, p, end);
-}
-
-void SwitchCpuWideRecord::DumpData(size_t indent) const {
- if (header.misc & PERF_RECORD_MISC_SWITCH_OUT) {
- PrintIndented(indent, "next_pid %u, next_tid %u\n", tid_data.pid, tid_data.tid);
- } else {
- PrintIndented(indent, "prev_pid %u, prev_tid %u\n", tid_data.pid, tid_data.tid);
- }
-}
-
-bool BuildIdRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- size_t size = Align(BUILD_ID_SIZE, 8);
- CHECK_SIZE(p, end, sizeof(uint32_t) + size);
+BuildIdRecord::BuildIdRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(pid, p);
build_id = BuildId(p, BUILD_ID_SIZE);
- p += size;
- size = Align(SafeStrlen(p, end) + 1, 64);
- CHECK_SIZE(p, end, size);
+ p += Align(build_id.Size(), 8);
filename = p;
- p += size;
- return p == end;
+ p += Align(strlen(filename) + 1, 64);
+ CHECK_EQ(p, end);
}
void BuildIdRecord::DumpData(size_t indent) const {
@@ -1073,53 +919,30 @@ BuildIdRecord::BuildIdRecord(bool in_kernel, uint32_t pid, const BuildId& build_
UpdateBinary(new_binary);
}
-bool AuxTraceInfoRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+AuxTraceInfoRecord::AuxTraceInfoRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
data = reinterpret_cast<DataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
- p += sizeof(*data);
- if (data->aux_type != AUX_TYPE_ETM || data->version != 1) {
- return false;
- }
+ CHECK_EQ(data->aux_type, AUX_TYPE_ETM);
+ CHECK_EQ(data->version, 0);
for (uint32_t i = 0; i < data->nr_cpu; ++i) {
- uint64_t magic = *reinterpret_cast<uint64_t*>(p);
- if (magic == MAGIC_ETM4) {
- CHECK_SIZE(p, end, sizeof(ETM4Info));
- p += sizeof(ETM4Info);
- } else if (magic == MAGIC_ETE) {
- CHECK_SIZE(p, end, sizeof(ETEInfo));
- p += sizeof(ETEInfo);
- } else {
- return false;
- }
+ CHECK_EQ(data->etm4_info[i].magic, MAGIC_ETM4);
}
- return p == end;
+ p += sizeof(DataType) + data->nr_cpu * sizeof(ETM4Info);
+ CHECK_EQ(p, end);
}
-AuxTraceInfoRecord::AuxTraceInfoRecord(const DataType& data, const std::vector<ETEInfo>& ete_info) {
+AuxTraceInfoRecord::AuxTraceInfoRecord(const DataType& data,
+ const std::vector<ETM4Info>& etm4_info) {
SetTypeAndMisc(PERF_RECORD_AUXTRACE_INFO, 0);
-
- uint32_t size = header_size() + sizeof(DataType);
- for (auto& ete : ete_info) {
- size += (ete.trcdevarch == 0) ? sizeof(ETM4Info) : sizeof(ETEInfo);
- }
- SetSize(size);
- char* new_binary = new char[size];
+ SetSize(header_size() + sizeof(DataType) + sizeof(ETM4Info) * etm4_info.size());
+ char* new_binary = new char[size()];
char* p = new_binary;
MoveToBinaryFormat(header, p);
this->data = reinterpret_cast<DataType*>(p);
MoveToBinaryFormat(data, p);
- for (auto& ete : ete_info) {
- if (ete.trcdevarch == 0) {
- ETM4Info etm4;
- static_assert(sizeof(ETM4Info) + sizeof(uint64_t) == sizeof(ETEInfo));
- memcpy(&etm4, &ete, sizeof(ETM4Info));
- MoveToBinaryFormat(etm4, p);
- } else {
- MoveToBinaryFormat(ete, p);
- }
+ for (auto& etm4 : etm4_info) {
+ MoveToBinaryFormat(etm4, p);
}
UpdateBinary(new_binary);
}
@@ -1131,49 +954,26 @@ void AuxTraceInfoRecord::DumpData(size_t indent) const {
PrintIndented(indent, "pmu_type %u\n", data->pmu_type);
PrintIndented(indent, "snapshot %" PRIu64 "\n", data->snapshot);
indent++;
- uint64_t* info = data->info;
-
for (int i = 0; i < data->nr_cpu; i++) {
- if (info[0] == MAGIC_ETM4) {
- ETM4Info& e = *reinterpret_cast<ETM4Info*>(info);
- PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic);
- PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu);
- PrintIndented(indent, "nrtrcparams %" PRIu64 "\n", e.nrtrcparams);
- PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr);
- PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr);
- PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0);
- PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1);
- PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2);
- PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8);
- PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus);
- info = reinterpret_cast<uint64_t*>(&e + 1);
- } else {
- CHECK_EQ(info[0], MAGIC_ETE);
- ETEInfo& e = *reinterpret_cast<ETEInfo*>(info);
- PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic);
- PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu);
- PrintIndented(indent, "nrtrcparams %" PRIu64 "\n", e.nrtrcparams);
- PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr);
- PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr);
- PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0);
- PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1);
- PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2);
- PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8);
- PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus);
- PrintIndented(indent, "trcdevarch 0x%" PRIx64 "\n", e.trcdevarch);
- info = reinterpret_cast<uint64_t*>(&e + 1);
- }
- }
-}
-
-bool AuxTraceRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+ const ETM4Info& e = data->etm4_info[i];
+ PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic);
+ PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu);
+ PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr);
+ PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr);
+ PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0);
+ PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1);
+ PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2);
+ PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8);
+ PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus);
+ }
+}
+
+AuxTraceRecord::AuxTraceRecord(char* p) : Record(p) {
+ const char* end = p + header.size;
+ p += header_size();
data = reinterpret_cast<DataType*>(p);
- CHECK_SIZE(p, end, sizeof(*data));
- p += sizeof(*data);
- return p == end;
+ p += sizeof(DataType);
+ CHECK_EQ(p, end);
}
AuxTraceRecord::AuxTraceRecord(uint64_t aux_size, uint64_t offset, uint32_t idx, uint32_t tid,
@@ -1203,17 +1003,13 @@ void AuxTraceRecord::DumpData(size_t indent) const {
PrintIndented(indent, "location.file_offset %" PRIu64 "\n", location.file_offset);
}
-bool KernelSymbolRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE(p, end, sizeof(uint32_t));
+KernelSymbolRecord::KernelSymbolRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(kallsyms_size, p);
- size_t size = Align(kallsyms_size, 8);
- CHECK_SIZE(p, end, size);
kallsyms = p;
- p += size;
- return p == end;
+ p += Align(kallsyms_size, 8);
+ CHECK_EQ(p, end);
}
void KernelSymbolRecord::DumpData(size_t indent) const {
@@ -1233,18 +1029,15 @@ KernelSymbolRecord::KernelSymbolRecord(const std::string& kallsyms) {
UpdateBinary(new_binary);
}
-bool DsoRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 3);
+DsoRecord::DsoRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(dso_type, p);
MoveFromBinaryFormat(dso_id, p);
MoveFromBinaryFormat(min_vaddr, p);
- size_t size = Align(SafeStrlen(p, end) + 1, 8);
dso_name = p;
- p += size;
- return p == end;
+ p += Align(strlen(dso_name) + 1, 8);
+ CHECK_EQ(p, end);
}
DsoRecord::DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
@@ -1273,18 +1066,15 @@ void DsoRecord::DumpData(size_t indent) const {
PrintIndented(indent, "dso_name: %s\n", dso_name);
}
-bool SymbolRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 3);
+SymbolRecord::SymbolRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(addr, p);
MoveFromBinaryFormat(len, p);
MoveFromBinaryFormat(dso_id, p);
- size_t size = Align(SafeStrlen(p, end) + 1, 8);
name = p;
- p += size;
- return p == end;
+ p += Align(strlen(name) + 1, 8);
+ CHECK_EQ(p, end);
}
SymbolRecord::SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, uint64_t dso_id) {
@@ -1311,17 +1101,13 @@ void SymbolRecord::DumpData(size_t indent) const {
PrintIndented(indent, "dso_id: %" PRIu64 "\n", dso_id);
}
-bool TracingDataRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE(p, end, sizeof(uint32_t));
+TracingDataRecord::TracingDataRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(data_size, p);
- size_t size = Align(data_size, 64);
- CHECK_SIZE(p, end, size);
data = p;
- p += size;
- return p == end;
+ p += Align(data_size, 64);
+ CHECK_EQ(p, end);
}
TracingDataRecord::TracingDataRecord(const std::vector<char>& tracing_data) {
@@ -1342,16 +1128,13 @@ void TracingDataRecord::DumpData(size_t indent) const {
tracing.Dump(indent);
}
-bool EventIdRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 1);
+EventIdRecord::EventIdRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(count, p);
data = reinterpret_cast<const EventIdData*>(p);
- CHECK_SIZE(p, end, sizeof(data[0]) * count);
p += sizeof(data[0]) * count;
- return p == end;
+ CHECK_EQ(p, end);
}
EventIdRecord::EventIdRecord(const std::vector<uint64_t>& data) {
@@ -1375,22 +1158,19 @@ void EventIdRecord::DumpData(size_t indent) const {
}
}
-bool CallChainRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 4);
+CallChainRecord::CallChainRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(pid, p);
MoveFromBinaryFormat(tid, p);
MoveFromBinaryFormat(chain_type, p);
MoveFromBinaryFormat(time, p);
MoveFromBinaryFormat(ip_nr, p);
- CHECK_SIZE_U64(p, end, ip_nr * 2);
ips = reinterpret_cast<uint64_t*>(p);
p += ip_nr * sizeof(uint64_t);
sps = reinterpret_cast<uint64_t*>(p);
p += ip_nr * sizeof(uint64_t);
- return p == end;
+ CHECK_EQ(p, end);
}
CallChainRecord::CallChainRecord(pid_t pid, pid_t tid, CallChainJoiner::ChainType type,
@@ -1445,11 +1225,9 @@ void CallChainRecord::DumpData(size_t indent) const {
}
}
-bool UnwindingResultRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
- CHECK_SIZE_U64(p, end, 8);
+UnwindingResultRecord::UnwindingResultRecord(char* p) : Record(p) {
+ const char* end = p + size();
+ p += header_size();
MoveFromBinaryFormat(time, p);
MoveFromBinaryFormat(unwinding_result.used_time, p);
MoveFromBinaryFormat(unwinding_result.error_code, p);
@@ -1461,18 +1239,15 @@ bool UnwindingResultRecord::Parse(const perf_event_attr&, char* p, char* end) {
MoveFromBinaryFormat(regs_user_data.abi, p);
MoveFromBinaryFormat(regs_user_data.reg_mask, p);
size_t bit_nr = __builtin_popcountll(regs_user_data.reg_mask);
- CHECK_SIZE_U64(p, end, bit_nr);
regs_user_data.reg_nr = bit_nr;
regs_user_data.regs = reinterpret_cast<uint64_t*>(p);
p += bit_nr * sizeof(uint64_t);
// stack_user_data
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(stack_user_data.size, p);
if (stack_user_data.size == 0) {
stack_user_data.dyn_size = 0;
} else {
- CHECK_SIZE(p, end, stack_user_data.size + sizeof(uint64_t));
stack_user_data.data = p;
p += stack_user_data.size;
MoveFromBinaryFormat(stack_user_data.dyn_size, p);
@@ -1480,15 +1255,13 @@ bool UnwindingResultRecord::Parse(const perf_event_attr&, char* p, char* end) {
// callchain
if (p < end) {
- CHECK_SIZE_U64(p, end, 1);
MoveFromBinaryFormat(callchain.length, p);
- CHECK_SIZE_U64(p, end, callchain.length * 2);
callchain.ips = reinterpret_cast<uint64_t*>(p);
p += callchain.length * sizeof(uint64_t);
callchain.sps = reinterpret_cast<uint64_t*>(p);
p += callchain.length * sizeof(uint64_t);
}
- return true;
+ CHECK_LE(p, end);
}
UnwindingResultRecord::UnwindingResultRecord(uint64_t time, const UnwindingResult& unwinding_result,
@@ -1573,89 +1346,65 @@ void UnwindingResultRecord::DumpData(size_t indent) const {
}
}
-bool UnknownRecord::Parse(const perf_event_attr&, char* p, char* end) {
- if (!ParseHeader(p, end)) {
- return false;
- }
+UnknownRecord::UnknownRecord(char* p) : Record(p) {
+ p += header_size();
data = p;
- return true;
}
void UnknownRecord::DumpData(size_t) const {}
-std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p,
- char* end) {
- std::unique_ptr<Record> r;
+std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p) {
switch (type) {
case PERF_RECORD_MMAP:
- r.reset(new MmapRecord);
- break;
+ return std::unique_ptr<Record>(new MmapRecord(attr, p));
case PERF_RECORD_MMAP2:
- r.reset(new Mmap2Record);
- break;
+ return std::unique_ptr<Record>(new Mmap2Record(attr, p));
case PERF_RECORD_COMM:
- r.reset(new CommRecord);
- break;
+ return std::unique_ptr<Record>(new CommRecord(attr, p));
case PERF_RECORD_EXIT:
- r.reset(new ExitRecord);
- break;
+ return std::unique_ptr<Record>(new ExitRecord(attr, p));
case PERF_RECORD_FORK:
- r.reset(new ForkRecord);
- break;
+ return std::unique_ptr<Record>(new ForkRecord(attr, p));
case PERF_RECORD_LOST:
- r.reset(new LostRecord);
- break;
+ return std::unique_ptr<Record>(new LostRecord(attr, p));
case PERF_RECORD_SAMPLE:
- r.reset(new SampleRecord);
- break;
+ return std::unique_ptr<Record>(new SampleRecord(attr, p));
case PERF_RECORD_AUX:
- r.reset(new AuxRecord);
- break;
- case PERF_RECORD_SWITCH:
- r.reset(new SwitchRecord);
- break;
- case PERF_RECORD_SWITCH_CPU_WIDE:
- r.reset(new SwitchCpuWideRecord);
- break;
+ return std::unique_ptr<Record>(new AuxRecord(attr, p));
case PERF_RECORD_TRACING_DATA:
- r.reset(new TracingDataRecord);
- break;
+ return std::unique_ptr<Record>(new TracingDataRecord(p));
case PERF_RECORD_AUXTRACE_INFO:
- r.reset(new AuxTraceInfoRecord);
- break;
+ return std::unique_ptr<Record>(new AuxTraceInfoRecord(p));
case PERF_RECORD_AUXTRACE:
- r.reset(new AuxTraceRecord);
- break;
+ return std::unique_ptr<Record>(new AuxTraceRecord(p));
case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- r.reset(new KernelSymbolRecord);
- break;
+ return std::unique_ptr<Record>(new KernelSymbolRecord(p));
case SIMPLE_PERF_RECORD_DSO:
- r.reset(new DsoRecord);
- break;
+ return std::unique_ptr<Record>(new DsoRecord(p));
case SIMPLE_PERF_RECORD_SYMBOL:
- r.reset(new SymbolRecord);
- break;
+ return std::unique_ptr<Record>(new SymbolRecord(p));
case SIMPLE_PERF_RECORD_EVENT_ID:
- r.reset(new EventIdRecord);
- break;
+ return std::unique_ptr<Record>(new EventIdRecord(p));
case SIMPLE_PERF_RECORD_CALLCHAIN:
- r.reset(new CallChainRecord);
- break;
+ return std::unique_ptr<Record>(new CallChainRecord(p));
case SIMPLE_PERF_RECORD_UNWINDING_RESULT:
- r.reset(new UnwindingResultRecord);
- break;
+ return std::unique_ptr<Record>(new UnwindingResultRecord(p));
case SIMPLE_PERF_RECORD_TRACING_DATA:
- r.reset(new TracingDataRecord);
- break;
+ return std::unique_ptr<Record>(new TracingDataRecord(p));
default:
- r.reset(new UnknownRecord);
- break;
+ return std::unique_ptr<Record>(new UnknownRecord(p));
}
- if (UNLIKELY(!r->Parse(attr, p, end))) {
- LOG(ERROR) << "failed to parse record " << RecordTypeToString(type);
- return nullptr;
+}
+
+std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr, uint32_t type,
+ char* p) {
+ std::unique_ptr<Record> record = ReadRecordFromBuffer(attr, type, p);
+ if (record != nullptr) {
+ record->OwnBinary();
+ } else {
+ delete[] p;
}
- return r;
+ return record;
}
std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr, char* buf,
@@ -1664,19 +1413,18 @@ std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr
char* p = buf;
char* end = buf + buf_size;
while (p < end) {
- std::unique_ptr<Record> r = ReadRecordFromBuffer(attr, p, end);
- if (!r) {
- return {};
- }
- p += r->size();
- result.emplace_back(std::move(r));
+ RecordHeader header(p);
+ CHECK_LE(p + header.size, end);
+ CHECK_NE(0u, header.size);
+ result.push_back(ReadRecordFromBuffer(attr, header.type, p));
+ p += header.size;
}
return result;
}
-std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p, char* end) {
+std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p) {
auto header = reinterpret_cast<const perf_event_header*>(p);
- return ReadRecordFromBuffer(attr, header->type, p, end);
+ return ReadRecordFromBuffer(attr, header->type, p);
}
} // namespace simpleperf