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