blob: 1f8e5b7d205ef9efdedcd2dc20f79e0b6d7c4e8c [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
Yabin Cui9759e1b2015-04-28 15:54:13 -070033enum user_record_type {
Yabin Cuib4212972016-05-25 14:08:05 -070034 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
Yabin Cui9759e1b2015-04-28 15:54:13 -070035 PERF_RECORD_ATTR = 64,
36 PERF_RECORD_EVENT_TYPE,
37 PERF_RECORD_TRACING_DATA,
38 PERF_RECORD_BUILD_ID,
39 PERF_RECORD_FINISHED_ROUND,
Yabin Cuib4212972016-05-25 14:08:05 -070040
41 SIMPLE_PERF_RECORD_TYPE_START = 32768,
42 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
Yabin Cuic5b4a312016-10-24 13:38:38 -070043 // TODO: remove DsoRecord and SymbolRecord.
Yabin Cui767dd172016-06-02 21:02:43 -070044 SIMPLE_PERF_RECORD_DSO,
45 SIMPLE_PERF_RECORD_SYMBOL,
Yabin Cui1761a272016-06-23 17:11:14 -070046 SIMPLE_PERF_RECORD_SPLIT,
47 SIMPLE_PERF_RECORD_SPLIT_END,
Yabin Cui825e56b2016-08-26 18:25:21 -070048 SIMPLE_PERF_RECORD_EVENT_ID,
Yabin Cui9759e1b2015-04-28 15:54:13 -070049};
50
Yabin Cui1761a272016-06-23 17:11:14 -070051// perf_event_header uses u16 to store record size. However, that is not
52// enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
53// a simpleperf_record_header struct to store record header for simpleperf
54// defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
55struct simpleperf_record_header {
56 uint32_t type;
57 uint16_t size1;
58 uint16_t size0;
59};
60
61static_assert(
62 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
63 "simpleperf_record_header should have the same size as perf_event_header");
64
Yabin Cui9759e1b2015-04-28 15:54:13 -070065struct PerfSampleIpType {
66 uint64_t ip;
67};
68
69struct PerfSampleTidType {
70 uint32_t pid, tid;
71};
72
73struct PerfSampleTimeType {
74 uint64_t time;
75};
76
77struct PerfSampleAddrType {
78 uint64_t addr;
79};
80
81struct PerfSampleIdType {
82 uint64_t id;
83};
84
85struct PerfSampleStreamIdType {
86 uint64_t stream_id;
87};
88
89struct PerfSampleCpuType {
90 uint32_t cpu, res;
91};
92
93struct PerfSamplePeriodType {
94 uint64_t period;
95};
96
Yabin Cui6e8a9a42015-06-15 14:36:43 -070097struct PerfSampleCallChainType {
Yabin Cui190a8482016-08-04 10:22:17 -070098 uint64_t ip_nr;
99 const uint64_t* ips;
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700100};
101
Yabin Cuibfc11b62015-08-19 10:12:51 -0700102struct PerfSampleRawType {
Yabin Cui190a8482016-08-04 10:22:17 -0700103 uint32_t size;
104 const char* data;
Yabin Cuibfc11b62015-08-19 10:12:51 -0700105};
106
Yabin Cuib64a8632016-05-24 18:23:33 -0700107struct BranchStackItemType {
108 uint64_t from;
109 uint64_t to;
110 uint64_t flags;
111};
112
Yabin Cuiddddc062015-06-02 17:54:52 -0700113struct PerfSampleBranchStackType {
Yabin Cui190a8482016-08-04 10:22:17 -0700114 uint64_t stack_nr;
115 const BranchStackItemType* stack;
Yabin Cuiddddc062015-06-02 17:54:52 -0700116};
117
Yabin Cui76769e52015-07-13 12:23:54 -0700118struct PerfSampleRegsUserType {
119 uint64_t abi;
120 uint64_t reg_mask;
Yabin Cui190a8482016-08-04 10:22:17 -0700121 uint64_t reg_nr;
122 const uint64_t* regs;
Yabin Cui76769e52015-07-13 12:23:54 -0700123};
124
125struct PerfSampleStackUserType {
Yabin Cui190a8482016-08-04 10:22:17 -0700126 uint64_t size;
127 const char* data;
Yabin Cui76769e52015-07-13 12:23:54 -0700128 uint64_t dyn_size;
129};
130
Yabin Cui1761a272016-06-23 17:11:14 -0700131struct RecordHeader {
132 public:
133 uint32_t type;
134 uint16_t misc;
135 uint32_t size;
136
137 RecordHeader() : type(0), misc(0), size(0) {}
138
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700139 explicit RecordHeader(const char* p) {
Yabin Cui1761a272016-06-23 17:11:14 -0700140 auto pheader = reinterpret_cast<const perf_event_header*>(p);
141 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
142 type = pheader->type;
143 misc = pheader->misc;
144 size = pheader->size;
145 } else {
146 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
147 type = sheader->type;
148 misc = 0;
149 size = (sheader->size1 << 16) | sheader->size0;
150 }
151 }
152
153 void MoveToBinaryFormat(char*& p) const {
154 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
155 auto pheader = reinterpret_cast<perf_event_header*>(p);
156 pheader->type = type;
157 pheader->misc = misc;
158 CHECK_LT(size, 1u << 16);
159 pheader->size = static_cast<uint16_t>(size);
160 } else {
161 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
162 sheader->type = type;
163 CHECK_EQ(misc, 0u);
164 sheader->size1 = size >> 16;
165 sheader->size0 = size & 0xffff;
166 }
167 p += sizeof(perf_event_header);
168 }
169};
170
Yabin Cui767dd172016-06-02 21:02:43 -0700171// SampleId is optional at the end of a record in binary format. Its content is
172// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
173// complexity of referring to perf_event_attr each time, we copy sample_id_all
174// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700175struct SampleId {
176 bool sample_id_all;
177 uint64_t sample_type;
178
Yabin Cui767dd172016-06-02 21:02:43 -0700179 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
180 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
181 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
182 PerfSampleStreamIdType
183 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
184 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700185
186 SampleId();
187
188 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700189 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700190
191 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700192 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
193 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700194
195 // Write the binary format of sample_id to the buffer pointed by p.
196 void WriteToBinaryFormat(char*& p) const;
197 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800198 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700199};
200
Yabin Cui767dd172016-06-02 21:02:43 -0700201// Usually one record contains the following three parts in order in binary
202// format:
Yabin Cui1761a272016-06-23 17:11:14 -0700203// RecordHeader (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700204// data depends on the record type
Yabin Cui1761a272016-06-23 17:11:14 -0700205// SampleId (optional part at the end of a record)
206// We hold the common parts (RecordHeader and SampleId) in the base class
Yabin Cui767dd172016-06-02 21:02:43 -0700207// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700208struct Record {
Yabin Cui1761a272016-06-23 17:11:14 -0700209 RecordHeader header;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700210 SampleId sample_id;
211
Yabin Cui190a8482016-08-04 10:22:17 -0700212 Record() : binary_(nullptr), own_binary_(false) {}
213 explicit Record(const char* p) : header(p), binary_(p), own_binary_(false) {}
214 Record(Record&& other);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700215
Yabin Cui190a8482016-08-04 10:22:17 -0700216 virtual ~Record() {
217 if (own_binary_) {
218 delete[] binary_;
219 }
220 }
221
222 void OwnBinary() { own_binary_ = true; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700223
Yabin Cui767dd172016-06-02 21:02:43 -0700224 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700225
Yabin Cui767dd172016-06-02 21:02:43 -0700226 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700227
Yabin Cui1761a272016-06-23 17:11:14 -0700228 uint32_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700229
Yabin Cui767dd172016-06-02 21:02:43 -0700230 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700231
Yabin Cuib64a8632016-05-24 18:23:33 -0700232 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700233 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
234 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700235 }
236
Yabin Cuib4212972016-05-25 14:08:05 -0700237 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
238 header.type = type;
239 header.misc = misc;
240 }
241
Yabin Cui1761a272016-06-23 17:11:14 -0700242 void SetSize(uint32_t size) { header.size = size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700243
Yabin Cui9759e1b2015-04-28 15:54:13 -0700244 void Dump(size_t indent = 0) const;
Yabin Cui190a8482016-08-04 10:22:17 -0700245
246 const char* Binary() const { return binary_; }
247
Yabin Cuif469c3d2015-10-07 15:00:46 -0700248 virtual uint64_t Timestamp() const;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700249 virtual uint32_t Cpu() const;
Yabin Cuiada97db2017-02-23 15:54:11 -0800250 virtual uint64_t Id() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700251
252 protected:
Yabin Cui190a8482016-08-04 10:22:17 -0700253 void UpdateBinary(const char* new_binary);
Yabin Cuicb84c982015-09-30 17:22:35 -0700254 virtual void DumpData(size_t) const = 0;
Yabin Cui190a8482016-08-04 10:22:17 -0700255
256 const char* binary_;
257 bool own_binary_;
258
259 DISALLOW_COPY_AND_ASSIGN(Record);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700260};
261
262struct MmapRecord : public Record {
263 struct MmapRecordDataType {
264 uint32_t pid, tid;
265 uint64_t addr;
266 uint64_t len;
267 uint64_t pgoff;
Yabin Cui190a8482016-08-04 10:22:17 -0700268 };
269 const MmapRecordDataType* data;
270 const char* filename;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700271
Yabin Cui1761a272016-06-23 17:11:14 -0700272 MmapRecord(const perf_event_attr& attr, const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700273
Yabin Cui190a8482016-08-04 10:22:17 -0700274 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
275 uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
276 const std::string& filename, uint64_t event_id, uint64_t time = 0);
277
278 void SetDataAndFilename(const MmapRecordDataType& data,
279 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700280
Yabin Cui8f622512015-05-05 19:58:07 -0700281 protected:
282 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700283};
284
Yabin Cui41d4ba92015-06-22 12:27:58 -0700285struct Mmap2Record : public Record {
286 struct Mmap2RecordDataType {
287 uint32_t pid, tid;
288 uint64_t addr;
289 uint64_t len;
290 uint64_t pgoff;
291 uint32_t maj;
292 uint32_t min;
293 uint64_t ino;
294 uint64_t ino_generation;
295 uint32_t prot, flags;
Yabin Cui190a8482016-08-04 10:22:17 -0700296 };
297 const Mmap2RecordDataType* data;
298 const char* filename;
Yabin Cui41d4ba92015-06-22 12:27:58 -0700299
Yabin Cui1761a272016-06-23 17:11:14 -0700300 Mmap2Record(const perf_event_attr& attr, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700301
302 void SetDataAndFilename(const Mmap2RecordDataType& data,
303 const std::string& filename);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700304
305 protected:
306 void DumpData(size_t indent) const override;
307};
308
Yabin Cui9759e1b2015-04-28 15:54:13 -0700309struct CommRecord : public Record {
310 struct CommRecordDataType {
311 uint32_t pid, tid;
Yabin Cui190a8482016-08-04 10:22:17 -0700312 };
313 const CommRecordDataType* data;
314 const char* comm;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700315
Yabin Cui1761a272016-06-23 17:11:14 -0700316 CommRecord(const perf_event_attr& attr, const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700317
Yabin Cui190a8482016-08-04 10:22:17 -0700318 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
Yabin Cui2597ef02016-10-19 11:28:48 -0700319 const std::string& comm, uint64_t event_id, uint64_t time);
Yabin Cui767dd172016-06-02 21:02:43 -0700320
Yabin Cui8f622512015-05-05 19:58:07 -0700321 protected:
322 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700323};
324
Yabin Cui41d4ba92015-06-22 12:27:58 -0700325struct ExitOrForkRecord : public Record {
326 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700327 uint32_t pid, ppid;
328 uint32_t tid, ptid;
329 uint64_t time;
Yabin Cui190a8482016-08-04 10:22:17 -0700330 };
331 const ExitOrForkRecordDataType* data;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700332
Yabin Cui1761a272016-06-23 17:11:14 -0700333 ExitOrForkRecord(const perf_event_attr& attr, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700334
335 ExitOrForkRecord() : data(nullptr) {}
Yabin Cui8f622512015-05-05 19:58:07 -0700336
337 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700338 void DumpData(size_t indent) const override;
339};
340
Yabin Cui41d4ba92015-06-22 12:27:58 -0700341struct ExitRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700342 ExitRecord(const perf_event_attr& attr, const char* p)
343 : ExitOrForkRecord(attr, p) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700344};
345
346struct ForkRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700347 ForkRecord(const perf_event_attr& attr, const char* p)
348 : ExitOrForkRecord(attr, p) {}
Yabin Cui767dd172016-06-02 21:02:43 -0700349
Yabin Cui190a8482016-08-04 10:22:17 -0700350 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
351 uint32_t ppid, uint32_t ptid, uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700352};
353
Yabin Cuie5adc132016-06-22 11:37:26 -0700354struct LostRecord : public Record {
355 uint64_t id;
356 uint64_t lost;
357
Yabin Cui1761a272016-06-23 17:11:14 -0700358 LostRecord(const perf_event_attr& attr, const char* p);
Yabin Cuie5adc132016-06-22 11:37:26 -0700359
360 protected:
361 void DumpData(size_t indent) const override;
362};
363
Yabin Cui9759e1b2015-04-28 15:54:13 -0700364struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700365 uint64_t sample_type; // sample_type is a bit mask determining which fields
366 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700367
368 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
369 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
370 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
371 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
372 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
373 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
374 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
375 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
376
Yabin Cui767dd172016-06-02 21:02:43 -0700377 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
378 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
379 PerfSampleBranchStackType
380 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
381 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
382 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700383
Yabin Cui1761a272016-06-23 17:11:14 -0700384 SampleRecord(const perf_event_attr& attr, const char* p);
Yabin Cui2597ef02016-10-19 11:28:48 -0700385 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip,
386 uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu,
387 uint64_t period, const std::vector<uint64_t>& ips);
388
Yabin Cui190a8482016-08-04 10:22:17 -0700389 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
Yabin Cuid3cb3b02017-07-24 14:59:46 -0700390 size_t ExcludeKernelCallChain();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700391 uint64_t Timestamp() const override;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700392 uint32_t Cpu() const override;
Yabin Cuiada97db2017-02-23 15:54:11 -0800393 uint64_t Id() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700394
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700395 uint64_t GetValidStackSize() const {
396 // If stack_user_data.dyn_size == 0, it may be because the kernel misses
397 // the patch to update dyn_size, like in N9 (See b/22612370). So assume
398 // all stack data is valid if dyn_size == 0.
399 if (stack_user_data.dyn_size == 0) {
Yabin Cui190a8482016-08-04 10:22:17 -0700400 return stack_user_data.size;
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700401 }
402 return stack_user_data.dyn_size;
403 }
404
Yabin Cui8f622512015-05-05 19:58:07 -0700405 protected:
406 void DumpData(size_t indent) const override;
407};
408
Yabin Cui767dd172016-06-02 21:02:43 -0700409// BuildIdRecord is defined in user-space, stored in BuildId feature section in
410// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700411struct BuildIdRecord : public Record {
412 uint32_t pid;
413 BuildId build_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700414 const char* filename;
Yabin Cui8f622512015-05-05 19:58:07 -0700415
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700416 explicit BuildIdRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700417
Yabin Cui190a8482016-08-04 10:22:17 -0700418 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
419 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700420
Yabin Cuicb84c982015-09-30 17:22:35 -0700421 protected:
422 void DumpData(size_t indent) const override;
423};
424
Yabin Cuib4212972016-05-25 14:08:05 -0700425struct KernelSymbolRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700426 uint32_t kallsyms_size;
427 const char* kallsyms;
Yabin Cuib4212972016-05-25 14:08:05 -0700428
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700429 explicit KernelSymbolRecord(const char* p);
Yabin Cuib4212972016-05-25 14:08:05 -0700430
Chih-Hung Hsieh1786a882016-08-11 11:06:00 -0700431 explicit KernelSymbolRecord(const std::string& kallsyms);
Yabin Cui767dd172016-06-02 21:02:43 -0700432
Yabin Cuib4212972016-05-25 14:08:05 -0700433 protected:
434 void DumpData(size_t indent) const override;
435};
436
Yabin Cui767dd172016-06-02 21:02:43 -0700437struct DsoRecord : public Record {
438 uint64_t dso_type;
439 uint64_t dso_id;
Yabin Cuic855ecc2016-07-11 17:04:54 -0700440 uint64_t min_vaddr;
Yabin Cui190a8482016-08-04 10:22:17 -0700441 const char* dso_name;
Yabin Cui767dd172016-06-02 21:02:43 -0700442
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700443 explicit DsoRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700444
Yabin Cui190a8482016-08-04 10:22:17 -0700445 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
446 uint64_t min_vaddr);
Yabin Cui767dd172016-06-02 21:02:43 -0700447
448 protected:
449 void DumpData(size_t indent) const override;
450};
451
452struct SymbolRecord : public Record {
453 uint64_t addr;
454 uint64_t len;
455 uint64_t dso_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700456 const char* name;
Yabin Cui767dd172016-06-02 21:02:43 -0700457
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700458 explicit SymbolRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700459
Yabin Cui190a8482016-08-04 10:22:17 -0700460 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
461 uint64_t dso_id);
Yabin Cui1761a272016-06-23 17:11:14 -0700462
Yabin Cui4f41df62016-06-01 17:29:06 -0700463 protected:
464 void DumpData(size_t indent) const override;
465};
Yabin Cui767dd172016-06-02 21:02:43 -0700466
Yabin Cui4f41df62016-06-01 17:29:06 -0700467struct TracingDataRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700468 uint32_t data_size;
469 const char* data;
Yabin Cui4f41df62016-06-01 17:29:06 -0700470
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700471 explicit TracingDataRecord(const char* p);
Yabin Cui4f41df62016-06-01 17:29:06 -0700472
Chih-Hung Hsieh1786a882016-08-11 11:06:00 -0700473 explicit TracingDataRecord(const std::vector<char>& tracing_data);
Yabin Cuie5adc132016-06-22 11:37:26 -0700474
Yabin Cui767dd172016-06-02 21:02:43 -0700475 protected:
476 void DumpData(size_t indent) const override;
477};
478
Yabin Cui825e56b2016-08-26 18:25:21 -0700479struct EventIdRecord : public Record {
480 uint64_t count;
481 struct EventIdData {
482 uint64_t attr_id;
483 uint64_t event_id;
484 } const* data;
485
486 explicit EventIdRecord(const char* p);
487
488 explicit EventIdRecord(const std::vector<uint64_t>& data);
489
490 protected:
491 void DumpData(size_t indent) const override;
492};
493
Yabin Cui767dd172016-06-02 21:02:43 -0700494// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700495// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700496struct UnknownRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700497 const char* data;
Yabin Cuicb84c982015-09-30 17:22:35 -0700498
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700499 explicit UnknownRecord(const char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700500
501 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700502 void DumpData(size_t indent) const override;
503};
504
Yabin Cui190a8482016-08-04 10:22:17 -0700505// Read record from the buffer pointed by [p]. But the record doesn't own
506// the buffer.
Yabin Cui767dd172016-06-02 21:02:43 -0700507std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
Yabin Cui1761a272016-06-23 17:11:14 -0700508 uint32_t type, const char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700509
510// Read record from the buffer pointed by [p]. And the record owns the buffer.
511std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
512 uint32_t type, const char* p);
513
514// Read records from the buffer pointed by [buf]. None of the records own
515// the buffer.
Yabin Cui767dd172016-06-02 21:02:43 -0700516std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
517 const perf_event_attr& attr, const char* buf, size_t buf_size);
518
Yabin Cui2ea6de12016-10-24 19:13:09 -0700519// Read one record from the buffer pointed by [p]. But the record doesn't
520// own the buffer.
521std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
522 const char* p);
523
Yabin Cuif469c3d2015-10-07 15:00:46 -0700524// RecordCache is a cache used when receiving records from the kernel.
525// It sorts received records based on type and timestamp, and pops records
526// in sorted order. Records from the kernel need to be sorted because
527// records may come from different cpus at the same time, and it is affected
528// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700529// RecordCache pushes records and pops sorted record online. It uses two checks
530// to help ensure that records are popped in order. Each time we pop a record A,
531// it is the earliest record among all records in the cache. In addition, we
532// have checks for min_cache_size and min_time_diff. For min_cache_size check,
533// we check if the cache size >= min_cache_size, which is based on the
534// assumption that if we have received (min_cache_size - 1) records after
535// record A, we are not likely to receive a record earlier than A. For
536// min_time_diff check, we check if record A is generated min_time_diff ns
537// earlier than the latest record, which is based on the assumption that if we
538// have received a record for time t, we are not likely to receive a record for
539// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700540class RecordCache {
541 public:
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700542 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700543 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700544 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700545 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700546 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700547 std::unique_ptr<Record> Pop();
548 std::vector<std::unique_ptr<Record>> PopAll();
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700549 std::unique_ptr<Record> ForcedPop();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700550
551 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800552 struct RecordWithSeq {
553 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700554 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800555
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700556 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
Yabin Cui4913c122016-01-11 17:15:55 -0800557 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700558 };
559
Yabin Cui4913c122016-01-11 17:15:55 -0800560 struct RecordComparator {
561 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
562 };
563
Yabin Cuif469c3d2015-10-07 15:00:46 -0700564 bool has_timestamp_;
565 size_t min_cache_size_;
566 uint64_t min_time_diff_in_ns_;
567 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800568 uint32_t cur_seq_;
569 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700570 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700571};
572
Yabin Cui9759e1b2015-04-28 15:54:13 -0700573#endif // SIMPLE_PERF_RECORD_H_