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