blob: 5e9f1aa7cb639026c8a3094e87a89c47bd438e09 [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 Cui81a9d332017-12-10 13:09:07 -080031#include "CallChainJoiner.h"
Yabin Cui03381452017-12-13 11:31:53 -080032#include "OfflineUnwinder.h"
Yabin Cui9759e1b2015-04-28 15:54:13 -070033#include "perf_event.h"
34
Yabin Cui9759e1b2015-04-28 15:54:13 -070035enum user_record_type {
Yabin Cuib4212972016-05-25 14:08:05 -070036 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
Yabin Cui9759e1b2015-04-28 15:54:13 -070037 PERF_RECORD_ATTR = 64,
38 PERF_RECORD_EVENT_TYPE,
39 PERF_RECORD_TRACING_DATA,
40 PERF_RECORD_BUILD_ID,
41 PERF_RECORD_FINISHED_ROUND,
Yabin Cuib4212972016-05-25 14:08:05 -070042
43 SIMPLE_PERF_RECORD_TYPE_START = 32768,
44 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
Yabin Cuic5b4a312016-10-24 13:38:38 -070045 // TODO: remove DsoRecord and SymbolRecord.
Yabin Cui767dd172016-06-02 21:02:43 -070046 SIMPLE_PERF_RECORD_DSO,
47 SIMPLE_PERF_RECORD_SYMBOL,
Yabin Cui1761a272016-06-23 17:11:14 -070048 SIMPLE_PERF_RECORD_SPLIT,
49 SIMPLE_PERF_RECORD_SPLIT_END,
Yabin Cui825e56b2016-08-26 18:25:21 -070050 SIMPLE_PERF_RECORD_EVENT_ID,
Yabin Cui81a9d332017-12-10 13:09:07 -080051 SIMPLE_PERF_RECORD_CALLCHAIN,
Yabin Cui03381452017-12-13 11:31:53 -080052 SIMPLE_PERF_RECORD_UNWINDING_RESULT,
Yabin Cui8cd92332018-03-21 14:34:29 -070053 SIMPLE_PERF_RECORD_TRACING_DATA,
Yabin Cui9759e1b2015-04-28 15:54:13 -070054};
55
Yabin Cui1761a272016-06-23 17:11:14 -070056// perf_event_header uses u16 to store record size. However, that is not
57// enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
58// a simpleperf_record_header struct to store record header for simpleperf
59// defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
60struct simpleperf_record_header {
61 uint32_t type;
62 uint16_t size1;
63 uint16_t size0;
64};
65
66static_assert(
67 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
68 "simpleperf_record_header should have the same size as perf_event_header");
69
Yabin Cui9759e1b2015-04-28 15:54:13 -070070struct PerfSampleIpType {
71 uint64_t ip;
72};
73
74struct PerfSampleTidType {
75 uint32_t pid, tid;
76};
77
78struct PerfSampleTimeType {
79 uint64_t time;
80};
81
82struct PerfSampleAddrType {
83 uint64_t addr;
84};
85
86struct PerfSampleIdType {
87 uint64_t id;
88};
89
90struct PerfSampleStreamIdType {
91 uint64_t stream_id;
92};
93
94struct PerfSampleCpuType {
95 uint32_t cpu, res;
96};
97
98struct PerfSamplePeriodType {
99 uint64_t period;
100};
101
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700102struct PerfSampleCallChainType {
Yabin Cui190a8482016-08-04 10:22:17 -0700103 uint64_t ip_nr;
Yabin Cui3d4aa262017-11-01 15:58:55 -0700104 uint64_t* ips;
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700105};
106
Yabin Cuibfc11b62015-08-19 10:12:51 -0700107struct PerfSampleRawType {
Yabin Cui190a8482016-08-04 10:22:17 -0700108 uint32_t size;
109 const char* data;
Yabin Cuibfc11b62015-08-19 10:12:51 -0700110};
111
Yabin Cuib64a8632016-05-24 18:23:33 -0700112struct BranchStackItemType {
113 uint64_t from;
114 uint64_t to;
115 uint64_t flags;
116};
117
Yabin Cuiddddc062015-06-02 17:54:52 -0700118struct PerfSampleBranchStackType {
Yabin Cui190a8482016-08-04 10:22:17 -0700119 uint64_t stack_nr;
120 const BranchStackItemType* stack;
Yabin Cuiddddc062015-06-02 17:54:52 -0700121};
122
Yabin Cui76769e52015-07-13 12:23:54 -0700123struct PerfSampleRegsUserType {
124 uint64_t abi;
125 uint64_t reg_mask;
Yabin Cui190a8482016-08-04 10:22:17 -0700126 uint64_t reg_nr;
127 const uint64_t* regs;
Yabin Cui76769e52015-07-13 12:23:54 -0700128};
129
130struct PerfSampleStackUserType {
Yabin Cui190a8482016-08-04 10:22:17 -0700131 uint64_t size;
Yabin Cui3d4aa262017-11-01 15:58:55 -0700132 char* data;
Yabin Cui76769e52015-07-13 12:23:54 -0700133 uint64_t dyn_size;
134};
135
Yabin Cui1761a272016-06-23 17:11:14 -0700136struct RecordHeader {
137 public:
138 uint32_t type;
139 uint16_t misc;
140 uint32_t size;
141
142 RecordHeader() : type(0), misc(0), size(0) {}
143
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700144 explicit RecordHeader(const char* p) {
Yabin Cui1761a272016-06-23 17:11:14 -0700145 auto pheader = reinterpret_cast<const perf_event_header*>(p);
146 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
147 type = pheader->type;
148 misc = pheader->misc;
149 size = pheader->size;
150 } else {
151 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
152 type = sheader->type;
153 misc = 0;
154 size = (sheader->size1 << 16) | sheader->size0;
155 }
156 }
157
158 void MoveToBinaryFormat(char*& p) const {
159 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
160 auto pheader = reinterpret_cast<perf_event_header*>(p);
161 pheader->type = type;
162 pheader->misc = misc;
163 CHECK_LT(size, 1u << 16);
164 pheader->size = static_cast<uint16_t>(size);
165 } else {
166 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
167 sheader->type = type;
168 CHECK_EQ(misc, 0u);
169 sheader->size1 = size >> 16;
170 sheader->size0 = size & 0xffff;
171 }
172 p += sizeof(perf_event_header);
173 }
174};
175
Yabin Cui767dd172016-06-02 21:02:43 -0700176// SampleId is optional at the end of a record in binary format. Its content is
177// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
178// complexity of referring to perf_event_attr each time, we copy sample_id_all
179// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700180struct SampleId {
181 bool sample_id_all;
182 uint64_t sample_type;
183
Yabin Cui767dd172016-06-02 21:02:43 -0700184 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
185 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
186 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
187 PerfSampleStreamIdType
188 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
189 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700190
191 SampleId();
192
193 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700194 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700195
196 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700197 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
198 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700199
200 // Write the binary format of sample_id to the buffer pointed by p.
201 void WriteToBinaryFormat(char*& p) const;
202 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800203 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700204};
205
Yabin Cui767dd172016-06-02 21:02:43 -0700206// Usually one record contains the following three parts in order in binary
207// format:
Yabin Cui1761a272016-06-23 17:11:14 -0700208// RecordHeader (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700209// data depends on the record type
Yabin Cui1761a272016-06-23 17:11:14 -0700210// SampleId (optional part at the end of a record)
211// We hold the common parts (RecordHeader and SampleId) in the base class
Yabin Cui767dd172016-06-02 21:02:43 -0700212// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700213struct Record {
Yabin Cui1761a272016-06-23 17:11:14 -0700214 RecordHeader header;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700215 SampleId sample_id;
216
Yabin Cui190a8482016-08-04 10:22:17 -0700217 Record() : binary_(nullptr), own_binary_(false) {}
Yabin Cui3d4aa262017-11-01 15:58:55 -0700218 explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {}
Yabin Cui190a8482016-08-04 10:22:17 -0700219 Record(Record&& other);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700220
Yabin Cui190a8482016-08-04 10:22:17 -0700221 virtual ~Record() {
222 if (own_binary_) {
223 delete[] binary_;
224 }
225 }
226
227 void OwnBinary() { own_binary_ = true; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700228
Yabin Cui767dd172016-06-02 21:02:43 -0700229 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700230
Yabin Cui767dd172016-06-02 21:02:43 -0700231 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700232
Yabin Cui1761a272016-06-23 17:11:14 -0700233 uint32_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700234
Yabin Cui767dd172016-06-02 21:02:43 -0700235 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700236
Yabin Cuib64a8632016-05-24 18:23:33 -0700237 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700238 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
239 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700240 }
241
Yabin Cuib4212972016-05-25 14:08:05 -0700242 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
243 header.type = type;
244 header.misc = misc;
245 }
246
Yabin Cui1761a272016-06-23 17:11:14 -0700247 void SetSize(uint32_t size) { header.size = size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700248
Yabin Cui9759e1b2015-04-28 15:54:13 -0700249 void Dump(size_t indent = 0) const;
Yabin Cui190a8482016-08-04 10:22:17 -0700250
251 const char* Binary() const { return binary_; }
Yabin Cui3d4aa262017-11-01 15:58:55 -0700252 char* BinaryForTestingOnly() { return binary_; }
Yabin Cui190a8482016-08-04 10:22:17 -0700253
Yabin Cuif469c3d2015-10-07 15:00:46 -0700254 virtual uint64_t Timestamp() const;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700255 virtual uint32_t Cpu() const;
Yabin Cuiada97db2017-02-23 15:54:11 -0800256 virtual uint64_t Id() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700257
258 protected:
Yabin Cui3d4aa262017-11-01 15:58:55 -0700259 void UpdateBinary(char* new_binary);
Yabin Cuicb84c982015-09-30 17:22:35 -0700260 virtual void DumpData(size_t) const = 0;
Yabin Cui190a8482016-08-04 10:22:17 -0700261
Yabin Cui3d4aa262017-11-01 15:58:55 -0700262 char* binary_;
Yabin Cui190a8482016-08-04 10:22:17 -0700263 bool own_binary_;
264
265 DISALLOW_COPY_AND_ASSIGN(Record);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700266};
267
268struct MmapRecord : public Record {
269 struct MmapRecordDataType {
270 uint32_t pid, tid;
271 uint64_t addr;
272 uint64_t len;
273 uint64_t pgoff;
Yabin Cui190a8482016-08-04 10:22:17 -0700274 };
275 const MmapRecordDataType* data;
276 const char* filename;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700277
Yabin Cui3d4aa262017-11-01 15:58:55 -0700278 MmapRecord(const perf_event_attr& attr, char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700279
Yabin Cui190a8482016-08-04 10:22:17 -0700280 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
281 uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
282 const std::string& filename, uint64_t event_id, uint64_t time = 0);
283
284 void SetDataAndFilename(const MmapRecordDataType& data,
285 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700286
Yabin Cui8f622512015-05-05 19:58:07 -0700287 protected:
288 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700289};
290
Yabin Cui41d4ba92015-06-22 12:27:58 -0700291struct Mmap2Record : public Record {
292 struct Mmap2RecordDataType {
293 uint32_t pid, tid;
294 uint64_t addr;
295 uint64_t len;
296 uint64_t pgoff;
297 uint32_t maj;
298 uint32_t min;
299 uint64_t ino;
300 uint64_t ino_generation;
301 uint32_t prot, flags;
Yabin Cui190a8482016-08-04 10:22:17 -0700302 };
303 const Mmap2RecordDataType* data;
304 const char* filename;
Yabin Cui41d4ba92015-06-22 12:27:58 -0700305
Yabin Cui3d4aa262017-11-01 15:58:55 -0700306 Mmap2Record(const perf_event_attr& attr, char* p);
Yabin Cuicdc11a32018-03-20 15:29:03 -0700307 Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
308 uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot,
309 const std::string& filename, uint64_t event_id, uint64_t time = 0);
Yabin Cui190a8482016-08-04 10:22:17 -0700310
311 void SetDataAndFilename(const Mmap2RecordDataType& data,
312 const std::string& filename);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700313
314 protected:
315 void DumpData(size_t indent) const override;
316};
317
Yabin Cui9759e1b2015-04-28 15:54:13 -0700318struct CommRecord : public Record {
319 struct CommRecordDataType {
320 uint32_t pid, tid;
Yabin Cui190a8482016-08-04 10:22:17 -0700321 };
322 const CommRecordDataType* data;
323 const char* comm;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700324
Yabin Cui3d4aa262017-11-01 15:58:55 -0700325 CommRecord(const perf_event_attr& attr, char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700326
Yabin Cui190a8482016-08-04 10:22:17 -0700327 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
Yabin Cui2597ef02016-10-19 11:28:48 -0700328 const std::string& comm, uint64_t event_id, uint64_t time);
Yabin Cui767dd172016-06-02 21:02:43 -0700329
Yabin Cui8f622512015-05-05 19:58:07 -0700330 protected:
331 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700332};
333
Yabin Cui41d4ba92015-06-22 12:27:58 -0700334struct ExitOrForkRecord : public Record {
335 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700336 uint32_t pid, ppid;
337 uint32_t tid, ptid;
338 uint64_t time;
Yabin Cui190a8482016-08-04 10:22:17 -0700339 };
340 const ExitOrForkRecordDataType* data;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700341
Yabin Cui3d4aa262017-11-01 15:58:55 -0700342 ExitOrForkRecord(const perf_event_attr& attr, char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700343
344 ExitOrForkRecord() : data(nullptr) {}
Yabin Cui8f622512015-05-05 19:58:07 -0700345
346 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700347 void DumpData(size_t indent) const override;
348};
349
Yabin Cui41d4ba92015-06-22 12:27:58 -0700350struct ExitRecord : public ExitOrForkRecord {
Yabin Cui3d4aa262017-11-01 15:58:55 -0700351 ExitRecord(const perf_event_attr& attr, char* p)
Yabin Cui1761a272016-06-23 17:11:14 -0700352 : ExitOrForkRecord(attr, p) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700353};
354
355struct ForkRecord : public ExitOrForkRecord {
Yabin Cui3d4aa262017-11-01 15:58:55 -0700356 ForkRecord(const perf_event_attr& attr, char* p)
Yabin Cui1761a272016-06-23 17:11:14 -0700357 : ExitOrForkRecord(attr, p) {}
Yabin Cui767dd172016-06-02 21:02:43 -0700358
Yabin Cui190a8482016-08-04 10:22:17 -0700359 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
360 uint32_t ppid, uint32_t ptid, uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700361};
362
Yabin Cuie5adc132016-06-22 11:37:26 -0700363struct LostRecord : public Record {
364 uint64_t id;
365 uint64_t lost;
366
Yabin Cui3d4aa262017-11-01 15:58:55 -0700367 LostRecord(const perf_event_attr& attr, char* p);
Yabin Cuie5adc132016-06-22 11:37:26 -0700368
369 protected:
370 void DumpData(size_t indent) const override;
371};
372
Yabin Cui9759e1b2015-04-28 15:54:13 -0700373struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700374 uint64_t sample_type; // sample_type is a bit mask determining which fields
375 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700376
377 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
378 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
379 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
380 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
381 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
382 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
383 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
384 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
385
Yabin Cui767dd172016-06-02 21:02:43 -0700386 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
387 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
388 PerfSampleBranchStackType
389 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
390 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
391 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700392
Yabin Cui3d4aa262017-11-01 15:58:55 -0700393 SampleRecord(const perf_event_attr& attr, char* p);
Yabin Cui2597ef02016-10-19 11:28:48 -0700394 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip,
395 uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu,
396 uint64_t period, const std::vector<uint64_t>& ips);
397
Yabin Cui190a8482016-08-04 10:22:17 -0700398 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
Yabin Cuid3cb3b02017-07-24 14:59:46 -0700399 size_t ExcludeKernelCallChain();
Yabin Cui81a9d332017-12-10 13:09:07 -0800400 bool HasUserCallChain() const;
401 void UpdateUserCallChain(const std::vector<uint64_t>& user_ips);
Yabin Cui5a5e92c2018-01-29 16:02:16 -0800402 void RemoveInvalidStackData();
Yabin Cui81a9d332017-12-10 13:09:07 -0800403
Yabin Cuif469c3d2015-10-07 15:00:46 -0700404 uint64_t Timestamp() const override;
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700405 uint32_t Cpu() const override;
Yabin Cuiada97db2017-02-23 15:54:11 -0800406 uint64_t Id() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700407
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700408 uint64_t GetValidStackSize() const {
409 // If stack_user_data.dyn_size == 0, it may be because the kernel misses
410 // the patch to update dyn_size, like in N9 (See b/22612370). So assume
411 // all stack data is valid if dyn_size == 0.
412 if (stack_user_data.dyn_size == 0) {
Yabin Cui190a8482016-08-04 10:22:17 -0700413 return stack_user_data.size;
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700414 }
415 return stack_user_data.dyn_size;
416 }
417
Yabin Cui3d4aa262017-11-01 15:58:55 -0700418 void AdjustCallChainGeneratedByKernel();
Yabin Cui7c8847b2018-04-13 11:23:06 -0700419 std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const;
Yabin Cui3d4aa262017-11-01 15:58:55 -0700420
Yabin Cui8f622512015-05-05 19:58:07 -0700421 protected:
422 void DumpData(size_t indent) const override;
423};
424
Yabin Cui767dd172016-06-02 21:02:43 -0700425// BuildIdRecord is defined in user-space, stored in BuildId feature section in
426// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700427struct BuildIdRecord : public Record {
428 uint32_t pid;
429 BuildId build_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700430 const char* filename;
Yabin Cui8f622512015-05-05 19:58:07 -0700431
Yabin Cui3d4aa262017-11-01 15:58:55 -0700432 explicit BuildIdRecord(char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700433
Yabin Cui190a8482016-08-04 10:22:17 -0700434 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
435 const std::string& filename);
Yabin Cui767dd172016-06-02 21:02:43 -0700436
Yabin Cuicb84c982015-09-30 17:22:35 -0700437 protected:
438 void DumpData(size_t indent) const override;
439};
440
Yabin Cuib4212972016-05-25 14:08:05 -0700441struct KernelSymbolRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700442 uint32_t kallsyms_size;
443 const char* kallsyms;
Yabin Cuib4212972016-05-25 14:08:05 -0700444
Yabin Cui3d4aa262017-11-01 15:58:55 -0700445 explicit KernelSymbolRecord(char* p);
Yabin Cuib4212972016-05-25 14:08:05 -0700446
Chih-Hung Hsieh1786a882016-08-11 11:06:00 -0700447 explicit KernelSymbolRecord(const std::string& kallsyms);
Yabin Cui767dd172016-06-02 21:02:43 -0700448
Yabin Cuib4212972016-05-25 14:08:05 -0700449 protected:
450 void DumpData(size_t indent) const override;
451};
452
Yabin Cui767dd172016-06-02 21:02:43 -0700453struct DsoRecord : public Record {
454 uint64_t dso_type;
455 uint64_t dso_id;
Yabin Cuic855ecc2016-07-11 17:04:54 -0700456 uint64_t min_vaddr;
Yabin Cui190a8482016-08-04 10:22:17 -0700457 const char* dso_name;
Yabin Cui767dd172016-06-02 21:02:43 -0700458
Yabin Cui3d4aa262017-11-01 15:58:55 -0700459 explicit DsoRecord(char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700460
Yabin Cui190a8482016-08-04 10:22:17 -0700461 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
462 uint64_t min_vaddr);
Yabin Cui767dd172016-06-02 21:02:43 -0700463
464 protected:
465 void DumpData(size_t indent) const override;
466};
467
468struct SymbolRecord : public Record {
469 uint64_t addr;
470 uint64_t len;
471 uint64_t dso_id;
Yabin Cui190a8482016-08-04 10:22:17 -0700472 const char* name;
Yabin Cui767dd172016-06-02 21:02:43 -0700473
Yabin Cui3d4aa262017-11-01 15:58:55 -0700474 explicit SymbolRecord(char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700475
Yabin Cui190a8482016-08-04 10:22:17 -0700476 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
477 uint64_t dso_id);
Yabin Cui1761a272016-06-23 17:11:14 -0700478
Yabin Cui4f41df62016-06-01 17:29:06 -0700479 protected:
480 void DumpData(size_t indent) const override;
481};
Yabin Cui767dd172016-06-02 21:02:43 -0700482
Yabin Cui4f41df62016-06-01 17:29:06 -0700483struct TracingDataRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700484 uint32_t data_size;
485 const char* data;
Yabin Cui4f41df62016-06-01 17:29:06 -0700486
Yabin Cui3d4aa262017-11-01 15:58:55 -0700487 explicit TracingDataRecord(char* p);
Yabin Cui4f41df62016-06-01 17:29:06 -0700488
Chih-Hung Hsieh1786a882016-08-11 11:06:00 -0700489 explicit TracingDataRecord(const std::vector<char>& tracing_data);
Yabin Cuie5adc132016-06-22 11:37:26 -0700490
Yabin Cui767dd172016-06-02 21:02:43 -0700491 protected:
492 void DumpData(size_t indent) const override;
493};
494
Yabin Cui825e56b2016-08-26 18:25:21 -0700495struct EventIdRecord : public Record {
496 uint64_t count;
497 struct EventIdData {
498 uint64_t attr_id;
499 uint64_t event_id;
500 } const* data;
501
Yabin Cui3d4aa262017-11-01 15:58:55 -0700502 explicit EventIdRecord(char* p);
Yabin Cui825e56b2016-08-26 18:25:21 -0700503
504 explicit EventIdRecord(const std::vector<uint64_t>& data);
505
506 protected:
507 void DumpData(size_t indent) const override;
508};
509
Yabin Cui81a9d332017-12-10 13:09:07 -0800510struct CallChainRecord : public Record {
511 uint32_t pid;
512 uint32_t tid;
513 uint64_t chain_type;
514 uint64_t time;
515 uint64_t ip_nr;
516 uint64_t* ips;
517 uint64_t* sps;
518
519 explicit CallChainRecord(char* p);
520
521 CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time,
522 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
523
524 uint64_t Timestamp() const override {
525 return time;
526 }
527
528 protected:
529 void DumpData(size_t indent) const override;
530};
531
Yabin Cui03381452017-12-13 11:31:53 -0800532struct UnwindingResultRecord : public Record {
533 uint64_t time;
Yabin Cui85faad92018-01-04 17:17:55 -0800534 simpleperf::UnwindingResult unwinding_result;
Yabin Cui03381452017-12-13 11:31:53 -0800535
536 explicit UnwindingResultRecord(char* p);
537
Yabin Cui85faad92018-01-04 17:17:55 -0800538 UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result);
Yabin Cui03381452017-12-13 11:31:53 -0800539
540 uint64_t Timestamp() const override {
541 return time;
542 }
543
544 protected:
545 void DumpData(size_t indent) const override;
546};
547
Yabin Cui767dd172016-06-02 21:02:43 -0700548// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700549// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700550struct UnknownRecord : public Record {
Yabin Cui190a8482016-08-04 10:22:17 -0700551 const char* data;
Yabin Cuicb84c982015-09-30 17:22:35 -0700552
Yabin Cui3d4aa262017-11-01 15:58:55 -0700553 explicit UnknownRecord(char* p);
Yabin Cui8f622512015-05-05 19:58:07 -0700554
555 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700556 void DumpData(size_t indent) const override;
557};
558
Yabin Cui190a8482016-08-04 10:22:17 -0700559// Read record from the buffer pointed by [p]. But the record doesn't own
560// the buffer.
Yabin Cui3d4aa262017-11-01 15:58:55 -0700561std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700562
563// Read record from the buffer pointed by [p]. And the record owns the buffer.
564std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
Yabin Cui3d4aa262017-11-01 15:58:55 -0700565 uint32_t type, char* p);
Yabin Cui190a8482016-08-04 10:22:17 -0700566
567// Read records from the buffer pointed by [buf]. None of the records own
568// the buffer.
Yabin Cui767dd172016-06-02 21:02:43 -0700569std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
Yabin Cui3d4aa262017-11-01 15:58:55 -0700570 const perf_event_attr& attr, char* buf, size_t buf_size);
Yabin Cui767dd172016-06-02 21:02:43 -0700571
Yabin Cui2ea6de12016-10-24 19:13:09 -0700572// Read one record from the buffer pointed by [p]. But the record doesn't
573// own the buffer.
Yabin Cui3d4aa262017-11-01 15:58:55 -0700574std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p);
Yabin Cui2ea6de12016-10-24 19:13:09 -0700575
Yabin Cuif469c3d2015-10-07 15:00:46 -0700576// RecordCache is a cache used when receiving records from the kernel.
577// It sorts received records based on type and timestamp, and pops records
578// in sorted order. Records from the kernel need to be sorted because
579// records may come from different cpus at the same time, and it is affected
580// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700581// RecordCache pushes records and pops sorted record online. It uses two checks
582// to help ensure that records are popped in order. Each time we pop a record A,
583// it is the earliest record among all records in the cache. In addition, we
584// have checks for min_cache_size and min_time_diff. For min_cache_size check,
585// we check if the cache size >= min_cache_size, which is based on the
586// assumption that if we have received (min_cache_size - 1) records after
587// record A, we are not likely to receive a record earlier than A. For
588// min_time_diff check, we check if record A is generated min_time_diff ns
589// earlier than the latest record, which is based on the assumption that if we
590// have received a record for time t, we are not likely to receive a record for
591// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700592class RecordCache {
593 public:
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -0700594 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700595 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700596 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700597 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700598 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700599 std::unique_ptr<Record> Pop();
600 std::vector<std::unique_ptr<Record>> PopAll();
Yabin Cuifc22b8f2016-08-04 14:47:50 -0700601 std::unique_ptr<Record> ForcedPop();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700602
603 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800604 struct RecordWithSeq {
605 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700606 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800607
Yabin Cuicf31e9d2016-07-14 14:29:33 -0700608 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
Yabin Cui4913c122016-01-11 17:15:55 -0800609 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700610 };
611
Yabin Cui4913c122016-01-11 17:15:55 -0800612 struct RecordComparator {
613 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
614 };
615
Yabin Cuif469c3d2015-10-07 15:00:46 -0700616 bool has_timestamp_;
617 size_t min_cache_size_;
618 uint64_t min_time_diff_in_ns_;
619 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800620 uint32_t cur_seq_;
621 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700622 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700623};
624
Yabin Cui9759e1b2015-04-28 15:54:13 -0700625#endif // SIMPLE_PERF_RECORD_H_