OSDN Git Service

Merge "Add support for iif rules."
[android-x86/system-extras.git] / simpleperf / record.h
1 /*
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
20 #include <stdio.h>
21 #include <sys/types.h>
22
23 #include <queue>
24 #include <string>
25 #include <vector>
26
27 #include "build_id.h"
28 #include "perf_event.h"
29
30 struct KernelMmap;
31 struct ModuleMmap;
32 struct ThreadComm;
33 struct ThreadMmap;
34
35 enum user_record_type {
36   PERF_RECORD_ATTR = 64,
37   PERF_RECORD_EVENT_TYPE,
38   PERF_RECORD_TRACING_DATA,
39   PERF_RECORD_BUILD_ID,
40   PERF_RECORD_FINISHED_ROUND,
41 };
42
43 struct PerfSampleIpType {
44   uint64_t ip;
45 };
46
47 struct PerfSampleTidType {
48   uint32_t pid, tid;
49 };
50
51 struct PerfSampleTimeType {
52   uint64_t time;
53 };
54
55 struct PerfSampleAddrType {
56   uint64_t addr;
57 };
58
59 struct PerfSampleIdType {
60   uint64_t id;
61 };
62
63 struct PerfSampleStreamIdType {
64   uint64_t stream_id;
65 };
66
67 struct PerfSampleCpuType {
68   uint32_t cpu, res;
69 };
70
71 struct PerfSamplePeriodType {
72   uint64_t period;
73 };
74
75 struct PerfSampleCallChainType {
76   std::vector<uint64_t> ips;
77 };
78
79 struct PerfSampleRawType {
80   std::vector<char> data;
81 };
82
83 struct PerfSampleBranchStackType {
84   struct BranchStackItemType {
85     uint64_t from;
86     uint64_t to;
87     uint64_t flags;
88   };
89   std::vector<BranchStackItemType> stack;
90 };
91
92 struct PerfSampleRegsUserType {
93   uint64_t abi;
94   uint64_t reg_mask;
95   std::vector<uint64_t> regs;
96 };
97
98 struct PerfSampleStackUserType {
99   std::vector<char> data;
100   uint64_t dyn_size;
101 };
102
103 // SampleId is optional at the end of a record in binary format. Its content is determined by
104 // sample_id_all and sample_type in perf_event_attr. To avoid the complexity of referring to
105 // perf_event_attr each time, we copy sample_id_all and sample_type inside the SampleId structure.
106 struct SampleId {
107   bool sample_id_all;
108   uint64_t sample_type;
109
110   PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
111   PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
112   PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
113   PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
114   PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.
115
116   SampleId();
117
118   // Create the content of sample_id. It depends on the attr we use.
119   size_t CreateContent(const perf_event_attr& attr);
120
121   // Parse sample_id from binary format in the buffer pointed by p.
122   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
123
124   // Write the binary format of sample_id to the buffer pointed by p.
125   void WriteToBinaryFormat(char*& p) const;
126   void Dump(size_t indent) const;
127 };
128
129 // Usually one record contains the following three parts in order in binary format:
130 //   perf_event_header (at the head of a record, containing type and size information)
131 //   data depends on the record type
132 //   sample_id (optional part at the end of a record)
133 // We hold the common parts (perf_event_header and sample_id) in the base class Record, and
134 // hold the type specific data part in classes derived from Record.
135 struct Record {
136   perf_event_header header;
137   SampleId sample_id;
138
139   Record();
140   Record(const perf_event_header* pheader);
141
142   virtual ~Record() {
143   }
144
145   size_t size() const {
146     return header.size;
147   }
148
149   uint32_t type() const {
150     return header.type;
151   }
152
153   void Dump(size_t indent = 0) const;
154   virtual std::vector<char> BinaryFormat() const = 0;
155   virtual uint64_t Timestamp() const;
156
157  protected:
158   virtual void DumpData(size_t) const = 0;
159 };
160
161 struct MmapRecord : public Record {
162   struct MmapRecordDataType {
163     uint32_t pid, tid;
164     uint64_t addr;
165     uint64_t len;
166     uint64_t pgoff;
167   } data;
168   std::string filename;
169
170   MmapRecord() {  // For CreateMmapRecord.
171   }
172
173   MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
174   std::vector<char> BinaryFormat() const override;
175
176  protected:
177   void DumpData(size_t indent) const override;
178 };
179
180 struct Mmap2Record : public Record {
181   struct Mmap2RecordDataType {
182     uint32_t pid, tid;
183     uint64_t addr;
184     uint64_t len;
185     uint64_t pgoff;
186     uint32_t maj;
187     uint32_t min;
188     uint64_t ino;
189     uint64_t ino_generation;
190     uint32_t prot, flags;
191   } data;
192   std::string filename;
193
194   Mmap2Record() {
195   }
196
197   Mmap2Record(const perf_event_attr& attr, const perf_event_header* pheader);
198   std::vector<char> BinaryFormat() const override;
199
200  protected:
201   void DumpData(size_t indent) const override;
202 };
203
204 struct CommRecord : public Record {
205   struct CommRecordDataType {
206     uint32_t pid, tid;
207   } data;
208   std::string comm;
209
210   CommRecord() {
211   }
212
213   CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
214   std::vector<char> BinaryFormat() const override;
215
216  protected:
217   void DumpData(size_t indent) const override;
218 };
219
220 struct ExitOrForkRecord : public Record {
221   struct ExitOrForkRecordDataType {
222     uint32_t pid, ppid;
223     uint32_t tid, ptid;
224     uint64_t time;
225   } data;
226
227   ExitOrForkRecord() {
228   }
229   ExitOrForkRecord(const perf_event_attr& attr, const perf_event_header* pheader);
230   std::vector<char> BinaryFormat() const override;
231
232  protected:
233   void DumpData(size_t indent) const override;
234 };
235
236 struct ExitRecord : public ExitOrForkRecord {
237   ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader)
238       : ExitOrForkRecord(attr, pheader) {
239   }
240 };
241
242 struct ForkRecord : public ExitOrForkRecord {
243   ForkRecord() {
244   }
245   ForkRecord(const perf_event_attr& attr, const perf_event_header* pheader)
246       : ExitOrForkRecord(attr, pheader) {
247   }
248 };
249
250 struct SampleRecord : public Record {
251   uint64_t sample_type;  // sample_type is a bit mask determining which fields below are valid.
252
253   PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
254   PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
255   PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
256   PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
257   PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
258   PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
259   PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
260   PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
261
262   PerfSampleCallChainType callchain_data;       // Valid if PERF_SAMPLE_CALLCHAIN.
263   PerfSampleRawType raw_data;                   // Valid if PERF_SAMPLE_RAW.
264   PerfSampleBranchStackType branch_stack_data;  // Valid if PERF_SAMPLE_BRANCH_STACK.
265   PerfSampleRegsUserType regs_user_data;        // Valid if PERF_SAMPLE_REGS_USER.
266   PerfSampleStackUserType stack_user_data;      // Valid if PERF_SAMPLE_STACK_USER.
267
268   SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
269   std::vector<char> BinaryFormat() const override;
270   void AdjustSizeBasedOnData();
271   uint64_t Timestamp() const override;
272
273  protected:
274   void DumpData(size_t indent) const override;
275 };
276
277 // BuildIdRecord is defined in user-space, stored in BuildId feature section in record file.
278 struct BuildIdRecord : public Record {
279   uint32_t pid;
280   BuildId build_id;
281   std::string filename;
282
283   BuildIdRecord() {
284   }
285
286   BuildIdRecord(const perf_event_header* pheader);
287   std::vector<char> BinaryFormat() const override;
288
289  protected:
290   void DumpData(size_t indent) const override;
291 };
292
293 // UnknownRecord is used for unknown record types, it makes sure all unknown records
294 // are not changed when modifying perf.data.
295 struct UnknownRecord : public Record {
296   std::vector<char> data;
297
298   UnknownRecord(const perf_event_header* pheader);
299   std::vector<char> BinaryFormat() const override;
300
301  protected:
302   void DumpData(size_t indent) const override;
303 };
304
305 // RecordCache is a cache used when receiving records from the kernel.
306 // It sorts received records based on type and timestamp, and pops records
307 // in sorted order. Records from the kernel need to be sorted because
308 // records may come from different cpus at the same time, and it is affected
309 // by the order in which we collect records from different cpus.
310 // RecordCache pushes records and pops sorted record online. It uses two checks to help
311 // ensure that records are popped in order. Each time we pop a record A, it is the earliest record
312 // among all records in the cache. In addition, we have checks for min_cache_size and
313 // min_time_diff. For min_cache_size check, we check if the cache size >= min_cache_size,
314 // which is based on the assumption that if we have received (min_cache_size - 1) records
315 // after record A, we are not likely to receive a record earlier than A. For min_time_diff
316 // check, we check if record A is generated min_time_diff ns earlier than the latest
317 // record, which is based on the assumption that if we have received a record for time t,
318 // we are not likely to receive a record for time (t - min_time_diff) or earlier.
319 class RecordCache {
320  public:
321   RecordCache(const perf_event_attr& attr, size_t min_cache_size = 1000u,
322               uint64_t min_time_diff_in_ns = 1000000u);
323   ~RecordCache();
324   void Push(const char* data, size_t size);
325   void Push(std::unique_ptr<Record> record);
326   std::unique_ptr<Record> Pop();
327   std::vector<std::unique_ptr<Record>> PopAll();
328
329  private:
330   struct RecordComparator {
331     bool operator()(const Record* r1, const Record* r2);
332   };
333
334   const perf_event_attr attr_;
335   bool has_timestamp_;
336   size_t min_cache_size_;
337   uint64_t min_time_diff_in_ns_;
338   uint64_t last_time_;
339   std::priority_queue<Record*, std::vector<Record*>, RecordComparator> queue_;
340 };
341
342 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr,
343                                                            const char* buf, size_t buf_size);
344 std::unique_ptr<Record> ReadRecordFromFile(const perf_event_attr& attr, FILE* fp);
345 MmapRecord CreateMmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
346                             uint64_t addr, uint64_t len, uint64_t pgoff,
347                             const std::string& filename);
348 CommRecord CreateCommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
349                             const std::string& comm);
350 ForkRecord CreateForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid,
351                             uint32_t ptid);
352 BuildIdRecord CreateBuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
353                                   const std::string& filename);
354
355 #endif  // SIMPLE_PERF_RECORD_H_