blob: abfc163f8218ac49092e7bd7cd39ed5af4fcf769 [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 {
Yabin Cui190a8482016-08-04 10:22:17 -0700101 uint64_t ip_nr;
102 const uint64_t* ips;
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700103};
104
Yabin Cuibfc11b62015-08-19 10:12:51 -0700105struct PerfSampleRawType {
Yabin Cui190a8482016-08-04 10:22:17 -0700106 uint32_t size;
107 const char* data;
Yabin Cuibfc11b62015-08-19 10:12:51 -0700108};
109
Yabin Cuib64a8632016-05-24 18:23:33 -0700110struct BranchStackItemType {
111 uint64_t from;
112 uint64_t to;
113 uint64_t flags;
114};
115
Yabin Cuiddddc062015-06-02 17:54:52 -0700116struct PerfSampleBranchStackType {
Yabin Cui190a8482016-08-04 10:22:17 -0700117 uint64_t stack_nr;
118 const BranchStackItemType* stack;
Yabin Cuiddddc062015-06-02 17:54:52 -0700119};
120
Yabin Cui76769e52015-07-13 12:23:54 -0700121struct PerfSampleRegsUserType {
122 uint64_t abi;
123 uint64_t reg_mask;
Yabin Cui190a8482016-08-04 10:22:17 -0700124 uint64_t reg_nr;
125 const uint64_t* regs;
Yabin Cui76769e52015-07-13 12:23:54 -0700126};
127
128struct PerfSampleStackUserType {
Yabin Cui190a8482016-08-04 10:22:17 -0700129 uint64_t size;
130 const char* data;
Yabin Cui76769e52015-07-13 12:23:54 -0700131 uint64_t dyn_size;
132};
133
Yabin Cui1761a272016-06-23 17:11:14 -0700134struct RecordHeader {
135 public:
136 uint32_t type;
137 uint16_t misc;
138 uint32_t size;
139
140 RecordHeader() : type(0), misc(0), size(0) {}
141
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700142 explicit RecordHeader(const char* p) {
Yabin Cui1761a272016-06-23 17:11:14 -0700143 auto pheader = reinterpret_cast<const perf_event_header*>(p);
144 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
145 type = pheader->type;
146 misc = pheader->misc;
147 size = pheader->size;
148 } else {
149 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
150 type = sheader->type;
151 misc = 0;
152 size = (sheader->size1 << 16) | sheader->size0;
153 }
154 }
155
156 void MoveToBinaryFormat(char*& p) const {
157 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
158 auto pheader = reinterpret_cast<perf_event_header*>(p);
159 pheader->type = type;
160 pheader->misc = misc;
161 CHECK_LT(size, 1u << 16);
162 pheader->size = static_cast<uint16_t>(size);
163 } else {
164 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
165 sheader->type = type;
166 CHECK_EQ(misc, 0u);
167 sheader->size1 = size >> 16;
168 sheader->size0 = size & 0xffff;
169 }
170 p += sizeof(perf_event_header);
171 }
172};
173
Yabin Cui767dd172016-06-02 21:02:43 -0700174// SampleId is optional at the end of a record in binary format. Its content is
175// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
176// complexity of referring to perf_event_attr each time, we copy sample_id_all
177// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700178struct SampleId {
179 bool sample_id_all;
180 uint64_t sample_type;
181
Yabin Cui767dd172016-06-02 21:02:43 -0700182 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
183 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
184 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
185 PerfSampleStreamIdType
186 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
187 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700188
189 SampleId();
190
191 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700192 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700193
194 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700195 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
196 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700197
198 // Write the binary format of sample_id to the buffer pointed by p.
199 void WriteToBinaryFormat(char*& p) const;
200 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800201 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700202};
203
Yabin Cui767dd172016-06-02 21:02:43 -0700204// Usually one record contains the following three parts in order in binary
205// format:
Yabin Cui1761a272016-06-23 17:11:14 -0700206// RecordHeader (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700207// data depends on the record type
Yabin Cui1761a272016-06-23 17:11:14 -0700208// SampleId (optional part at the end of a record)
209// We hold the common parts (RecordHeader and SampleId) in the base class
Yabin Cui767dd172016-06-02 21:02:43 -0700210// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700211struct Record {
Yabin Cui1761a272016-06-23 17:11:14 -0700212 RecordHeader header;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700213 SampleId sample_id;
214
Yabin Cui190a8482016-08-04 10:22:17 -0700215 Record() : binary_(nullptr), own_binary_(false) {}
216 explicit Record(const char* p) : header(p), binary_(p), own_binary_(false) {}
217 Record(Record&& other);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700218
Yabin Cui190a8482016-08-04 10:22:17 -0700219 virtual ~Record() {
220 if (own_binary_) {
221 delete[] binary_;
222 }
223 }
224
225 void OwnBinary() { own_binary_ = true; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700226
Yabin Cui767dd172016-06-02 21:02:43 -0700227 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700228
Yabin Cui767dd172016-06-02 21:02:43 -0700229 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700230
Yabin Cui1761a272016-06-23 17:11:14 -0700231 uint32_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700232
Yabin Cui767dd172016-06-02 21:02:43 -0700233 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700234
Yabin Cuib64a8632016-05-24 18:23:33 -0700235 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700236 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
237 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700238 }
239
Yabin Cuib4212972016-05-25 14:08:05 -0700240 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
241 header.type = type;
242 header.misc = misc;
243 }
244
Yabin Cui1761a272016-06-23 17:11:14 -0700245 void SetSize(uint32_t size) { header.size = size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700246
Yabin Cui9759e1b2015-04-28 15:54:13 -0700247 void Dump(size_t indent = 0) const;
Yabin Cui190a8482016-08-04 10:22:17 -0700248
249 const char* Binary() const { return binary_; }
250
Yabin Cuif469c3d2015-10-07 15:00:46 -0700251 virtual uint64_t Timestamp() const;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700252 virtual uint32_t Cpu() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700253
254 protected:
Yabin Cui190a8482016-08-04 10:22:17 -0700255 void UpdateBinary(const char* new_binary);
Yabin Cuicb84c982015-09-30 17:22:35 -0700256 virtual void DumpData(size_t) const = 0;
Yabin Cui190a8482016-08-04 10:22:17 -0700257
258 const char* binary_;
259 bool own_binary_;
260
261 DISALLOW_COPY_AND_ASSIGN(Record);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700262};
263
264struct MmapRecord : public Record {
265 struct MmapRecordDataType {
266 uint32_t pid, tid;
267 uint64_t addr;
268 uint64_t len;
269 uint64_t pgoff;
Yabin Cui190a8482016-08-04 10:22:17 -0700270 };
271 const MmapRecordDataType* data;
272 const char* filename;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700273
Yabin Cui1761a272016-06-23 17:11:14 -0700274 MmapRecord(const perf_event_attr& attr, const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700275
Yabin Cui190a8482016-08-04 10:22:17 -0700276 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
277 uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
278 const std::string& filename, uint64_t event_id, uint64_t time = 0);
279
280 void SetDataAndFilename(const MmapRecordDataType& data,
281 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700282
Yabin Cui8f622512015-05-05 19:58:07 -0700283 protected:
284 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700285};
286
Yabin Cui41d4ba92015-06-22 12:27:58 -0700287struct Mmap2Record : public Record {
288 struct Mmap2RecordDataType {
289 uint32_t pid, tid;
290 uint64_t addr;
291 uint64_t len;
292 uint64_t pgoff;
293 uint32_t maj;
294 uint32_t min;
295 uint64_t ino;
296 uint64_t ino_generation;
297 uint32_t prot, flags;
Yabin Cui190a8482016-08-04 10:22:17 -0700298 };
299 const Mmap2RecordDataType* data;
300 const char* filename;
Yabin Cui41d4ba92015-06-22 12:27:58 -0700301
Yabin Cui1761a272016-06-23 17:11:14 -0700302 Mmap2Record(const perf_event_attr& attr, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700303
304 void SetDataAndFilename(const Mmap2RecordDataType& data,
305 const std::string& filename);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700306
307 protected:
308 void DumpData(size_t indent) const override;
309};
310
Yabin Cui9759e1b2015-04-28 15:54:13 -0700311struct CommRecord : public Record {
312 struct CommRecordDataType {
313 uint32_t pid, tid;
Yabin Cui190a8482016-08-04 10:22:17 -0700314 };
315 const CommRecordDataType* data;
316 const char* comm;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700317
Yabin Cui1761a272016-06-23 17:11:14 -0700318 CommRecord(const perf_event_attr& attr, const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700319
Yabin Cui190a8482016-08-04 10:22:17 -0700320 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
321 const std::string& comm, uint64_t event_id);
Yabin Cui767dd172016-06-02 21:02:43 -0700322
Yabin Cui8f622512015-05-05 19:58:07 -0700323 protected:
324 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700325};
326
Yabin Cui41d4ba92015-06-22 12:27:58 -0700327struct ExitOrForkRecord : public Record {
328 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700329 uint32_t pid, ppid;
330 uint32_t tid, ptid;
331 uint64_t time;
Yabin Cui190a8482016-08-04 10:22:17 -0700332 };
333 const ExitOrForkRecordDataType* data;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700334
Yabin Cui1761a272016-06-23 17:11:14 -0700335 ExitOrForkRecord(const perf_event_attr& attr, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700336
337 ExitOrForkRecord() : data(nullptr) {}
Yabin Cui8f622512015-05-05 19:58:07 -0700338
339 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700340 void DumpData(size_t indent) const override;
341};
342
Yabin Cui41d4ba92015-06-22 12:27:58 -0700343struct ExitRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700344 ExitRecord(const perf_event_attr& attr, const char* p)
345 : ExitOrForkRecord(attr, p) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700346};
347
348struct ForkRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700349 ForkRecord(const perf_event_attr& attr, const char* p)
350 : ExitOrForkRecord(attr, p) {}
Yabin Cui767dd172016-06-02 21:02:43 -0700351
Yabin Cui190a8482016-08-04 10:22:17 -0700352 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
353 uint32_t ppid, uint32_t ptid, uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700354};
355
Yabin Cuie5adc132016-06-22 11:37:26 -0700356struct LostRecord : public Record {
357 uint64_t id;
358 uint64_t lost;
359
Yabin Cui1761a272016-06-23 17:11:14 -0700360 LostRecord(const perf_event_attr& attr, const char* p);
Yabin Cuie5adc132016-06-22 11:37:26 -0700361
362 protected:
363 void DumpData(size_t indent) const override;
364};
365
Yabin Cui9759e1b2015-04-28 15:54:13 -0700366struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700367 uint64_t sample_type; // sample_type is a bit mask determining which fields
368 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700369
370 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
371 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
372 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
373 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
374 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
375 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
376 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
377 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
378
Yabin Cui767dd172016-06-02 21:02:43 -0700379 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
380 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
381 PerfSampleBranchStackType
382 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
383 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
384 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700385
Yabin Cui1761a272016-06-23 17:11:14 -0700386 SampleRecord(const perf_event_attr& attr, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700387 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700388 uint64_t Timestamp() const override;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700389 uint32_t Cpu() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700390
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700391 uint64_t GetValidStackSize() const {
392 // If stack_user_data.dyn_size == 0, it may be because the kernel misses
393 // the patch to update dyn_size, like in N9 (See b/22612370). So assume
394 // all stack data is valid if dyn_size == 0.
395 if (stack_user_data.dyn_size == 0) {
Yabin Cui190a8482016-08-04 10:22:17 -0700396 return stack_user_data.size;
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700397 }
398 return stack_user_data.dyn_size;
399 }
400
Yabin Cui8f622512015-05-05 19:58:07 -0700401 protected:
402 void DumpData(size_t indent) const override;
403};
404
Yabin Cui767dd172016-06-02 21:02:43 -0700405// BuildIdRecord is defined in user-space, stored in BuildId feature section in
406// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700407struct BuildIdRecord : public Record {
408 uint32_t pid;
409 BuildId build_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700410 const char* filename;
Yabin Cui8f622512015-05-05 19:58:07 -0700411
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700412 explicit BuildIdRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700413
Yabin Cui190a8482016-08-04 10:22:17 -0700414 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
415 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700416
Yabin Cuicb84c982015-09-30 17:22:35 -0700417 protected:
418 void DumpData(size_t indent) const override;
419};
420
Yabin Cuib4212972016-05-25 14:08:05 -0700421struct KernelSymbolRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700422 uint32_t kallsyms_size;
423 const char* kallsyms;
Yabin Cuib4212972016-05-25 14:08:05 -0700424
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700425 explicit KernelSymbolRecord(const char* p);
Yabin Cuib4212972016-05-25 14:08:05 -0700426
Yabin Cui190a8482016-08-04 10:22:17 -0700427 KernelSymbolRecord(const std::string& kallsyms);
Yabin Cui767dd172016-06-02 21:02:43 -0700428
Yabin Cuib4212972016-05-25 14:08:05 -0700429 protected:
430 void DumpData(size_t indent) const override;
431};
432
Yabin Cui767dd172016-06-02 21:02:43 -0700433struct DsoRecord : public Record {
434 uint64_t dso_type;
435 uint64_t dso_id;
Yabin Cuic855ecc2016-07-11 17:04:54 -0700436 uint64_t min_vaddr;
Yabin Cui190a8482016-08-04 10:22:17 -0700437 const char* dso_name;
Yabin Cui767dd172016-06-02 21:02:43 -0700438
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700439 explicit DsoRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700440
Yabin Cui190a8482016-08-04 10:22:17 -0700441 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
442 uint64_t min_vaddr);
Yabin Cui767dd172016-06-02 21:02:43 -0700443
444 protected:
445 void DumpData(size_t indent) const override;
446};
447
448struct SymbolRecord : public Record {
449 uint64_t addr;
450 uint64_t len;
451 uint64_t dso_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700452 const char* name;
Yabin Cui767dd172016-06-02 21:02:43 -0700453
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700454 explicit SymbolRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700455
Yabin Cui190a8482016-08-04 10:22:17 -0700456 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
457 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 {
Yabin Cui190a8482016-08-04 10:22:17 -0700464 uint32_t data_size;
465 const char* data;
Yabin Cui4f41df62016-06-01 17:29:06 -0700466
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700467 explicit TracingDataRecord(const char* p);
Yabin Cui4f41df62016-06-01 17:29:06 -0700468
Yabin Cui190a8482016-08-04 10:22:17 -0700469 TracingDataRecord(const std::vector<char>& tracing_data);
Yabin Cuie5adc132016-06-22 11:37:26 -0700470
Yabin Cui767dd172016-06-02 21:02:43 -0700471 protected:
472 void DumpData(size_t indent) const override;
473};
474
475// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700476// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700477struct UnknownRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700478 const char* data;
Yabin Cuicb84c982015-09-30 17:22:35 -0700479
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700480 explicit UnknownRecord(const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700481
482 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700483 void DumpData(size_t indent) const override;
484};
485
Yabin Cui190a8482016-08-04 10:22:17 -0700486// Read record from the buffer pointed by [p]. But the record doesn't own
487// the buffer.
Yabin Cui767dd172016-06-02 21:02:43 -0700488std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
Yabin Cui1761a272016-06-23 17:11:14 -0700489 uint32_t type, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700490
491// Read record from the buffer pointed by [p]. And the record owns the buffer.
492std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
493 uint32_t type, const char* p);
494
495// Read records from the buffer pointed by [buf]. None of the records own
496// the buffer.
Yabin Cui767dd172016-06-02 21:02:43 -0700497std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
498 const perf_event_attr& attr, const char* buf, size_t buf_size);
499
Yabin Cuif469c3d2015-10-07 15:00:46 -0700500// RecordCache is a cache used when receiving records from the kernel.
501// It sorts received records based on type and timestamp, and pops records
502// in sorted order. Records from the kernel need to be sorted because
503// records may come from different cpus at the same time, and it is affected
504// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700505// RecordCache pushes records and pops sorted record online. It uses two checks
506// to help ensure that records are popped in order. Each time we pop a record A,
507// it is the earliest record among all records in the cache. In addition, we
508// have checks for min_cache_size and min_time_diff. For min_cache_size check,
509// we check if the cache size >= min_cache_size, which is based on the
510// assumption that if we have received (min_cache_size - 1) records after
511// record A, we are not likely to receive a record earlier than A. For
512// min_time_diff check, we check if record A is generated min_time_diff ns
513// earlier than the latest record, which is based on the assumption that if we
514// have received a record for time t, we are not likely to receive a record for
515// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700516class RecordCache {
517 public:
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700518 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700519 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700520 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700521 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700522 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700523 std::unique_ptr<Record> Pop();
524 std::vector<std::unique_ptr<Record>> PopAll();
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700525 std::unique_ptr<Record> ForcedPop();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700526
527 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800528 struct RecordWithSeq {
529 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700530 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800531
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700532 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
Yabin Cui4913c122016-01-11 17:15:55 -0800533 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700534 };
535
Yabin Cui4913c122016-01-11 17:15:55 -0800536 struct RecordComparator {
537 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
538 };
539
Yabin Cuif469c3d2015-10-07 15:00:46 -0700540 bool has_timestamp_;
541 size_t min_cache_size_;
542 uint64_t min_time_diff_in_ns_;
543 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800544 uint32_t cur_seq_;
545 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700546 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700547};
548
Yabin Cui9759e1b2015-04-28 15:54:13 -0700549#endif // SIMPLE_PERF_RECORD_H_