blob: 85dcbc7090ec9956aed52f3e8b500c5e797d89cb [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 Cui8f622512015-05-05 19:58:07 -070028#include "build_id.h"
Yabin Cui9759e1b2015-04-28 15:54:13 -070029#include "perf_event.h"
30
31struct KernelMmap;
32struct ModuleMmap;
33struct ThreadComm;
34struct ThreadMmap;
35
36enum user_record_type {
37 PERF_RECORD_ATTR = 64,
38 PERF_RECORD_EVENT_TYPE,
39 PERF_RECORD_TRACING_DATA,
40 PERF_RECORD_BUILD_ID,
41 PERF_RECORD_FINISHED_ROUND,
42};
43
44struct PerfSampleIpType {
45 uint64_t ip;
46};
47
48struct PerfSampleTidType {
49 uint32_t pid, tid;
50};
51
52struct PerfSampleTimeType {
53 uint64_t time;
54};
55
56struct PerfSampleAddrType {
57 uint64_t addr;
58};
59
60struct PerfSampleIdType {
61 uint64_t id;
62};
63
64struct PerfSampleStreamIdType {
65 uint64_t stream_id;
66};
67
68struct PerfSampleCpuType {
69 uint32_t cpu, res;
70};
71
72struct PerfSamplePeriodType {
73 uint64_t period;
74};
75
Yabin Cui6e8a9a42015-06-15 14:36:43 -070076struct PerfSampleCallChainType {
77 std::vector<uint64_t> ips;
78};
79
Yabin Cuibfc11b62015-08-19 10:12:51 -070080struct PerfSampleRawType {
81 std::vector<char> data;
82};
83
Yabin Cuib64a8632016-05-24 18:23:33 -070084struct BranchStackItemType {
85 uint64_t from;
86 uint64_t to;
87 uint64_t flags;
88};
89
Yabin Cuiddddc062015-06-02 17:54:52 -070090struct PerfSampleBranchStackType {
Yabin Cuiddddc062015-06-02 17:54:52 -070091 std::vector<BranchStackItemType> stack;
92};
93
Yabin Cui76769e52015-07-13 12:23:54 -070094struct PerfSampleRegsUserType {
95 uint64_t abi;
96 uint64_t reg_mask;
97 std::vector<uint64_t> regs;
98};
99
100struct PerfSampleStackUserType {
101 std::vector<char> data;
102 uint64_t dyn_size;
103};
104
Yabin Cui9759e1b2015-04-28 15:54:13 -0700105// SampleId is optional at the end of a record in binary format. Its content is determined by
106// sample_id_all and sample_type in perf_event_attr. To avoid the complexity of referring to
107// perf_event_attr each time, we copy sample_id_all and sample_type inside the SampleId structure.
108struct SampleId {
109 bool sample_id_all;
110 uint64_t sample_type;
111
112 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
113 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
114 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
115 PerfSampleStreamIdType stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
116 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
117
118 SampleId();
119
120 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700121 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700122
123 // Parse sample_id from binary format in the buffer pointed by p.
124 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
125
126 // Write the binary format of sample_id to the buffer pointed by p.
127 void WriteToBinaryFormat(char*& p) const;
128 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800129 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700130};
131
132// Usually one record contains the following three parts in order in binary format:
133// perf_event_header (at the head of a record, containing type and size information)
134// data depends on the record type
135// sample_id (optional part at the end of a record)
136// We hold the common parts (perf_event_header and sample_id) in the base class Record, and
137// hold the type specific data part in classes derived from Record.
138struct Record {
139 perf_event_header header;
140 SampleId sample_id;
141
142 Record();
143 Record(const perf_event_header* pheader);
144
145 virtual ~Record() {
146 }
147
Yabin Cuib7f481f2015-10-23 19:48:42 -0700148 size_t size() const {
149 return header.size;
150 }
151
152 uint32_t type() const {
153 return header.type;
154 }
155
Yabin Cuib64a8632016-05-24 18:23:33 -0700156 bool InKernel() const {
157 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_KERNEL;
158 }
159
Yabin Cui9759e1b2015-04-28 15:54:13 -0700160 void Dump(size_t indent = 0) const;
Yabin Cuicb84c982015-09-30 17:22:35 -0700161 virtual std::vector<char> BinaryFormat() const = 0;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700162 virtual uint64_t Timestamp() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700163
164 protected:
Yabin Cuicb84c982015-09-30 17:22:35 -0700165 virtual void DumpData(size_t) const = 0;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700166};
167
168struct MmapRecord : public Record {
169 struct MmapRecordDataType {
170 uint32_t pid, tid;
171 uint64_t addr;
172 uint64_t len;
173 uint64_t pgoff;
174 } data;
175 std::string filename;
176
Yabin Cuicb84c982015-09-30 17:22:35 -0700177 MmapRecord() { // For CreateMmapRecord.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700178 }
179
180 MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700181 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800182 void AdjustSizeBasedOnData();
Yabin Cui8f622512015-05-05 19:58:07 -0700183
184 protected:
185 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700186};
187
Yabin Cui41d4ba92015-06-22 12:27:58 -0700188struct Mmap2Record : public Record {
189 struct Mmap2RecordDataType {
190 uint32_t pid, tid;
191 uint64_t addr;
192 uint64_t len;
193 uint64_t pgoff;
194 uint32_t maj;
195 uint32_t min;
196 uint64_t ino;
197 uint64_t ino_generation;
198 uint32_t prot, flags;
199 } data;
200 std::string filename;
201
202 Mmap2Record() {
203 }
204
205 Mmap2Record(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700206 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800207 void AdjustSizeBasedOnData();
Yabin Cui41d4ba92015-06-22 12:27:58 -0700208
209 protected:
210 void DumpData(size_t indent) const override;
211};
212
Yabin Cui9759e1b2015-04-28 15:54:13 -0700213struct CommRecord : public Record {
214 struct CommRecordDataType {
215 uint32_t pid, tid;
216 } data;
217 std::string comm;
218
219 CommRecord() {
220 }
221
222 CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700223 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700224
225 protected:
226 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700227};
228
Yabin Cui41d4ba92015-06-22 12:27:58 -0700229struct ExitOrForkRecord : public Record {
230 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700231 uint32_t pid, ppid;
232 uint32_t tid, ptid;
233 uint64_t time;
234 } data;
235
Yabin Cui41d4ba92015-06-22 12:27:58 -0700236 ExitOrForkRecord() {
237 }
238 ExitOrForkRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700239 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700240
241 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700242 void DumpData(size_t indent) const override;
243};
244
Yabin Cui41d4ba92015-06-22 12:27:58 -0700245struct ExitRecord : public ExitOrForkRecord {
246 ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader)
247 : ExitOrForkRecord(attr, pheader) {
248 }
249};
250
251struct ForkRecord : public ExitOrForkRecord {
252 ForkRecord() {
253 }
254 ForkRecord(const perf_event_attr& attr, const perf_event_header* pheader)
255 : ExitOrForkRecord(attr, pheader) {
256 }
Yabin Cui41d4ba92015-06-22 12:27:58 -0700257};
258
Yabin Cui9759e1b2015-04-28 15:54:13 -0700259struct SampleRecord : public Record {
260 uint64_t sample_type; // sample_type is a bit mask determining which fields below are valid.
261
262 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
263 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
264 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
265 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
266 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
267 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
268 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
269 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
270
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700271 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
Yabin Cuibfc11b62015-08-19 10:12:51 -0700272 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
Yabin Cuiddddc062015-06-02 17:54:52 -0700273 PerfSampleBranchStackType branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
Yabin Cui76769e52015-07-13 12:23:54 -0700274 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
275 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700276
Yabin Cui9759e1b2015-04-28 15:54:13 -0700277 SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700278 std::vector<char> BinaryFormat() const override;
279 void AdjustSizeBasedOnData();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700280 uint64_t Timestamp() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700281
282 protected:
283 void DumpData(size_t indent) const override;
284};
285
286// BuildIdRecord is defined in user-space, stored in BuildId feature section in record file.
287struct BuildIdRecord : public Record {
288 uint32_t pid;
289 BuildId build_id;
290 std::string filename;
291
292 BuildIdRecord() {
293 }
294
295 BuildIdRecord(const perf_event_header* pheader);
Yabin Cuicb84c982015-09-30 17:22:35 -0700296 std::vector<char> BinaryFormat() const override;
297
298 protected:
299 void DumpData(size_t indent) const override;
300};
301
302// UnknownRecord is used for unknown record types, it makes sure all unknown records
303// are not changed when modifying perf.data.
304struct UnknownRecord : public Record {
305 std::vector<char> data;
306
307 UnknownRecord(const perf_event_header* pheader);
308 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700309
310 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700311 void DumpData(size_t indent) const override;
312};
313
Yabin Cuif469c3d2015-10-07 15:00:46 -0700314// RecordCache is a cache used when receiving records from the kernel.
315// It sorts received records based on type and timestamp, and pops records
316// in sorted order. Records from the kernel need to be sorted because
317// records may come from different cpus at the same time, and it is affected
318// by the order in which we collect records from different cpus.
319// RecordCache pushes records and pops sorted record online. It uses two checks to help
320// ensure that records are popped in order. Each time we pop a record A, it is the earliest record
321// among all records in the cache. In addition, we have checks for min_cache_size and
322// min_time_diff. For min_cache_size check, we check if the cache size >= min_cache_size,
323// which is based on the assumption that if we have received (min_cache_size - 1) records
324// after record A, we are not likely to receive a record earlier than A. For min_time_diff
325// check, we check if record A is generated min_time_diff ns earlier than the latest
326// record, which is based on the assumption that if we have received a record for time t,
327// we are not likely to receive a record for time (t - min_time_diff) or earlier.
328class RecordCache {
329 public:
Yabin Cui2d6efe42016-04-01 20:22:35 -0700330 RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuib7f481f2015-10-23 19:48:42 -0700331 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700332 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700333 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700334 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700335 std::unique_ptr<Record> Pop();
336 std::vector<std::unique_ptr<Record>> PopAll();
337
338 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800339 struct RecordWithSeq {
340 uint32_t seq;
341 Record *record;
342
343 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700344 };
345
Yabin Cui4913c122016-01-11 17:15:55 -0800346 struct RecordComparator {
347 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
348 };
349
350 RecordWithSeq CreateRecordWithSeq(Record *r);
351
Yabin Cuif469c3d2015-10-07 15:00:46 -0700352 bool has_timestamp_;
353 size_t min_cache_size_;
354 uint64_t min_time_diff_in_ns_;
355 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800356 uint32_t cur_seq_;
357 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
358 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700359};
360
Yabin Cui2d6efe42016-04-01 20:22:35 -0700361std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
362 const perf_event_header* pheader);
Yabin Cui73d80782015-07-23 21:39:57 -0700363std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr,
364 const char* buf, size_t buf_size);
Yabin Cui7d59bb42015-05-04 20:27:57 -0700365MmapRecord CreateMmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
366 uint64_t addr, uint64_t len, uint64_t pgoff,
Yabin Cui2d6efe42016-04-01 20:22:35 -0700367 const std::string& filename, uint64_t event_id);
Yabin Cui7d59bb42015-05-04 20:27:57 -0700368CommRecord CreateCommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
Yabin Cui2d6efe42016-04-01 20:22:35 -0700369 const std::string& comm, uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700370ForkRecord CreateForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid,
Yabin Cui2d6efe42016-04-01 20:22:35 -0700371 uint32_t ptid, uint64_t event_id);
Yabin Cui8f622512015-05-05 19:58:07 -0700372BuildIdRecord CreateBuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
373 const std::string& filename);
Yabin Cui73d80782015-07-23 21:39:57 -0700374
Yabin Cui9759e1b2015-04-28 15:54:13 -0700375#endif // SIMPLE_PERF_RECORD_H_