• 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 "CallChainJoiner.h"
31 #include "OfflineUnwinder.h"
32 #include "build_id.h"
33 #include "perf_event.h"
34 
35 namespace simpleperf {
36 
37 enum user_record_type {
38   PERF_RECORD_USER_DEFINED_TYPE_START = 64,
39   PERF_RECORD_ATTR = 64,
40   PERF_RECORD_EVENT_TYPE,
41   PERF_RECORD_TRACING_DATA,
42   PERF_RECORD_BUILD_ID,
43   PERF_RECORD_FINISHED_ROUND,
44 
45   PERF_RECORD_AUXTRACE_INFO = 70,
46   PERF_RECORD_AUXTRACE = 71,
47 
48   SIMPLE_PERF_RECORD_TYPE_START = 32768,
49   SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
50   // TODO: remove DsoRecord and SymbolRecord.
51   SIMPLE_PERF_RECORD_DSO,
52   SIMPLE_PERF_RECORD_SYMBOL,
53   SIMPLE_PERF_RECORD_SPLIT,
54   SIMPLE_PERF_RECORD_SPLIT_END,
55   SIMPLE_PERF_RECORD_EVENT_ID,
56   SIMPLE_PERF_RECORD_CALLCHAIN,
57   SIMPLE_PERF_RECORD_UNWINDING_RESULT,
58   SIMPLE_PERF_RECORD_TRACING_DATA,
59 };
60 
61 // perf_event_header uses u16 to store record size. However, that is not
62 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
63 // a simpleperf_record_header struct to store record header for simpleperf
64 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
65 struct simpleperf_record_header {
66   uint32_t type;
67   uint16_t size1;
68   uint16_t size0;
69 };
70 
71 static_assert(sizeof(simpleperf_record_header) == sizeof(perf_event_header),
72               "simpleperf_record_header should have the same size as perf_event_header");
73 
74 struct PerfSampleIpType {
75   uint64_t ip;
76 };
77 
78 struct PerfSampleTidType {
79   uint32_t pid, tid;
80 };
81 
82 struct PerfSampleTimeType {
83   uint64_t time;
84 };
85 
86 struct PerfSampleAddrType {
87   uint64_t addr;
88 };
89 
90 struct PerfSampleIdType {
91   uint64_t id;
92 };
93 
94 struct PerfSampleStreamIdType {
95   uint64_t stream_id;
96 };
97 
98 struct PerfSampleCpuType {
99   uint32_t cpu, res;
100 };
101 
102 struct PerfSamplePeriodType {
103   uint64_t period;
104 };
105 
106 struct PerfSampleCallChainType {
107   uint64_t ip_nr;
108   uint64_t* ips;
109 };
110 
111 struct PerfSampleRawType {
112   uint32_t size;
113   const char* data;
114 };
115 
116 struct BranchStackItemType {
117   uint64_t from;
118   uint64_t to;
119   uint64_t flags;
120 };
121 
122 struct PerfSampleBranchStackType {
123   uint64_t stack_nr;
124   const BranchStackItemType* stack;
125 };
126 
127 struct PerfSampleRegsUserType {
128   uint64_t abi;
129   uint64_t reg_mask;
130   uint64_t reg_nr;
131   const uint64_t* regs;
132 };
133 
134 struct PerfSampleStackUserType {
135   uint64_t size;
136   char* data;
137   uint64_t dyn_size;
138 };
139 
140 struct RecordHeader {
141  public:
142   uint32_t type;
143   uint16_t misc;
144   uint32_t size;
145 
RecordHeaderRecordHeader146   RecordHeader() : type(0), misc(0), size(0) {}
147 
RecordHeaderRecordHeader148   explicit RecordHeader(const char* p) {
149     auto pheader = reinterpret_cast<const perf_event_header*>(p);
150     if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
151       type = pheader->type;
152       misc = pheader->misc;
153       size = pheader->size;
154     } else {
155       auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
156       type = sheader->type;
157       misc = 0;
158       size = (sheader->size1 << 16) | sheader->size0;
159     }
160   }
161 
MoveToBinaryFormatRecordHeader162   void MoveToBinaryFormat(char*& p) const {
163     if (type < SIMPLE_PERF_RECORD_TYPE_START) {
164       auto pheader = reinterpret_cast<perf_event_header*>(p);
165       pheader->type = type;
166       pheader->misc = misc;
167       CHECK_LT(size, 1u << 16);
168       pheader->size = static_cast<uint16_t>(size);
169     } else {
170       auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
171       sheader->type = type;
172       CHECK_EQ(misc, 0u);
173       sheader->size1 = size >> 16;
174       sheader->size0 = size & 0xffff;
175     }
176     p += sizeof(perf_event_header);
177   }
178 };
179 
180 // SampleId is optional at the end of a record in binary format. Its content is
181 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the
182 // complexity of referring to perf_event_attr each time, we copy sample_id_all
183 // and sample_type inside the SampleId structure.
184 struct SampleId {
185   bool sample_id_all;
186   uint64_t sample_type;
187 
188   PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
189   PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
190   PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
191   PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
192   PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.
193 
194   SampleId();
195 
196   // Create the content of sample_id. It depends on the attr we use.
197   size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
198 
199   // Parse sample_id from binary format in the buffer pointed by p.
200   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
201 
202   // Write the binary format of sample_id to the buffer pointed by p.
203   void WriteToBinaryFormat(char*& p) const;
204   void Dump(size_t indent) const;
205   size_t Size() const;
206 };
207 
208 // Usually one record contains the following three parts in order in binary
209 // format:
210 //   RecordHeader (at the head of a record, containing type and size info)
211 //   data depends on the record type
212 //   SampleId (optional part at the end of a record)
213 // We hold the common parts (RecordHeader and SampleId) in the base class
214 // Record, and hold the type specific data part in classes derived from Record.
215 struct Record {
216   RecordHeader header;
217   SampleId sample_id;
218 
RecordRecord219   Record() : binary_(nullptr), own_binary_(false) {}
RecordRecord220   explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {}
221   Record(Record&& other) noexcept;
222 
~RecordRecord223   virtual ~Record() {
224     if (own_binary_) {
225       delete[] binary_;
226     }
227   }
228 
OwnBinaryRecord229   void OwnBinary() { own_binary_ = true; }
230 
typeRecord231   uint32_t type() const { return header.type; }
232 
miscRecord233   uint16_t misc() const { return header.misc; }
234 
sizeRecord235   uint32_t size() const { return header.size; }
236 
header_sizeRecord237   static uint32_t header_size() { return sizeof(perf_event_header); }
238 
InKernelRecord239   bool InKernel() const {
240     uint16_t cpumode = header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
241     return cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL;
242   }
243 
SetTypeAndMiscRecord244   void SetTypeAndMisc(uint32_t type, uint16_t misc) {
245     header.type = type;
246     header.misc = misc;
247   }
248 
SetSizeRecord249   void SetSize(uint32_t size) { header.size = size; }
250 
251   void Dump(size_t indent = 0) const;
252 
BinaryRecord253   const char* Binary() const { return binary_; }
BinaryForTestingOnlyRecord254   char* BinaryForTestingOnly() { return binary_; }
255 
256   virtual uint64_t Timestamp() const;
257   virtual uint32_t Cpu() const;
258   virtual uint64_t Id() const;
259 
260  protected:
261   void UpdateBinary(char* new_binary);
262   virtual void DumpData(size_t) const = 0;
263 
264   char* binary_;
265   bool own_binary_;
266 
267   DISALLOW_COPY_AND_ASSIGN(Record);
268 };
269 
270 struct MmapRecord : public Record {
271   struct MmapRecordDataType {
272     uint32_t pid, tid;
273     uint64_t addr;
274     uint64_t len;
275     uint64_t pgoff;
276   };
277   const MmapRecordDataType* data;
278   const char* filename;
279 
280   MmapRecord(const perf_event_attr& attr, char* p);
281 
282   MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, uint64_t addr,
283              uint64_t len, uint64_t pgoff, const std::string& filename, uint64_t event_id,
284              uint64_t time = 0);
285 
286   void SetDataAndFilename(const MmapRecordDataType& data, const std::string& filename);
287 
288  protected:
289   void DumpData(size_t indent) const override;
290 };
291 
292 struct Mmap2Record : public Record {
293   struct Mmap2RecordDataType {
294     uint32_t pid, tid;
295     uint64_t addr;
296     uint64_t len;
297     uint64_t pgoff;
298     uint32_t maj;
299     uint32_t min;
300     uint64_t ino;
301     uint64_t ino_generation;
302     uint32_t prot, flags;
303   };
304   const Mmap2RecordDataType* data;
305   const char* filename;
306 
307   Mmap2Record(const perf_event_attr& attr, char* p);
308   Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
309               uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot,
310               const std::string& filename, uint64_t event_id, uint64_t time = 0);
311 
312   void SetDataAndFilename(const Mmap2RecordDataType& data, const std::string& filename);
313 
314  protected:
315   void DumpData(size_t indent) const override;
316 };
317 
318 struct CommRecord : public Record {
319   struct CommRecordDataType {
320     uint32_t pid, tid;
321   };
322   const CommRecordDataType* data;
323   const char* comm;
324 
325   CommRecord(const perf_event_attr& attr, char* p);
326 
327   CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, const std::string& comm,
328              uint64_t event_id, uint64_t time);
329 
330   void SetCommandName(const std::string& name);
331 
332  protected:
333   void DumpData(size_t indent) const override;
334 };
335 
336 struct ExitOrForkRecord : public Record {
337   struct ExitOrForkRecordDataType {
338     uint32_t pid, ppid;
339     uint32_t tid, ptid;
340     uint64_t time;
341   };
342   const ExitOrForkRecordDataType* data;
343 
344   ExitOrForkRecord(const perf_event_attr& attr, char* p);
345 
ExitOrForkRecordExitOrForkRecord346   ExitOrForkRecord() : data(nullptr) {}
347 
348  protected:
349   void DumpData(size_t indent) const override;
350 };
351 
352 struct ExitRecord : public ExitOrForkRecord {
ExitRecordExitRecord353   ExitRecord(const perf_event_attr& attr, char* p) : ExitOrForkRecord(attr, p) {}
354 };
355 
356 struct ForkRecord : public ExitOrForkRecord {
ForkRecordForkRecord357   ForkRecord(const perf_event_attr& attr, char* p) : ExitOrForkRecord(attr, p) {}
358 
359   ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid, uint32_t ptid,
360              uint64_t event_id);
361 };
362 
363 struct LostRecord : public Record {
364   uint64_t id;
365   uint64_t lost;
366 
367   LostRecord(const perf_event_attr& attr, char* p);
368 
369  protected:
370   void DumpData(size_t indent) const override;
371 };
372 
373 struct SampleRecord : public Record {
374   uint64_t sample_type;  // sample_type is a bit mask determining which fields
375                          // below are valid.
376 
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 
386   PerfSampleCallChainType callchain_data;       // Valid if PERF_SAMPLE_CALLCHAIN.
387   PerfSampleRawType raw_data;                   // Valid if PERF_SAMPLE_RAW.
388   PerfSampleBranchStackType branch_stack_data;  // Valid if PERF_SAMPLE_BRANCH_STACK.
389   PerfSampleRegsUserType regs_user_data;        // Valid if PERF_SAMPLE_REGS_USER.
390   PerfSampleStackUserType stack_user_data;      // Valid if PERF_SAMPLE_STACK_USER.
391 
392   SampleRecord(const perf_event_attr& attr, char* p);
393   SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, uint32_t pid, uint32_t tid,
394                uint64_t time, uint32_t cpu, uint64_t period, const std::vector<uint64_t>& ips,
395                const std::vector<char>& stack, uint64_t dyn_stack_size);
396 
397   void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
398   // Remove kernel callchain, return true if there is a user space callchain left, otherwise
399   // return false.
400   bool ExcludeKernelCallChain();
401   bool HasUserCallChain() const;
402   void UpdateUserCallChain(const std::vector<uint64_t>& user_ips);
403 
404   uint64_t Timestamp() const override;
405   uint32_t Cpu() const override;
406   uint64_t Id() const override;
407 
GetValidStackSizeSampleRecord408   uint64_t GetValidStackSize() const {
409     // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer().
410     return stack_user_data.size;
411   }
412 
413   void AdjustCallChainGeneratedByKernel();
414   std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const;
415 
416  protected:
417   void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips);
418   void DumpData(size_t indent) const override;
419 };
420 
421 struct AuxRecord : public Record {
422   struct DataType {
423     uint64_t aux_offset;
424     uint64_t aux_size;
425     uint64_t flags;
426   } * data;
427 
428   AuxRecord(const perf_event_attr& attr, char* p);
429 
430  protected:
431   void DumpData(size_t indent) const override;
432 };
433 
434 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
435 // record file.
436 struct BuildIdRecord : public Record {
437   uint32_t pid;
438   BuildId build_id;
439   const char* filename;
440 
441   explicit BuildIdRecord(char* p);
442 
443   BuildIdRecord(bool in_kernel, uint32_t pid, const BuildId& build_id, const std::string& filename);
444 
445  protected:
446   void DumpData(size_t indent) const override;
447 };
448 
449 struct AuxTraceInfoRecord : public Record {
450   // magic values to be compatible with linux perf
451   static const uint32_t AUX_TYPE_ETM = 3;
452   static const uint64_t MAGIC_ETM4 = 0x4040404040404040ULL;
453 
454   struct ETM4Info {
455     uint64_t magic;
456     uint64_t cpu;
457     uint64_t trcconfigr;
458     uint64_t trctraceidr;
459     uint64_t trcidr0;
460     uint64_t trcidr1;
461     uint64_t trcidr2;
462     uint64_t trcidr8;
463     uint64_t trcauthstatus;
464   };
465 
466   struct DataType {
467     uint32_t aux_type;
468     uint32_t reserved;
469     uint64_t version;
470     uint32_t nr_cpu;
471     uint32_t pmu_type;
472     uint64_t snapshot;
473     ETM4Info etm4_info[0];
474   } * data;
475 
476   explicit AuxTraceInfoRecord(char* p);
477   AuxTraceInfoRecord(const DataType& data, const std::vector<ETM4Info>& etm4_info);
478 
479  protected:
480   void DumpData(size_t indent) const override;
481 };
482 
483 struct AuxTraceRecord : public Record {
484   struct DataType {
485     uint64_t aux_size;
486     uint64_t offset;
487     uint64_t reserved0;  // reference
488     uint32_t idx;
489     uint32_t tid;
490     uint32_t cpu;
491     uint32_t reserved1;
492   } * data;
493   // AuxTraceRecord is followed by aux tracing data with size data->aux_size.
494   // The location of aux tracing data in memory or file is kept in location.
495   struct AuxDataLocation {
496     const char* addr = nullptr;
497     uint64_t file_offset = 0;
498   } location;
499 
500   explicit AuxTraceRecord(char* p);
501   AuxTraceRecord(uint64_t aux_size, uint64_t offset, uint32_t idx, uint32_t tid, uint32_t cpu);
502 
SizeAuxTraceRecord503   static size_t Size() { return sizeof(perf_event_header) + sizeof(DataType); }
504 
505  protected:
506   void DumpData(size_t indent) const override;
507 };
508 
509 struct KernelSymbolRecord : public Record {
510   uint32_t kallsyms_size;
511   const char* kallsyms;
512 
513   explicit KernelSymbolRecord(char* p);
514 
515   explicit KernelSymbolRecord(const std::string& kallsyms);
516 
517  protected:
518   void DumpData(size_t indent) const override;
519 };
520 
521 struct DsoRecord : public Record {
522   uint64_t dso_type;
523   uint64_t dso_id;
524   uint64_t min_vaddr;
525   const char* dso_name;
526 
527   explicit DsoRecord(char* p);
528 
529   DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name, uint64_t min_vaddr);
530 
531  protected:
532   void DumpData(size_t indent) const override;
533 };
534 
535 struct SymbolRecord : public Record {
536   uint64_t addr;
537   uint64_t len;
538   uint64_t dso_id;
539   const char* name;
540 
541   explicit SymbolRecord(char* p);
542 
543   SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, uint64_t dso_id);
544 
545  protected:
546   void DumpData(size_t indent) const override;
547 };
548 
549 struct TracingDataRecord : public Record {
550   uint32_t data_size;
551   const char* data;
552 
553   explicit TracingDataRecord(char* p);
554 
555   explicit TracingDataRecord(const std::vector<char>& tracing_data);
556 
557  protected:
558   void DumpData(size_t indent) const override;
559 };
560 
561 struct EventIdRecord : public Record {
562   uint64_t count;
563   struct EventIdData {
564     uint64_t attr_id;
565     uint64_t event_id;
566   } const* data;
567 
568   explicit EventIdRecord(char* p);
569 
570   explicit EventIdRecord(const std::vector<uint64_t>& data);
571 
572  protected:
573   void DumpData(size_t indent) const override;
574 };
575 
576 struct CallChainRecord : public Record {
577   uint32_t pid;
578   uint32_t tid;
579   uint64_t chain_type;
580   uint64_t time;
581   uint64_t ip_nr;
582   uint64_t* ips;
583   uint64_t* sps;
584 
585   explicit CallChainRecord(char* p);
586 
587   CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time,
588                   const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
589 
TimestampCallChainRecord590   uint64_t Timestamp() const override { return time; }
591 
592  protected:
593   void DumpData(size_t indent) const override;
594 };
595 
596 struct UnwindingResultRecord : public Record {
597   uint64_t time;
598   UnwindingResult unwinding_result;
599   PerfSampleRegsUserType regs_user_data;
600   PerfSampleStackUserType stack_user_data;
601 
602   struct CallChain {
603     uint64_t length = 0;
604     uint64_t* ips = nullptr;
605     uint64_t* sps = nullptr;
606   } callchain;
607 
608   explicit UnwindingResultRecord(char* p);
609 
610   UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result,
611                         const PerfSampleRegsUserType& regs_user_data,
612                         const PerfSampleStackUserType& stack_user_data,
613                         const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
614 
TimestampUnwindingResultRecord615   uint64_t Timestamp() const override { return time; }
616 
617  protected:
618   void DumpData(size_t indent) const override;
619 };
620 
621 // UnknownRecord is used for unknown record types, it makes sure all unknown
622 // records are not changed when modifying perf.data.
623 struct UnknownRecord : public Record {
624   const char* data;
625 
626   explicit UnknownRecord(char* p);
627 
628  protected:
629   void DumpData(size_t indent) const override;
630 };
631 
632 // Read record from the buffer pointed by [p]. But the record doesn't own
633 // the buffer.
634 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p);
635 
636 // Read record from the buffer pointed by [p]. And the record owns the buffer.
637 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr, uint32_t type,
638                                                   char* p);
639 
640 // Read records from the buffer pointed by [buf]. None of the records own
641 // the buffer.
642 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr, char* buf,
643                                                            size_t buf_size);
644 
645 // Read one record from the buffer pointed by [p]. But the record doesn't
646 // own the buffer.
647 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p);
648 
649 }  // namespace simpleperf
650 
651 #endif  // SIMPLE_PERF_RECORD_H_
652