• 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   SIMPLE_PERF_RECORD_DEBUG,
60 };
61 
62 // perf_event_header uses u16 to store record size. However, that is not
63 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
64 // a simpleperf_record_header struct to store record header for simpleperf
65 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
66 struct simpleperf_record_header {
67   uint32_t type;
68   uint16_t size1;
69   uint16_t size0;
70 };
71 
72 static_assert(sizeof(simpleperf_record_header) == sizeof(perf_event_header),
73               "simpleperf_record_header should have the same size as perf_event_header");
74 
75 struct PerfSampleIpType {
76   uint64_t ip;
77 };
78 
79 struct PerfSampleTidType {
80   uint32_t pid, tid;
81 };
82 
83 struct PerfSampleTimeType {
84   uint64_t time;
85 };
86 
87 struct PerfSampleAddrType {
88   uint64_t addr;
89 };
90 
91 struct PerfSampleIdType {
92   uint64_t id;
93 };
94 
95 struct PerfSampleStreamIdType {
96   uint64_t stream_id;
97 };
98 
99 struct PerfSampleCpuType {
100   uint32_t cpu, res;
101 };
102 
103 struct PerfSamplePeriodType {
104   uint64_t period;
105 };
106 
107 struct PerfSampleReadType {
108   uint64_t time_enabled = 0;
109   uint64_t time_running = 0;
110   std::vector<uint64_t> counts;
111   std::vector<uint64_t> ids;
112 };
113 
114 struct PerfSampleCallChainType {
115   uint64_t ip_nr;
116   uint64_t* ips;
117 };
118 
119 struct PerfSampleRawType {
120   uint32_t size;
121   const char* data;
122 };
123 
124 struct BranchStackItemType {
125   uint64_t from;
126   uint64_t to;
127   uint64_t flags;
128 };
129 
130 struct PerfSampleBranchStackType {
131   uint64_t stack_nr;
132   const BranchStackItemType* stack;
133 };
134 
135 struct PerfSampleRegsUserType {
136   uint64_t abi;
137   uint64_t reg_mask;
138   uint64_t reg_nr;
139   const uint64_t* regs;
140 };
141 
142 struct PerfSampleStackUserType {
143   uint64_t size;
144   char* data;
145   uint64_t dyn_size;
146 };
147 
148 struct RecordHeader {
149  public:
150   uint32_t type;
151   uint16_t misc;
152   uint32_t size;
153 
RecordHeaderRecordHeader154   RecordHeader() : type(0), misc(0), size(0) {}
155 
ParseRecordHeader156   bool Parse(const char* p) {
157     auto pheader = reinterpret_cast<const perf_event_header*>(p);
158     if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
159       type = pheader->type;
160       misc = pheader->misc;
161       size = pheader->size;
162     } else {
163       auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
164       type = sheader->type;
165       misc = 0;
166       size = (sheader->size1 << 16) | sheader->size0;
167     }
168     if (size < sizeof(perf_event_header)) {
169       LOG(ERROR) << "invalid record";
170       return false;
171     }
172     return true;
173   }
174 
MoveToBinaryFormatRecordHeader175   void MoveToBinaryFormat(char*& p) const {
176     if (type < SIMPLE_PERF_RECORD_TYPE_START) {
177       auto pheader = reinterpret_cast<perf_event_header*>(p);
178       pheader->type = type;
179       pheader->misc = misc;
180       CHECK_LT(size, 1u << 16);
181       pheader->size = static_cast<uint16_t>(size);
182     } else {
183       auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
184       sheader->type = type;
185       CHECK_EQ(misc, 0u);
186       sheader->size1 = size >> 16;
187       sheader->size0 = size & 0xffff;
188     }
189     p += sizeof(perf_event_header);
190   }
191 };
192 
193 // SampleId is optional at the end of a record in binary format. Its content is
194 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the
195 // complexity of referring to perf_event_attr each time, we copy sample_id_all
196 // and sample_type inside the SampleId structure.
197 struct SampleId {
198   bool sample_id_all;
199   uint64_t sample_type;
200 
201   PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
202   PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
203   PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
204   PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
205   PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.
206 
207   SampleId();
208 
209   // Create the content of sample_id. It depends on the attr we use.
210   size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
211 
212   // Parse sample_id from binary format in the buffer pointed by p.
213   bool ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
214 
215   // Write the binary format of sample_id to the buffer pointed by p.
216   void WriteToBinaryFormat(char*& p) const;
217   void Dump(size_t indent) const;
218   size_t Size() const;
219 };
220 
221 // Usually one record contains the following three parts in order in binary
222 // format:
223 //   RecordHeader (at the head of a record, containing type and size info)
224 //   data depends on the record type
225 //   SampleId (optional part at the end of a record)
226 // We hold the common parts (RecordHeader and SampleId) in the base class
227 // Record, and hold the type specific data part in classes derived from Record.
228 struct Record {
229   RecordHeader header;
230   SampleId sample_id;
231 
RecordRecord232   Record() : binary_(nullptr), own_binary_(false) {}
233   Record(Record&& other) noexcept;
234 
~RecordRecord235   virtual ~Record() {
236     if (own_binary_) {
237       delete[] binary_;
238     }
239   }
240 
241   virtual bool Parse(const perf_event_attr& attr, char* p, char* end) = 0;
242 
OwnBinaryRecord243   void OwnBinary() { own_binary_ = true; }
244 
typeRecord245   uint32_t type() const { return header.type; }
246 
miscRecord247   uint16_t misc() const { return header.misc; }
248 
sizeRecord249   uint32_t size() const { return header.size; }
250 
header_sizeRecord251   static uint32_t header_size() { return sizeof(perf_event_header); }
252 
InKernelRecord253   bool InKernel() const {
254     uint16_t cpumode = header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
255     return cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL;
256   }
257 
SetTypeAndMiscRecord258   void SetTypeAndMisc(uint32_t type, uint16_t misc) {
259     header.type = type;
260     header.misc = misc;
261   }
262 
SetSizeRecord263   void SetSize(uint32_t size) { header.size = size; }
264 
265   void Dump(size_t indent = 0) const;
266 
BinaryRecord267   const char* Binary() const { return binary_; }
BinaryForTestingOnlyRecord268   char* BinaryForTestingOnly() { return binary_; }
269 
270   virtual uint64_t Timestamp() const;
271   virtual uint32_t Cpu() const;
272   virtual uint64_t Id() const;
273 
274  protected:
275   bool ParseHeader(char*& p, char*& end);
276   void UpdateBinary(char* new_binary);
277   virtual void DumpData(size_t) const = 0;
278 
279   char* binary_;
280   bool own_binary_;
281 
282   DISALLOW_COPY_AND_ASSIGN(Record);
283 };
284 
285 struct MmapRecord : public Record {
286   struct MmapRecordDataType {
287     uint32_t pid, tid;
288     uint64_t addr;
289     uint64_t len;
290     uint64_t pgoff;
291   };
292   const MmapRecordDataType* data;
293   const char* filename;
294 
MmapRecordMmapRecord295   MmapRecord() {}
296   MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, uint64_t addr,
297              uint64_t len, uint64_t pgoff, const std::string& filename, uint64_t event_id,
298              uint64_t time = 0);
299 
300   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
301   void SetDataAndFilename(const MmapRecordDataType& data, const std::string& filename);
302 
303  protected:
304   void DumpData(size_t indent) const override;
305 };
306 
307 struct Mmap2Record : public Record {
308   struct Mmap2RecordDataType {
309     uint32_t pid, tid;
310     uint64_t addr;
311     uint64_t len;
312     uint64_t pgoff;
313     uint32_t maj;
314     uint32_t min;
315     uint64_t ino;
316     uint64_t ino_generation;
317     uint32_t prot, flags;
318   };
319   const Mmap2RecordDataType* data;
320   const char* filename;
321 
Mmap2RecordMmap2Record322   Mmap2Record() {}
323   Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
324               uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot,
325               const std::string& filename, uint64_t event_id, uint64_t time = 0);
326 
327   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
328   void SetDataAndFilename(const Mmap2RecordDataType& data, const std::string& filename);
329 
330  protected:
331   void DumpData(size_t indent) const override;
332 };
333 
334 struct CommRecord : public Record {
335   struct CommRecordDataType {
336     uint32_t pid, tid;
337   };
338   const CommRecordDataType* data;
339   const char* comm;
340 
CommRecordCommRecord341   CommRecord() {}
342   CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, const std::string& comm,
343              uint64_t event_id, uint64_t time);
344 
345   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
346   void SetCommandName(const std::string& name);
347 
348  protected:
349   void DumpData(size_t indent) const override;
350 };
351 
352 struct ExitOrForkRecord : public Record {
353   struct ExitOrForkRecordDataType {
354     uint32_t pid, ppid;
355     uint32_t tid, ptid;
356     uint64_t time;
357   };
358   const ExitOrForkRecordDataType* data;
359 
ExitOrForkRecordExitOrForkRecord360   ExitOrForkRecord() : data(nullptr) {}
361   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
362 
363  protected:
364   void DumpData(size_t indent) const override;
365 };
366 
367 struct ExitRecord : public ExitOrForkRecord {};
368 
369 struct ForkRecord : public ExitOrForkRecord {
ForkRecordForkRecord370   ForkRecord() {}
371   ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid, uint32_t ptid,
372              uint64_t event_id);
373 };
374 
375 struct LostRecord : public Record {
376   uint64_t id;
377   uint64_t lost;
378 
379   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
380 
381  protected:
382   void DumpData(size_t indent) const override;
383 };
384 
385 struct SampleRecord : public Record {
386   uint64_t sample_type;  // sample_type is a bit mask determining which fields
387                          // below are valid.
388   uint64_t read_format;
389 
390   PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
391   PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
392   PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
393   PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
394   PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
395   PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
396   PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
397   PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
398   PerfSampleReadType read_data;           // Valid if PERF_SAMPLE_READ.
399 
400   PerfSampleCallChainType callchain_data;       // Valid if PERF_SAMPLE_CALLCHAIN.
401   PerfSampleRawType raw_data;                   // Valid if PERF_SAMPLE_RAW.
402   PerfSampleBranchStackType branch_stack_data;  // Valid if PERF_SAMPLE_BRANCH_STACK.
403   PerfSampleRegsUserType regs_user_data;        // Valid if PERF_SAMPLE_REGS_USER.
404   PerfSampleStackUserType stack_user_data;      // Valid if PERF_SAMPLE_STACK_USER.
405 
SampleRecordSampleRecord406   SampleRecord() {}
407   SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, uint32_t pid, uint32_t tid,
408                uint64_t time, uint32_t cpu, uint64_t period, const PerfSampleReadType& read_data,
409                const std::vector<uint64_t>& ips, const std::vector<char>& stack,
410                uint64_t dyn_stack_size);
411 
412   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
413   void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
414   // Remove kernel callchain, return true if there is a user space callchain left, otherwise
415   // return false.
416   bool ExcludeKernelCallChain();
417   bool HasUserCallChain() const;
418   void UpdateUserCallChain(const std::vector<uint64_t>& user_ips);
419 
420   uint64_t Timestamp() const override;
421   uint32_t Cpu() const override;
422   uint64_t Id() const override;
423 
GetValidStackSizeSampleRecord424   uint64_t GetValidStackSize() const {
425     // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer().
426     return stack_user_data.size;
427   }
428 
429   void AdjustCallChainGeneratedByKernel();
430   std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const;
431 
432  protected:
433   void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips);
434   void DumpData(size_t indent) const override;
435 };
436 
437 struct AuxRecord : public Record {
438   struct DataType {
439     uint64_t aux_offset;
440     uint64_t aux_size;
441     uint64_t flags;
442   }* data;
443 
444   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
UnformattedAuxRecord445   bool Unformatted() const { return data->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW; }
446 
447  protected:
448   void DumpData(size_t indent) const override;
449 };
450 
451 struct SwitchRecord : public Record {
452   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
453 
454  protected:
DumpDataSwitchRecord455   void DumpData(size_t) const override {}
456 };
457 
458 struct SwitchCpuWideRecord : public Record {
459   PerfSampleTidType tid_data;
460 
461   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
462 
463  protected:
464   void DumpData(size_t indent) const override;
465 };
466 
467 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
468 // record file.
469 struct BuildIdRecord : public Record {
470   uint32_t pid;
471   BuildId build_id;
472   const char* filename;
473 
BuildIdRecordBuildIdRecord474   BuildIdRecord() {}
475   BuildIdRecord(bool in_kernel, uint32_t pid, const BuildId& build_id, const std::string& filename);
476   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
477 
478  protected:
479   void DumpData(size_t indent) const override;
480 };
481 
482 struct AuxTraceInfoRecord : public Record {
483   // magic values to be compatible with linux perf
484   static constexpr uint32_t AUX_TYPE_ETM = 3;
485   static constexpr uint64_t MAGIC_ETM4 = 0x4040404040404040ULL;
486   static constexpr uint64_t MAGIC_ETE = 0x5050505050505050ULL;
487 
488   struct ETM4Info {
489     uint64_t magic;
490     uint64_t cpu;
491     uint64_t nrtrcparams;
492     uint64_t trcconfigr;
493     uint64_t trctraceidr;
494     uint64_t trcidr0;
495     uint64_t trcidr1;
496     uint64_t trcidr2;
497     uint64_t trcidr8;
498     uint64_t trcauthstatus;
499   };
500 
501   struct ETEInfo {
502     uint64_t magic;
503     uint64_t cpu;
504     uint64_t nrtrcparams;
505     uint64_t trcconfigr;
506     uint64_t trctraceidr;
507     uint64_t trcidr0;
508     uint64_t trcidr1;
509     uint64_t trcidr2;
510     uint64_t trcidr8;
511     uint64_t trcauthstatus;
512     uint64_t trcdevarch;
513   };
514 
515   struct DataType {
516     uint32_t aux_type;
517     uint32_t reserved;
518     uint64_t version;
519     uint32_t nr_cpu;
520     uint32_t pmu_type;
521     uint64_t snapshot;
522     uint64_t info[0];
523   }* data;
524 
AuxTraceInfoRecordAuxTraceInfoRecord525   AuxTraceInfoRecord() {}
526   AuxTraceInfoRecord(const DataType& data, const std::vector<ETEInfo>& ete_info);
527   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
528 
529  protected:
530   void DumpData(size_t indent) const override;
531 };
532 
533 struct AuxTraceRecord : public Record {
534   struct DataType {
535     uint64_t aux_size;
536     uint64_t offset;
537     uint64_t reserved0;  // reference
538     uint32_t idx;
539     uint32_t tid;
540     uint32_t cpu;
541     uint32_t reserved1;
542   }* data;
543   // AuxTraceRecord is followed by aux tracing data with size data->aux_size.
544   // The location of aux tracing data in memory or file is kept in location.
545   struct AuxDataLocation {
546     const char* addr = nullptr;
547     uint64_t file_offset = 0;
548   } location;
549 
AuxTraceRecordAuxTraceRecord550   AuxTraceRecord() {}
551   AuxTraceRecord(uint64_t aux_size, uint64_t offset, uint32_t idx, uint32_t tid, uint32_t cpu);
552 
553   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
CpuAuxTraceRecord554   uint32_t Cpu() const override { return data->cpu; }
SizeAuxTraceRecord555   static size_t Size() { return sizeof(perf_event_header) + sizeof(DataType); }
556 
557  protected:
558   void DumpData(size_t indent) const override;
559 };
560 
561 struct KernelSymbolRecord : public Record {
562   uint32_t kallsyms_size;
563   const char* kallsyms;
564 
KernelSymbolRecordKernelSymbolRecord565   KernelSymbolRecord() {}
566   explicit KernelSymbolRecord(const std::string& kallsyms);
567   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
568 
569  protected:
570   void DumpData(size_t indent) const override;
571 };
572 
573 struct DsoRecord : public Record {
574   uint64_t dso_type;
575   uint64_t dso_id;
576   uint64_t min_vaddr;
577   const char* dso_name;
578 
DsoRecordDsoRecord579   DsoRecord() {}
580   DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name, uint64_t min_vaddr);
581   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
582 
583  protected:
584   void DumpData(size_t indent) const override;
585 };
586 
587 struct SymbolRecord : public Record {
588   uint64_t addr;
589   uint64_t len;
590   uint64_t dso_id;
591   const char* name;
592 
SymbolRecordSymbolRecord593   SymbolRecord() {}
594   SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, uint64_t dso_id);
595   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
596 
597  protected:
598   void DumpData(size_t indent) const override;
599 };
600 
601 struct TracingDataRecord : public Record {
602   uint32_t data_size;
603   const char* data;
604 
TracingDataRecordTracingDataRecord605   TracingDataRecord() {}
606   explicit TracingDataRecord(const std::vector<char>& tracing_data);
607   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
608 
609  protected:
610   void DumpData(size_t indent) const override;
611 };
612 
613 struct EventIdRecord : public Record {
614   uint64_t count;
615   struct EventIdData {
616     uint64_t attr_id;
617     uint64_t event_id;
618   } const* data;
619 
EventIdRecordEventIdRecord620   EventIdRecord() {}
621   explicit EventIdRecord(const std::vector<uint64_t>& data);
622   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
623 
624  protected:
625   void DumpData(size_t indent) const override;
626 };
627 
628 struct CallChainRecord : public Record {
629   uint32_t pid;
630   uint32_t tid;
631   uint64_t chain_type;
632   uint64_t time;
633   uint64_t ip_nr;
634   uint64_t* ips;
635   uint64_t* sps;
636 
CallChainRecordCallChainRecord637   CallChainRecord() {}
638 
639   CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time,
640                   const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
641 
642   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
TimestampCallChainRecord643   uint64_t Timestamp() const override { return time; }
644 
645  protected:
646   void DumpData(size_t indent) const override;
647 };
648 
649 struct UnwindingResultRecord : public Record {
650   uint64_t time;
651   UnwindingResult unwinding_result;
652   PerfSampleRegsUserType regs_user_data;
653   PerfSampleStackUserType stack_user_data;
654 
655   struct CallChain {
656     uint64_t length = 0;
657     uint64_t* ips = nullptr;
658     uint64_t* sps = nullptr;
659   } callchain;
660 
UnwindingResultRecordUnwindingResultRecord661   UnwindingResultRecord() {}
662 
663   UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result,
664                         const PerfSampleRegsUserType& regs_user_data,
665                         const PerfSampleStackUserType& stack_user_data,
666                         const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
667 
668   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
TimestampUnwindingResultRecord669   uint64_t Timestamp() const override { return time; }
670 
671  protected:
672   void DumpData(size_t indent) const override;
673 };
674 
675 // Add a debug string in the recording file.
676 struct DebugRecord : public Record {
677   uint64_t time = 0;
678   char* s = nullptr;
679 
DebugRecordDebugRecord680   DebugRecord() {}
681 
682   DebugRecord(uint64_t time, const std::string& s);
683 
684   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
TimestampDebugRecord685   uint64_t Timestamp() const override { return time; }
686 
687  protected:
688   void DumpData(size_t indent) const override;
689 };
690 
691 // UnknownRecord is used for unknown record types, it makes sure all unknown
692 // records are not changed when modifying perf.data.
693 struct UnknownRecord : public Record {
694   const char* data;
695 
696   bool Parse(const perf_event_attr& attr, char* p, char* end) override;
697 
698  protected:
699   void DumpData(size_t indent) const override;
700 };
701 
702 // Read record from the buffer pointed by [p]. But the record doesn't own
703 // the buffer.
704 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p,
705                                              char* end);
706 
707 // Read records from the buffer pointed by [buf]. None of the records own
708 // the buffer.
709 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr, char* buf,
710                                                            size_t buf_size);
711 
712 // Read one record from the buffer pointed by [p]. But the record doesn't
713 // own the buffer.
714 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p, char* end);
715 
716 }  // namespace simpleperf
717 
718 #endif  // SIMPLE_PERF_RECORD_H_
719