• 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 <android-base/logging.h>
29 
30 #include "build_id.h"
31 #include "perf_event.h"
32 
33 enum user_record_type {
34   PERF_RECORD_USER_DEFINED_TYPE_START = 64,
35   PERF_RECORD_ATTR = 64,
36   PERF_RECORD_EVENT_TYPE,
37   PERF_RECORD_TRACING_DATA,
38   PERF_RECORD_BUILD_ID,
39   PERF_RECORD_FINISHED_ROUND,
40 
41   SIMPLE_PERF_RECORD_TYPE_START = 32768,
42   SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
43   // TODO: remove DsoRecord and SymbolRecord.
44   SIMPLE_PERF_RECORD_DSO,
45   SIMPLE_PERF_RECORD_SYMBOL,
46   SIMPLE_PERF_RECORD_SPLIT,
47   SIMPLE_PERF_RECORD_SPLIT_END,
48   SIMPLE_PERF_RECORD_EVENT_ID,
49 };
50 
51 // 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).
55 struct simpleperf_record_header {
56   uint32_t type;
57   uint16_t size1;
58   uint16_t size0;
59 };
60 
61 static_assert(
62     sizeof(simpleperf_record_header) == sizeof(perf_event_header),
63     "simpleperf_record_header should have the same size as perf_event_header");
64 
65 struct PerfSampleIpType {
66   uint64_t ip;
67 };
68 
69 struct PerfSampleTidType {
70   uint32_t pid, tid;
71 };
72 
73 struct PerfSampleTimeType {
74   uint64_t time;
75 };
76 
77 struct PerfSampleAddrType {
78   uint64_t addr;
79 };
80 
81 struct PerfSampleIdType {
82   uint64_t id;
83 };
84 
85 struct PerfSampleStreamIdType {
86   uint64_t stream_id;
87 };
88 
89 struct PerfSampleCpuType {
90   uint32_t cpu, res;
91 };
92 
93 struct PerfSamplePeriodType {
94   uint64_t period;
95 };
96 
97 struct PerfSampleCallChainType {
98   uint64_t ip_nr;
99   const uint64_t* ips;
100 };
101 
102 struct PerfSampleRawType {
103   uint32_t size;
104   const char* data;
105 };
106 
107 struct BranchStackItemType {
108   uint64_t from;
109   uint64_t to;
110   uint64_t flags;
111 };
112 
113 struct PerfSampleBranchStackType {
114   uint64_t stack_nr;
115   const BranchStackItemType* stack;
116 };
117 
118 struct PerfSampleRegsUserType {
119   uint64_t abi;
120   uint64_t reg_mask;
121   uint64_t reg_nr;
122   const uint64_t* regs;
123 };
124 
125 struct PerfSampleStackUserType {
126   uint64_t size;
127   const char* data;
128   uint64_t dyn_size;
129 };
130 
131 struct RecordHeader {
132  public:
133   uint32_t type;
134   uint16_t misc;
135   uint32_t size;
136 
RecordHeaderRecordHeader137   RecordHeader() : type(0), misc(0), size(0) {}
138 
RecordHeaderRecordHeader139   explicit RecordHeader(const char* p) {
140     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 
MoveToBinaryFormatRecordHeader153   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 
171 // 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.
175 struct SampleId {
176   bool sample_id_all;
177   uint64_t sample_type;
178 
179   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.
185 
186   SampleId();
187 
188   // Create the content of sample_id. It depends on the attr we use.
189   size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
190 
191   // Parse sample_id from binary format in the buffer pointed by p.
192   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
193                             const char* end);
194 
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;
198   size_t Size() const;
199 };
200 
201 // Usually one record contains the following three parts in order in binary
202 // format:
203 //   RecordHeader (at the head of a record, containing type and size info)
204 //   data depends on the record type
205 //   SampleId (optional part at the end of a record)
206 // We hold the common parts (RecordHeader and SampleId) in the base class
207 // Record, and hold the type specific data part in classes derived from Record.
208 struct Record {
209   RecordHeader header;
210   SampleId sample_id;
211 
RecordRecord212   Record() : binary_(nullptr), own_binary_(false) {}
RecordRecord213   explicit Record(const char* p) : header(p), binary_(p), own_binary_(false) {}
214   Record(Record&& other);
215 
~RecordRecord216   virtual ~Record() {
217     if (own_binary_) {
218       delete[] binary_;
219     }
220   }
221 
OwnBinaryRecord222   void OwnBinary() { own_binary_ = true; }
223 
typeRecord224   uint32_t type() const { return header.type; }
225 
miscRecord226   uint16_t misc() const { return header.misc; }
227 
sizeRecord228   uint32_t size() const { return header.size; }
229 
header_sizeRecord230   static uint32_t header_size() { return sizeof(perf_event_header); }
231 
InKernelRecord232   bool InKernel() const {
233     return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
234            PERF_RECORD_MISC_KERNEL;
235   }
236 
SetTypeAndMiscRecord237   void SetTypeAndMisc(uint32_t type, uint16_t misc) {
238     header.type = type;
239     header.misc = misc;
240   }
241 
SetSizeRecord242   void SetSize(uint32_t size) { header.size = size; }
243 
244   void Dump(size_t indent = 0) const;
245 
BinaryRecord246   const char* Binary() const { return binary_; }
247 
248   virtual uint64_t Timestamp() const;
249   virtual uint32_t Cpu() const;
250   virtual uint64_t Id() const;
251 
252  protected:
253   void UpdateBinary(const char* new_binary);
254   virtual void DumpData(size_t) const = 0;
255 
256   const char* binary_;
257   bool own_binary_;
258 
259   DISALLOW_COPY_AND_ASSIGN(Record);
260 };
261 
262 struct MmapRecord : public Record {
263   struct MmapRecordDataType {
264     uint32_t pid, tid;
265     uint64_t addr;
266     uint64_t len;
267     uint64_t pgoff;
268   };
269   const MmapRecordDataType* data;
270   const char* filename;
271 
272   MmapRecord(const perf_event_attr& attr, const char* p);
273 
274   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);
280 
281  protected:
282   void DumpData(size_t indent) const override;
283 };
284 
285 struct 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;
296   };
297   const Mmap2RecordDataType* data;
298   const char* filename;
299 
300   Mmap2Record(const perf_event_attr& attr, const char* p);
301 
302   void SetDataAndFilename(const Mmap2RecordDataType& data,
303                           const std::string& filename);
304 
305  protected:
306   void DumpData(size_t indent) const override;
307 };
308 
309 struct CommRecord : public Record {
310   struct CommRecordDataType {
311     uint32_t pid, tid;
312   };
313   const CommRecordDataType* data;
314   const char* comm;
315 
316   CommRecord(const perf_event_attr& attr, const char* p);
317 
318   CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
319              const std::string& comm, uint64_t event_id, uint64_t time);
320 
321  protected:
322   void DumpData(size_t indent) const override;
323 };
324 
325 struct ExitOrForkRecord : public Record {
326   struct ExitOrForkRecordDataType {
327     uint32_t pid, ppid;
328     uint32_t tid, ptid;
329     uint64_t time;
330   };
331   const ExitOrForkRecordDataType* data;
332 
333   ExitOrForkRecord(const perf_event_attr& attr, const char* p);
334 
ExitOrForkRecordExitOrForkRecord335   ExitOrForkRecord() : data(nullptr) {}
336 
337  protected:
338   void DumpData(size_t indent) const override;
339 };
340 
341 struct ExitRecord : public ExitOrForkRecord {
ExitRecordExitRecord342   ExitRecord(const perf_event_attr& attr, const char* p)
343       : ExitOrForkRecord(attr, p) {}
344 };
345 
346 struct ForkRecord : public ExitOrForkRecord {
ForkRecordForkRecord347   ForkRecord(const perf_event_attr& attr, const char* p)
348       : ExitOrForkRecord(attr, p) {}
349 
350   ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
351              uint32_t ppid, uint32_t ptid, uint64_t event_id);
352 };
353 
354 struct LostRecord : public Record {
355   uint64_t id;
356   uint64_t lost;
357 
358   LostRecord(const perf_event_attr& attr, const char* p);
359 
360  protected:
361   void DumpData(size_t indent) const override;
362 };
363 
364 struct SampleRecord : public Record {
365   uint64_t sample_type;  // sample_type is a bit mask determining which fields
366                          // below are valid.
367 
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 
377   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.
383 
384   SampleRecord(const perf_event_attr& attr, const char* p);
385   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 
389   void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
390   uint64_t Timestamp() const override;
391   uint32_t Cpu() const override;
392   uint64_t Id() const override;
393 
GetValidStackSizeSampleRecord394   uint64_t GetValidStackSize() const {
395     // If stack_user_data.dyn_size == 0, it may be because the kernel misses
396     // the patch to update dyn_size, like in N9 (See b/22612370). So assume
397     // all stack data is valid if dyn_size == 0.
398     if (stack_user_data.dyn_size == 0) {
399       return stack_user_data.size;
400     }
401     return stack_user_data.dyn_size;
402   }
403 
404  protected:
405   void DumpData(size_t indent) const override;
406 };
407 
408 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
409 // record file.
410 struct BuildIdRecord : public Record {
411   uint32_t pid;
412   BuildId build_id;
413   const char* filename;
414 
415   explicit BuildIdRecord(const char* p);
416 
417   BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
418                 const std::string& filename);
419 
420  protected:
421   void DumpData(size_t indent) const override;
422 };
423 
424 struct KernelSymbolRecord : public Record {
425   uint32_t kallsyms_size;
426   const char* kallsyms;
427 
428   explicit KernelSymbolRecord(const char* p);
429 
430   explicit KernelSymbolRecord(const std::string& kallsyms);
431 
432  protected:
433   void DumpData(size_t indent) const override;
434 };
435 
436 struct DsoRecord : public Record {
437   uint64_t dso_type;
438   uint64_t dso_id;
439   uint64_t min_vaddr;
440   const char* dso_name;
441 
442   explicit DsoRecord(const char* p);
443 
444   DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
445             uint64_t min_vaddr);
446 
447  protected:
448   void DumpData(size_t indent) const override;
449 };
450 
451 struct SymbolRecord : public Record {
452   uint64_t addr;
453   uint64_t len;
454   uint64_t dso_id;
455   const char* name;
456 
457   explicit SymbolRecord(const char* p);
458 
459   SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
460                uint64_t dso_id);
461 
462  protected:
463   void DumpData(size_t indent) const override;
464 };
465 
466 struct TracingDataRecord : public Record {
467   uint32_t data_size;
468   const char* data;
469 
470   explicit TracingDataRecord(const char* p);
471 
472   explicit TracingDataRecord(const std::vector<char>& tracing_data);
473 
474  protected:
475   void DumpData(size_t indent) const override;
476 };
477 
478 struct EventIdRecord : public Record {
479   uint64_t count;
480   struct EventIdData {
481     uint64_t attr_id;
482     uint64_t event_id;
483   } const* data;
484 
485   explicit EventIdRecord(const char* p);
486 
487   explicit EventIdRecord(const std::vector<uint64_t>& data);
488 
489  protected:
490   void DumpData(size_t indent) const override;
491 };
492 
493 // UnknownRecord is used for unknown record types, it makes sure all unknown
494 // records are not changed when modifying perf.data.
495 struct UnknownRecord : public Record {
496   const char* data;
497 
498   explicit UnknownRecord(const char* p);
499 
500  protected:
501   void DumpData(size_t indent) const override;
502 };
503 
504 // Read record from the buffer pointed by [p]. But the record doesn't own
505 // the buffer.
506 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
507                                              uint32_t type, const char* p);
508 
509 // Read record from the buffer pointed by [p]. And the record owns the buffer.
510 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
511                                                   uint32_t type, const char* p);
512 
513 // Read records from the buffer pointed by [buf]. None of the records own
514 // the buffer.
515 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
516     const perf_event_attr& attr, const char* buf, size_t buf_size);
517 
518 // Read one record from the buffer pointed by [p]. But the record doesn't
519 // own the buffer.
520 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
521                                              const char* p);
522 
523 // RecordCache is a cache used when receiving records from the kernel.
524 // It sorts received records based on type and timestamp, and pops records
525 // in sorted order. Records from the kernel need to be sorted because
526 // records may come from different cpus at the same time, and it is affected
527 // by the order in which we collect records from different cpus.
528 // RecordCache pushes records and pops sorted record online. It uses two checks
529 // to help ensure that records are popped in order. Each time we pop a record A,
530 // it is the earliest record among all records in the cache. In addition, we
531 // have checks for min_cache_size and min_time_diff. For min_cache_size check,
532 // we check if the cache size >= min_cache_size, which is based on the
533 // assumption that if we have received (min_cache_size - 1) records after
534 // record A, we are not likely to receive a record earlier than A. For
535 // min_time_diff check, we check if record A is generated min_time_diff ns
536 // earlier than the latest record, which is based on the assumption that if we
537 // have received a record for time t, we are not likely to receive a record for
538 // time (t - min_time_diff) or earlier.
539 class RecordCache {
540  public:
541   explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
542                        uint64_t min_time_diff_in_ns = 1000000u);
543   ~RecordCache();
544   void Push(std::unique_ptr<Record> record);
545   void Push(std::vector<std::unique_ptr<Record>> records);
546   std::unique_ptr<Record> Pop();
547   std::vector<std::unique_ptr<Record>> PopAll();
548   std::unique_ptr<Record> ForcedPop();
549 
550  private:
551   struct RecordWithSeq {
552     uint32_t seq;
553     Record* record;
554 
RecordWithSeqRecordWithSeq555     RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
556     bool IsHappensBefore(const RecordWithSeq& other) const;
557   };
558 
559   struct RecordComparator {
560     bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
561   };
562 
563   bool has_timestamp_;
564   size_t min_cache_size_;
565   uint64_t min_time_diff_in_ns_;
566   uint64_t last_time_;
567   uint32_t cur_seq_;
568   std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
569                       RecordComparator> queue_;
570 };
571 
572 #endif  // SIMPLE_PERF_RECORD_H_
573