blob: 024c67bd2f1ac409656cb3fe4213185c9e2e048c [file] [log] [blame]
Yabin Cui9759e1b2015-04-28 15:54:13 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SIMPLE_PERF_RECORD_H_
18#define SIMPLE_PERF_RECORD_H_
19
Yabin Cuib7f481f2015-10-23 19:48:42 -070020#include <stdio.h>
Dan Albert918e4b72015-08-11 15:59:43 -070021#include <sys/types.h>
22
Yabin Cuiffaa9122016-01-15 15:25:48 -080023#include <memory>
Yabin Cuif469c3d2015-10-07 15:00:46 -070024#include <queue>
Yabin Cui9759e1b2015-04-28 15:54:13 -070025#include <string>
26#include <vector>
27
Yabin Cuib4212972016-05-25 14:08:05 -070028#include <android-base/logging.h>
29
Yabin Cui8f622512015-05-05 19:58:07 -070030#include "build_id.h"
Yabin Cui9759e1b2015-04-28 15:54:13 -070031#include "perf_event.h"
32
33struct KernelMmap;
34struct ModuleMmap;
35struct ThreadComm;
36struct ThreadMmap;
37
38enum user_record_type {
Yabin Cuib4212972016-05-25 14:08:05 -070039 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
Yabin Cui9759e1b2015-04-28 15:54:13 -070040 PERF_RECORD_ATTR = 64,
41 PERF_RECORD_EVENT_TYPE,
42 PERF_RECORD_TRACING_DATA,
43 PERF_RECORD_BUILD_ID,
44 PERF_RECORD_FINISHED_ROUND,
Yabin Cuib4212972016-05-25 14:08:05 -070045
46 SIMPLE_PERF_RECORD_TYPE_START = 32768,
47 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
Yabin Cui767dd172016-06-02 21:02:43 -070048 SIMPLE_PERF_RECORD_DSO,
49 SIMPLE_PERF_RECORD_SYMBOL,
Yabin Cui1761a272016-06-23 17:11:14 -070050 SIMPLE_PERF_RECORD_SPLIT,
51 SIMPLE_PERF_RECORD_SPLIT_END,
Yabin Cui9759e1b2015-04-28 15:54:13 -070052};
53
Yabin Cui1761a272016-06-23 17:11:14 -070054// perf_event_header uses u16 to store record size. However, that is not
55// enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
56// a simpleperf_record_header struct to store record header for simpleperf
57// defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
58struct simpleperf_record_header {
59 uint32_t type;
60 uint16_t size1;
61 uint16_t size0;
62};
63
64static_assert(
65 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
66 "simpleperf_record_header should have the same size as perf_event_header");
67
Yabin Cui9759e1b2015-04-28 15:54:13 -070068struct PerfSampleIpType {
69 uint64_t ip;
70};
71
72struct PerfSampleTidType {
73 uint32_t pid, tid;
74};
75
76struct PerfSampleTimeType {
77 uint64_t time;
78};
79
80struct PerfSampleAddrType {
81 uint64_t addr;
82};
83
84struct PerfSampleIdType {
85 uint64_t id;
86};
87
88struct PerfSampleStreamIdType {
89 uint64_t stream_id;
90};
91
92struct PerfSampleCpuType {
93 uint32_t cpu, res;
94};
95
96struct PerfSamplePeriodType {
97 uint64_t period;
98};
99
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700100struct PerfSampleCallChainType {
101 std::vector<uint64_t> ips;
102};
103
Yabin Cuibfc11b62015-08-19 10:12:51 -0700104struct PerfSampleRawType {
105 std::vector<char> data;
106};
107
Yabin Cuib64a8632016-05-24 18:23:33 -0700108struct BranchStackItemType {
109 uint64_t from;
110 uint64_t to;
111 uint64_t flags;
112};
113
Yabin Cuiddddc062015-06-02 17:54:52 -0700114struct PerfSampleBranchStackType {
Yabin Cuiddddc062015-06-02 17:54:52 -0700115 std::vector<BranchStackItemType> stack;
116};
117
Yabin Cui76769e52015-07-13 12:23:54 -0700118struct PerfSampleRegsUserType {
119 uint64_t abi;
120 uint64_t reg_mask;
121 std::vector<uint64_t> regs;
122};
123
124struct PerfSampleStackUserType {
125 std::vector<char> data;
126 uint64_t dyn_size;
127};
128
Yabin Cui1761a272016-06-23 17:11:14 -0700129struct RecordHeader {
130 public:
131 uint32_t type;
132 uint16_t misc;
133 uint32_t size;
134
135 RecordHeader() : type(0), misc(0), size(0) {}
136
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700137 explicit RecordHeader(const char* p) {
Yabin Cui1761a272016-06-23 17:11:14 -0700138 auto pheader = reinterpret_cast<const perf_event_header*>(p);
139 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
140 type = pheader->type;
141 misc = pheader->misc;
142 size = pheader->size;
143 } else {
144 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
145 type = sheader->type;
146 misc = 0;
147 size = (sheader->size1 << 16) | sheader->size0;
148 }
149 }
150
151 void MoveToBinaryFormat(char*& p) const {
152 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
153 auto pheader = reinterpret_cast<perf_event_header*>(p);
154 pheader->type = type;
155 pheader->misc = misc;
156 CHECK_LT(size, 1u << 16);
157 pheader->size = static_cast<uint16_t>(size);
158 } else {
159 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
160 sheader->type = type;
161 CHECK_EQ(misc, 0u);
162 sheader->size1 = size >> 16;
163 sheader->size0 = size & 0xffff;
164 }
165 p += sizeof(perf_event_header);
166 }
167};
168
Yabin Cui767dd172016-06-02 21:02:43 -0700169// SampleId is optional at the end of a record in binary format. Its content is
170// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
171// complexity of referring to perf_event_attr each time, we copy sample_id_all
172// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700173struct SampleId {
174 bool sample_id_all;
175 uint64_t sample_type;
176
Yabin Cui767dd172016-06-02 21:02:43 -0700177 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
178 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
179 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
180 PerfSampleStreamIdType
181 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
182 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700183
184 SampleId();
185
186 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700187 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700188
189 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700190 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
191 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700192
193 // Write the binary format of sample_id to the buffer pointed by p.
194 void WriteToBinaryFormat(char*& p) const;
195 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800196 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700197};
198
Yabin Cui767dd172016-06-02 21:02:43 -0700199// Usually one record contains the following three parts in order in binary
200// format:
Yabin Cui1761a272016-06-23 17:11:14 -0700201// RecordHeader (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700202// data depends on the record type
Yabin Cui1761a272016-06-23 17:11:14 -0700203// SampleId (optional part at the end of a record)
204// We hold the common parts (RecordHeader and SampleId) in the base class
Yabin Cui767dd172016-06-02 21:02:43 -0700205// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700206struct Record {
Yabin Cui1761a272016-06-23 17:11:14 -0700207 RecordHeader header;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700208 SampleId sample_id;
209
Yabin Cui1761a272016-06-23 17:11:14 -0700210 Record() {}
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700211 explicit Record(const char* p) : header(p) {}
Yabin Cui9759e1b2015-04-28 15:54:13 -0700212
Yabin Cui767dd172016-06-02 21:02:43 -0700213 virtual ~Record() {}
Yabin Cuib7f481f2015-10-23 19:48:42 -0700214
Yabin Cui767dd172016-06-02 21:02:43 -0700215 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700216
Yabin Cui767dd172016-06-02 21:02:43 -0700217 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700218
Yabin Cui1761a272016-06-23 17:11:14 -0700219 uint32_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700220
Yabin Cui767dd172016-06-02 21:02:43 -0700221 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700222
Yabin Cuib64a8632016-05-24 18:23:33 -0700223 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700224 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
225 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700226 }
227
Yabin Cuib4212972016-05-25 14:08:05 -0700228 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
229 header.type = type;
230 header.misc = misc;
231 }
232
Yabin Cui1761a272016-06-23 17:11:14 -0700233 void SetSize(uint32_t size) { header.size = size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700234
Yabin Cui9759e1b2015-04-28 15:54:13 -0700235 void Dump(size_t indent = 0) const;
Yabin Cuicb84c982015-09-30 17:22:35 -0700236 virtual std::vector<char> BinaryFormat() const = 0;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700237 virtual uint64_t Timestamp() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700238
239 protected:
Yabin Cuicb84c982015-09-30 17:22:35 -0700240 virtual void DumpData(size_t) const = 0;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700241};
242
243struct MmapRecord : public Record {
244 struct MmapRecordDataType {
245 uint32_t pid, tid;
246 uint64_t addr;
247 uint64_t len;
248 uint64_t pgoff;
249 } data;
250 std::string filename;
251
Yabin Cuicb84c982015-09-30 17:22:35 -0700252 MmapRecord() { // For CreateMmapRecord.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700253 }
254
Yabin Cui1761a272016-06-23 17:11:14 -0700255 MmapRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700256 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800257 void AdjustSizeBasedOnData();
Yabin Cui8f622512015-05-05 19:58:07 -0700258
Yabin Cui767dd172016-06-02 21:02:43 -0700259 static MmapRecord Create(const perf_event_attr& attr, bool in_kernel,
260 uint32_t pid, uint32_t tid, uint64_t addr,
261 uint64_t len, uint64_t pgoff,
262 const std::string& filename, uint64_t event_id);
263
Yabin Cui8f622512015-05-05 19:58:07 -0700264 protected:
265 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700266};
267
Yabin Cui41d4ba92015-06-22 12:27:58 -0700268struct Mmap2Record : public Record {
269 struct Mmap2RecordDataType {
270 uint32_t pid, tid;
271 uint64_t addr;
272 uint64_t len;
273 uint64_t pgoff;
274 uint32_t maj;
275 uint32_t min;
276 uint64_t ino;
277 uint64_t ino_generation;
278 uint32_t prot, flags;
279 } data;
280 std::string filename;
281
Yabin Cui767dd172016-06-02 21:02:43 -0700282 Mmap2Record() {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700283
Yabin Cui1761a272016-06-23 17:11:14 -0700284 Mmap2Record(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700285 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800286 void AdjustSizeBasedOnData();
Yabin Cui41d4ba92015-06-22 12:27:58 -0700287
288 protected:
289 void DumpData(size_t indent) const override;
290};
291
Yabin Cui9759e1b2015-04-28 15:54:13 -0700292struct CommRecord : public Record {
293 struct CommRecordDataType {
294 uint32_t pid, tid;
295 } data;
296 std::string comm;
297
Yabin Cui767dd172016-06-02 21:02:43 -0700298 CommRecord() {}
Yabin Cui9759e1b2015-04-28 15:54:13 -0700299
Yabin Cui1761a272016-06-23 17:11:14 -0700300 CommRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700301 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700302
Yabin Cui767dd172016-06-02 21:02:43 -0700303 static CommRecord Create(const perf_event_attr& attr, uint32_t pid,
304 uint32_t tid, const std::string& comm,
305 uint64_t event_id);
306
Yabin Cui8f622512015-05-05 19:58:07 -0700307 protected:
308 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700309};
310
Yabin Cui41d4ba92015-06-22 12:27:58 -0700311struct ExitOrForkRecord : public Record {
312 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700313 uint32_t pid, ppid;
314 uint32_t tid, ptid;
315 uint64_t time;
316 } data;
317
Yabin Cui767dd172016-06-02 21:02:43 -0700318 ExitOrForkRecord() {}
Yabin Cui1761a272016-06-23 17:11:14 -0700319 ExitOrForkRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700320 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700321
322 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700323 void DumpData(size_t indent) const override;
324};
325
Yabin Cui41d4ba92015-06-22 12:27:58 -0700326struct ExitRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700327 ExitRecord(const perf_event_attr& attr, const char* p)
328 : ExitOrForkRecord(attr, p) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700329};
330
331struct ForkRecord : public ExitOrForkRecord {
Yabin Cui767dd172016-06-02 21:02:43 -0700332 ForkRecord() {}
Yabin Cui1761a272016-06-23 17:11:14 -0700333 ForkRecord(const perf_event_attr& attr, const char* p)
334 : ExitOrForkRecord(attr, p) {}
Yabin Cui767dd172016-06-02 21:02:43 -0700335
336 static ForkRecord Create(const perf_event_attr& attr, uint32_t pid,
337 uint32_t tid, uint32_t ppid, uint32_t ptid,
338 uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700339};
340
Yabin Cuie5adc132016-06-22 11:37:26 -0700341struct LostRecord : public Record {
342 uint64_t id;
343 uint64_t lost;
344
Yabin Cui1761a272016-06-23 17:11:14 -0700345 LostRecord() {}
Yabin Cuie5adc132016-06-22 11:37:26 -0700346
Yabin Cui1761a272016-06-23 17:11:14 -0700347 LostRecord(const perf_event_attr& attr, const char* p);
Yabin Cuie5adc132016-06-22 11:37:26 -0700348 std::vector<char> BinaryFormat() const override;
349
350 protected:
351 void DumpData(size_t indent) const override;
352};
353
Yabin Cui9759e1b2015-04-28 15:54:13 -0700354struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700355 uint64_t sample_type; // sample_type is a bit mask determining which fields
356 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700357
358 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
359 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
360 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
361 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
362 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
363 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
364 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
365 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
366
Yabin Cui767dd172016-06-02 21:02:43 -0700367 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
368 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
369 PerfSampleBranchStackType
370 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
371 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
372 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700373
Yabin Cui1761a272016-06-23 17:11:14 -0700374 SampleRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700375 std::vector<char> BinaryFormat() const override;
376 void AdjustSizeBasedOnData();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700377 uint64_t Timestamp() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700378
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700379 uint64_t GetValidStackSize() const {
380 // If stack_user_data.dyn_size == 0, it may be because the kernel misses
381 // the patch to update dyn_size, like in N9 (See b/22612370). So assume
382 // all stack data is valid if dyn_size == 0.
383 if (stack_user_data.dyn_size == 0) {
384 return stack_user_data.data.size();
385 }
386 return stack_user_data.dyn_size;
387 }
388
Yabin Cui8f622512015-05-05 19:58:07 -0700389 protected:
390 void DumpData(size_t indent) const override;
391};
392
Yabin Cui767dd172016-06-02 21:02:43 -0700393// BuildIdRecord is defined in user-space, stored in BuildId feature section in
394// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700395struct BuildIdRecord : public Record {
396 uint32_t pid;
397 BuildId build_id;
398 std::string filename;
399
Yabin Cui767dd172016-06-02 21:02:43 -0700400 BuildIdRecord() {}
Yabin Cui8f622512015-05-05 19:58:07 -0700401
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700402 explicit BuildIdRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700403 std::vector<char> BinaryFormat() const override;
404
Yabin Cui767dd172016-06-02 21:02:43 -0700405 static BuildIdRecord Create(bool in_kernel, pid_t pid,
406 const BuildId& build_id,
407 const std::string& filename);
408
Yabin Cuicb84c982015-09-30 17:22:35 -0700409 protected:
410 void DumpData(size_t indent) const override;
411};
412
Yabin Cuib4212972016-05-25 14:08:05 -0700413struct KernelSymbolRecord : public Record {
Yabin Cuib4212972016-05-25 14:08:05 -0700414 std::string kallsyms;
415
Yabin Cui767dd172016-06-02 21:02:43 -0700416 KernelSymbolRecord() {}
Yabin Cuib4212972016-05-25 14:08:05 -0700417
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700418 explicit KernelSymbolRecord(const char* p);
Yabin Cuib4212972016-05-25 14:08:05 -0700419 std::vector<char> BinaryFormat() const override;
420
Yabin Cui1761a272016-06-23 17:11:14 -0700421 static KernelSymbolRecord Create(std::string kallsyms);
Yabin Cui767dd172016-06-02 21:02:43 -0700422
Yabin Cuib4212972016-05-25 14:08:05 -0700423 protected:
424 void DumpData(size_t indent) const override;
425};
426
Yabin Cui767dd172016-06-02 21:02:43 -0700427struct DsoRecord : public Record {
428 uint64_t dso_type;
429 uint64_t dso_id;
Yabin Cuic855ecc2016-07-11 17:04:54 -0700430 uint64_t min_vaddr;
Yabin Cui767dd172016-06-02 21:02:43 -0700431 std::string dso_name;
432
433 DsoRecord() {}
434
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700435 explicit DsoRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700436 std::vector<char> BinaryFormat() const override;
437
438 static DsoRecord Create(uint64_t dso_type, uint64_t dso_id,
Yabin Cuic855ecc2016-07-11 17:04:54 -0700439 const std::string& dso_name, uint64_t min_vaddr);
Yabin Cui767dd172016-06-02 21:02:43 -0700440
441 protected:
442 void DumpData(size_t indent) const override;
443};
444
445struct SymbolRecord : public Record {
446 uint64_t addr;
447 uint64_t len;
448 uint64_t dso_id;
449 std::string name;
450
451 SymbolRecord() {}
452
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700453 explicit SymbolRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700454 std::vector<char> BinaryFormat() const override;
455
456 static SymbolRecord Create(uint64_t addr, uint64_t len,
457 const std::string& name, uint64_t dso_id);
Yabin Cui1761a272016-06-23 17:11:14 -0700458
Yabin Cui4f41df62016-06-01 17:29:06 -0700459 protected:
460 void DumpData(size_t indent) const override;
461};
Yabin Cui767dd172016-06-02 21:02:43 -0700462
Yabin Cui4f41df62016-06-01 17:29:06 -0700463struct TracingDataRecord : public Record {
464 std::vector<char> data;
465
Yabin Cui1761a272016-06-23 17:11:14 -0700466 TracingDataRecord() {}
Yabin Cui4f41df62016-06-01 17:29:06 -0700467
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700468 explicit TracingDataRecord(const char* p);
Yabin Cui4f41df62016-06-01 17:29:06 -0700469 std::vector<char> BinaryFormat() const override;
470
471 static TracingDataRecord Create(std::vector<char> tracing_data);
Yabin Cuie5adc132016-06-22 11:37:26 -0700472
Yabin Cui767dd172016-06-02 21:02:43 -0700473 protected:
474 void DumpData(size_t indent) const override;
475};
476
477// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700478// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700479struct UnknownRecord : public Record {
480 std::vector<char> data;
481
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700482 explicit UnknownRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700483 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700484
485 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700486 void DumpData(size_t indent) const override;
487};
488
Yabin Cui767dd172016-06-02 21:02:43 -0700489std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
Yabin Cui1761a272016-06-23 17:11:14 -0700490 uint32_t type, const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700491std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
492 const perf_event_attr& attr, const char* buf, size_t buf_size);
493
Yabin Cuif469c3d2015-10-07 15:00:46 -0700494// RecordCache is a cache used when receiving records from the kernel.
495// It sorts received records based on type and timestamp, and pops records
496// in sorted order. Records from the kernel need to be sorted because
497// records may come from different cpus at the same time, and it is affected
498// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700499// RecordCache pushes records and pops sorted record online. It uses two checks
500// to help ensure that records are popped in order. Each time we pop a record A,
501// it is the earliest record among all records in the cache. In addition, we
502// have checks for min_cache_size and min_time_diff. For min_cache_size check,
503// we check if the cache size >= min_cache_size, which is based on the
504// assumption that if we have received (min_cache_size - 1) records after
505// record A, we are not likely to receive a record earlier than A. For
506// min_time_diff check, we check if record A is generated min_time_diff ns
507// earlier than the latest record, which is based on the assumption that if we
508// have received a record for time t, we are not likely to receive a record for
509// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700510class RecordCache {
511 public:
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700512 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700513 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700514 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700515 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700516 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700517 std::unique_ptr<Record> Pop();
518 std::vector<std::unique_ptr<Record>> PopAll();
519
520 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800521 struct RecordWithSeq {
522 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700523 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800524
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700525 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
Yabin Cui4913c122016-01-11 17:15:55 -0800526 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700527 };
528
Yabin Cui4913c122016-01-11 17:15:55 -0800529 struct RecordComparator {
530 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
531 };
532
Yabin Cuif469c3d2015-10-07 15:00:46 -0700533 bool has_timestamp_;
534 size_t min_cache_size_;
535 uint64_t min_time_diff_in_ns_;
536 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800537 uint32_t cur_seq_;
538 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700539 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700540};
541
Yabin Cui9759e1b2015-04-28 15:54:13 -0700542#endif // SIMPLE_PERF_RECORD_H_