summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2023-11-21 22:38:38 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-11-21 22:38:38 +0000
commit2950b98ad47892a16092ae11ab809b4e3b3b4aef (patch)
tree4d60e879b242bae80b2491a9205a1b6f0955c786
parentd59010441b866ec457a75be58ce3871da7e8b0b9 (diff)
parent5cc4e17654f6651aed599edf4ba1d62210f1e9be (diff)
downloadextras-2950b98ad47892a16092ae11ab809b4e3b3b4aef.tar.gz
Merge "simpleperf: Add DebugRecord" into main
-rw-r--r--simpleperf/record.cpp36
-rw-r--r--simpleperf/record.h17
-rw-r--r--simpleperf/record_equal_test.h29
-rw-r--r--simpleperf/record_test.cpp8
4 files changed, 78 insertions, 12 deletions
diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp
index 29e5d112..b9f03829 100644
--- a/simpleperf/record.cpp
+++ b/simpleperf/record.cpp
@@ -72,6 +72,7 @@ static std::string RecordTypeToString(int record_type) {
{SIMPLE_PERF_RECORD_CALLCHAIN, "callchain"},
{SIMPLE_PERF_RECORD_UNWINDING_RESULT, "unwinding_result"},
{SIMPLE_PERF_RECORD_TRACING_DATA, "tracing_data"},
+ {SIMPLE_PERF_RECORD_DEBUG, "debug"},
};
auto it = record_type_names.find(record_type);
@@ -1603,6 +1604,38 @@ void UnwindingResultRecord::DumpData(size_t indent) const {
}
}
+DebugRecord::DebugRecord(uint64_t time, const std::string& s) {
+ SetTypeAndMisc(SIMPLE_PERF_RECORD_DEBUG, 0);
+ uint32_t size = header_size() + sizeof(uint64_t) + Align(strlen(s.c_str()) + 1, sizeof(uint64_t));
+ SetSize(size);
+ char* new_binary = new char[size];
+ char* p = new_binary;
+ MoveToBinaryFormat(header, p);
+ MoveToBinaryFormat(time, p);
+ this->time = time;
+ this->s = p;
+ MoveToBinaryFormat(s.c_str(), strlen(s.c_str()) + 1, p);
+ CHECK_LE(p, new_binary + size);
+ UpdateBinary(new_binary);
+}
+
+bool DebugRecord::Parse(const perf_event_attr&, char* p, char* end) {
+ if (!ParseHeader(p, end)) {
+ return false;
+ }
+ CHECK_SIZE_U64(p, end, 1);
+ MoveFromBinaryFormat(time, p);
+ if (memchr(p, '\0', end - p) == nullptr) {
+ return false;
+ }
+ s = p;
+ return true;
+}
+
+void DebugRecord::DumpData(size_t indent) const {
+ PrintIndented(indent, "s %s\n", s);
+}
+
bool UnknownRecord::Parse(const perf_event_attr&, char* p, char* end) {
if (!ParseHeader(p, end)) {
return false;
@@ -1677,6 +1710,9 @@ std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32
case SIMPLE_PERF_RECORD_TRACING_DATA:
r.reset(new TracingDataRecord);
break;
+ case SIMPLE_PERF_RECORD_DEBUG:
+ r.reset(new DebugRecord);
+ break;
default:
r.reset(new UnknownRecord);
break;
diff --git a/simpleperf/record.h b/simpleperf/record.h
index 925eaaa0..92cc88c4 100644
--- a/simpleperf/record.h
+++ b/simpleperf/record.h
@@ -56,6 +56,7 @@ enum user_record_type {
SIMPLE_PERF_RECORD_CALLCHAIN,
SIMPLE_PERF_RECORD_UNWINDING_RESULT,
SIMPLE_PERF_RECORD_TRACING_DATA,
+ SIMPLE_PERF_RECORD_DEBUG,
};
// perf_event_header uses u16 to store record size. However, that is not
@@ -671,6 +672,22 @@ struct UnwindingResultRecord : public Record {
void DumpData(size_t indent) const override;
};
+// Add a debug string in the recording file.
+struct DebugRecord : public Record {
+ uint64_t time = 0;
+ char* s = nullptr;
+
+ DebugRecord() {}
+
+ DebugRecord(uint64_t time, const std::string& s);
+
+ bool Parse(const perf_event_attr& attr, char* p, char* end) override;
+ uint64_t Timestamp() const override { return time; }
+
+ protected:
+ void DumpData(size_t indent) const override;
+};
+
// UnknownRecord is used for unknown record types, it makes sure all unknown
// records are not changed when modifying perf.data.
struct UnknownRecord : public Record {
diff --git a/simpleperf/record_equal_test.h b/simpleperf/record_equal_test.h
index bd66415a..fce1a840 100644
--- a/simpleperf/record_equal_test.h
+++ b/simpleperf/record_equal_test.h
@@ -16,23 +16,28 @@
namespace simpleperf {
-static void CheckMmapRecordDataEqual(const MmapRecord& r1, const MmapRecord& r2) {
+static void CheckRecordDataEqual(const MmapRecord& r1, const MmapRecord& r2) {
ASSERT_EQ(0, memcmp(r1.data, r2.data, sizeof(*r1.data)));
ASSERT_STREQ(r1.filename, r2.filename);
}
-static void CheckCommRecordDataEqual(const CommRecord& r1, const CommRecord& r2) {
+static void CheckRecordDataEqual(const CommRecord& r1, const CommRecord& r2) {
ASSERT_EQ(0, memcmp(r1.data, r2.data, sizeof(*r1.data)));
ASSERT_STREQ(r1.comm, r2.comm);
}
-static void CheckBuildIdRecordDataEqual(const BuildIdRecord& r1, const BuildIdRecord& r2) {
+static void CheckRecordDataEqual(const BuildIdRecord& r1, const BuildIdRecord& r2) {
ASSERT_EQ(r1.pid, r2.pid);
ASSERT_EQ(r1.build_id, r2.build_id);
ASSERT_STREQ(r1.filename, r2.filename);
}
-static void CheckSampleRecordDataEqual(const SampleRecord& r1, const SampleRecord& r2) {
+static void CheckRecordDataEqual(const DebugRecord& r1, const DebugRecord& r2) {
+ ASSERT_EQ(r1.time, r2.time);
+ ASSERT_STREQ(r1.s, r2.s);
+}
+
+static void CheckRecordDataEqual(const SampleRecord& r1, const SampleRecord& r2) {
ASSERT_EQ(r1.sample_type, r2.sample_type);
ASSERT_EQ(r1.read_format, r2.read_format);
if (r1.sample_type & PERF_SAMPLE_IP) {
@@ -95,20 +100,20 @@ static void CheckRecordEqual(const Record& r1, const Record& r2) {
ASSERT_EQ(r1.misc(), r2.misc());
ASSERT_EQ(r1.size(), r2.size());
if (r1.type() == PERF_RECORD_SAMPLE) {
- CheckSampleRecordDataEqual(static_cast<const SampleRecord&>(r1),
- static_cast<const SampleRecord&>(r2));
+ CheckRecordDataEqual(static_cast<const SampleRecord&>(r1),
+ static_cast<const SampleRecord&>(r2));
return;
}
ASSERT_EQ(0, memcmp(&r1.sample_id, &r2.sample_id, sizeof(r1.sample_id)));
if (r1.type() == PERF_RECORD_MMAP) {
- CheckMmapRecordDataEqual(static_cast<const MmapRecord&>(r1),
- static_cast<const MmapRecord&>(r2));
+ CheckRecordDataEqual(static_cast<const MmapRecord&>(r1), static_cast<const MmapRecord&>(r2));
} else if (r1.type() == PERF_RECORD_COMM) {
- CheckCommRecordDataEqual(static_cast<const CommRecord&>(r1),
- static_cast<const CommRecord&>(r2));
+ CheckRecordDataEqual(static_cast<const CommRecord&>(r1), static_cast<const CommRecord&>(r2));
} else if (r1.type() == PERF_RECORD_BUILD_ID) {
- CheckBuildIdRecordDataEqual(static_cast<const BuildIdRecord&>(r1),
- static_cast<const BuildIdRecord&>(r2));
+ CheckRecordDataEqual(static_cast<const BuildIdRecord&>(r1),
+ static_cast<const BuildIdRecord&>(r2));
+ } else if (r1.type() == SIMPLE_PERF_RECORD_DEBUG) {
+ CheckRecordDataEqual(static_cast<const DebugRecord&>(r1), static_cast<const DebugRecord&>(r2));
}
}
diff --git a/simpleperf/record_test.cpp b/simpleperf/record_test.cpp
index 20c9c18a..bca0b7ff 100644
--- a/simpleperf/record_test.cpp
+++ b/simpleperf/record_test.cpp
@@ -193,3 +193,11 @@ TEST_F(RecordTest, CommRecord) {
ASSERT_EQ(r.sample_id.time_data.time, 4u);
CheckRecordMatchBinary(r);
}
+
+TEST_F(RecordTest, DebugRecord) {
+ DebugRecord r(1234, "hello");
+ ASSERT_EQ(r.size() % sizeof(uint64_t), 0);
+ ASSERT_EQ(r.Timestamp(), 1234);
+ ASSERT_STREQ(r.s, "hello");
+ CheckRecordMatchBinary(r);
+}