19759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui/*
29759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Copyright (C) 2015 The Android Open Source Project
39759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
49759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
59759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * you may not use this file except in compliance with the License.
69759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * You may obtain a copy of the License at
79759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
89759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *      http://www.apache.org/licenses/LICENSE-2.0
99759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
109759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Unless required by applicable law or agreed to in writing, software
119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * distributed under the License is distributed on an "AS IS" BASIS,
129759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * See the License for the specific language governing permissions and
149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * limitations under the License.
159759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui */
169759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
179759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#ifndef SIMPLE_PERF_RECORD_H_
189759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#define SIMPLE_PERF_RECORD_H_
199759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
20b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui#include <stdio.h>
21918e4b757aa5e8a04811039068e2b56528505e28Dan Albert#include <sys/types.h>
22918e4b757aa5e8a04811039068e2b56528505e28Dan Albert
23ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui#include <memory>
24f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui#include <queue>
259759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <string>
269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <vector>
279759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
288f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include "build_id.h"
299759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "perf_event.h"
309759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
319759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct KernelMmap;
329759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct ModuleMmap;
339759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct ThreadComm;
349759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct ThreadMmap;
359759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
369759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuienum user_record_type {
379759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PERF_RECORD_ATTR = 64,
389759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PERF_RECORD_EVENT_TYPE,
399759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PERF_RECORD_TRACING_DATA,
409759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PERF_RECORD_BUILD_ID,
419759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PERF_RECORD_FINISHED_ROUND,
429759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
439759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
449759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleIpType {
459759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t ip;
469759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
479759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
489759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleTidType {
499759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint32_t pid, tid;
509759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
519759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
529759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleTimeType {
539759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t time;
549759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
559759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
569759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleAddrType {
579759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t addr;
589759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
599759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
609759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleIdType {
619759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t id;
629759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
639759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
649759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleStreamIdType {
659759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t stream_id;
669759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
679759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
689759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSampleCpuType {
699759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint32_t cpu, res;
709759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
719759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
729759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct PerfSamplePeriodType {
739759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t period;
749759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
759759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
766e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cuistruct PerfSampleCallChainType {
776e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui  std::vector<uint64_t> ips;
786e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui};
796e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui
80bfc11b6c1cf93615c00f3503774dd8f4e3b30172Yabin Cuistruct PerfSampleRawType {
81bfc11b6c1cf93615c00f3503774dd8f4e3b30172Yabin Cui  std::vector<char> data;
82bfc11b6c1cf93615c00f3503774dd8f4e3b30172Yabin Cui};
83bfc11b6c1cf93615c00f3503774dd8f4e3b30172Yabin Cui
84ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cuistruct PerfSampleBranchStackType {
85ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  struct BranchStackItemType {
86ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    uint64_t from;
87ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    uint64_t to;
88ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    uint64_t flags;
89ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  };
90ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  std::vector<BranchStackItemType> stack;
91ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui};
92ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui
9376769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cuistruct PerfSampleRegsUserType {
9476769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  uint64_t abi;
9576769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  uint64_t reg_mask;
9676769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  std::vector<uint64_t> regs;
9776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui};
9876769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui
9976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cuistruct PerfSampleStackUserType {
10076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  std::vector<char> data;
10176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  uint64_t dyn_size;
10276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui};
10376769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui
1049759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// SampleId is optional at the end of a record in binary format. Its content is determined by
1059759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// sample_id_all and sample_type in perf_event_attr. To avoid the complexity of referring to
1069759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// perf_event_attr each time, we copy sample_id_all and sample_type inside the SampleId structure.
1079759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct SampleId {
1089759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  bool sample_id_all;
1099759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t sample_type;
1109759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
1129759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
1139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
1149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
1159759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.
1169759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1179759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  SampleId();
1189759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1199759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  // Create the content of sample_id. It depends on the attr we use.
1209759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  size_t CreateContent(const perf_event_attr& attr);
1219759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1229759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  // Parse sample_id from binary format in the buffer pointed by p.
1239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
1249759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1259759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  // Write the binary format of sample_id to the buffer pointed by p.
1269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void WriteToBinaryFormat(char*& p) const;
1279759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void Dump(size_t indent) const;
1287288501a660ce2616539e8a963185d2f3c679729Yabin Cui  size_t Size() const;
1299759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
1309759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1319759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// Usually one record contains the following three parts in order in binary format:
1329759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui//   perf_event_header (at the head of a record, containing type and size information)
1339759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui//   data depends on the record type
1349759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui//   sample_id (optional part at the end of a record)
1359759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// We hold the common parts (perf_event_header and sample_id) in the base class Record, and
1369759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui// hold the type specific data part in classes derived from Record.
1379759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct Record {
1389759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  perf_event_header header;
1399759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  SampleId sample_id;
1409759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1419759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  Record();
1429759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  Record(const perf_event_header* pheader);
1439759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1449759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  virtual ~Record() {
1459759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
1469759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
147b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  size_t size() const {
148b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return header.size;
149b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
150b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui
151b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  uint32_t type() const {
152b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return header.type;
153b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
154b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui
1559759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void Dump(size_t indent = 0) const;
156cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  virtual std::vector<char> BinaryFormat() const = 0;
157f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  virtual uint64_t Timestamp() const;
1589759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1599759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui protected:
160cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  virtual void DumpData(size_t) const = 0;
1619759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
1629759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1639759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct MmapRecord : public Record {
1649759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  struct MmapRecordDataType {
1659759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint32_t pid, tid;
1669759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint64_t addr;
1679759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint64_t len;
1689759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint64_t pgoff;
1699759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  } data;
1709759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  std::string filename;
1719759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
172cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  MmapRecord() {  // For CreateMmapRecord.
1739759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
1749759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1759759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
176cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
1777288501a660ce2616539e8a963185d2f3c679729Yabin Cui  void AdjustSizeBasedOnData();
1788f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
1798f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui protected:
1808f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  void DumpData(size_t indent) const override;
1819759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
1829759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
18341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cuistruct Mmap2Record : public Record {
18441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  struct Mmap2RecordDataType {
18541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint32_t pid, tid;
18641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint64_t addr;
18741d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint64_t len;
18841d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint64_t pgoff;
18941d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint32_t maj;
19041d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint32_t min;
19141d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint64_t ino;
19241d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint64_t ino_generation;
19341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    uint32_t prot, flags;
19441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  } data;
19541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  std::string filename;
19641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
19741d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  Mmap2Record() {
19841d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
19941d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
20041d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  Mmap2Record(const perf_event_attr& attr, const perf_event_header* pheader);
201cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
2027288501a660ce2616539e8a963185d2f3c679729Yabin Cui  void AdjustSizeBasedOnData();
20341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
20441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui protected:
20541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  void DumpData(size_t indent) const override;
20641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui};
20741d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
2089759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct CommRecord : public Record {
2099759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  struct CommRecordDataType {
2109759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint32_t pid, tid;
2119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  } data;
2129759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  std::string comm;
2139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  CommRecord() {
2159759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
2169759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2179759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
218cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
2198f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2208f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui protected:
2218f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  void DumpData(size_t indent) const override;
2229759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
2239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
22441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cuistruct ExitOrForkRecord : public Record {
22541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  struct ExitOrForkRecordDataType {
2269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint32_t pid, ppid;
2279759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint32_t tid, ptid;
2289759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    uint64_t time;
2299759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  } data;
2309759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
23141d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  ExitOrForkRecord() {
23241d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
23341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  ExitOrForkRecord(const perf_event_attr& attr, const perf_event_header* pheader);
234cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
2358f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2368f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui protected:
2379759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void DumpData(size_t indent) const override;
2389759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
2399759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
24041d4ba9f6f2781155a0519a784606d5382cda88fYabin Cuistruct ExitRecord : public ExitOrForkRecord {
24141d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader)
24241d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui      : ExitOrForkRecord(attr, pheader) {
24341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
24441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui};
24541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
24641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cuistruct ForkRecord : public ExitOrForkRecord {
24741d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  ForkRecord() {
24841d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
24941d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  ForkRecord(const perf_event_attr& attr, const perf_event_header* pheader)
25041d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui      : ExitOrForkRecord(attr, pheader) {
25141d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
25241d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui};
25341d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui
2549759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistruct SampleRecord : public Record {
2559759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t sample_type;  // sample_type is a bit mask determining which fields below are valid.
2569759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2579759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
2589759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
2599759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
2609759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
2619759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
2629759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
2639759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
2649759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
2659759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2666e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui  PerfSampleCallChainType callchain_data;       // Valid if PERF_SAMPLE_CALLCHAIN.
267bfc11b6c1cf93615c00f3503774dd8f4e3b30172Yabin Cui  PerfSampleRawType raw_data;                   // Valid if PERF_SAMPLE_RAW.
268ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  PerfSampleBranchStackType branch_stack_data;  // Valid if PERF_SAMPLE_BRANCH_STACK.
26976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  PerfSampleRegsUserType regs_user_data;        // Valid if PERF_SAMPLE_REGS_USER.
27076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  PerfSampleStackUserType stack_user_data;      // Valid if PERF_SAMPLE_STACK_USER.
271ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui
2729759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
273cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
274cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  void AdjustSizeBasedOnData();
275f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  uint64_t Timestamp() const override;
2768f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2778f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui protected:
2788f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  void DumpData(size_t indent) const override;
2798f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui};
2808f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2818f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui// BuildIdRecord is defined in user-space, stored in BuildId feature section in record file.
2828f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cuistruct BuildIdRecord : public Record {
2838f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  uint32_t pid;
2848f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  BuildId build_id;
2858f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  std::string filename;
2868f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2878f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  BuildIdRecord() {
2888f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  }
2898f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
2908f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  BuildIdRecord(const perf_event_header* pheader);
291cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
292cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui
293cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui protected:
294cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  void DumpData(size_t indent) const override;
295cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui};
296cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui
297cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui// UnknownRecord is used for unknown record types, it makes sure all unknown records
298cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui// are not changed when modifying perf.data.
299cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cuistruct UnknownRecord : public Record {
300cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> data;
301cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui
302cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  UnknownRecord(const perf_event_header* pheader);
303cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  std::vector<char> BinaryFormat() const override;
3048f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
3058f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui protected:
3069759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  void DumpData(size_t indent) const override;
3079759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
3089759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
309f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// RecordCache is a cache used when receiving records from the kernel.
310f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// It sorts received records based on type and timestamp, and pops records
311f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// in sorted order. Records from the kernel need to be sorted because
312f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// records may come from different cpus at the same time, and it is affected
313f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// by the order in which we collect records from different cpus.
314f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// RecordCache pushes records and pops sorted record online. It uses two checks to help
315f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// ensure that records are popped in order. Each time we pop a record A, it is the earliest record
316f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// among all records in the cache. In addition, we have checks for min_cache_size and
317f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// min_time_diff. For min_cache_size check, we check if the cache size >= min_cache_size,
318f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// which is based on the assumption that if we have received (min_cache_size - 1) records
319f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// after record A, we are not likely to receive a record earlier than A. For min_time_diff
320f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// check, we check if record A is generated min_time_diff ns earlier than the latest
321f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// record, which is based on the assumption that if we have received a record for time t,
322f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui// we are not likely to receive a record for time (t - min_time_diff) or earlier.
323f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cuiclass RecordCache {
324f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui public:
325b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  RecordCache(const perf_event_attr& attr, size_t min_cache_size = 1000u,
326b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui              uint64_t min_time_diff_in_ns = 1000000u);
327f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  ~RecordCache();
328f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  void Push(const char* data, size_t size);
329b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  void Push(std::unique_ptr<Record> record);
330f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  std::unique_ptr<Record> Pop();
331f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  std::vector<std::unique_ptr<Record>> PopAll();
332f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui
333f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui private:
3344913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui  struct RecordWithSeq {
3354913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui    uint32_t seq;
3364913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui    Record *record;
3374913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui
3384913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui    bool IsHappensBefore(const RecordWithSeq& other) const;
3394913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui  };
3404913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui
341f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  struct RecordComparator {
3424913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui    bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
343f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  };
344f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui
3454913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui  RecordWithSeq CreateRecordWithSeq(Record *r);
3464913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui
347f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  const perf_event_attr attr_;
348f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  bool has_timestamp_;
349f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  size_t min_cache_size_;
350f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  uint64_t min_time_diff_in_ns_;
351f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  uint64_t last_time_;
3524913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui  uint32_t cur_seq_;
3534913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui  std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
3544913c12f341bc4319d243af24fa2ee1a6618eb34Yabin Cui      RecordComparator> queue_;
355f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui};
356f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui
35773d8078e6e5ef92b2301386ce96260bd99efacbbYabin Cuistd::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr,
35873d8078e6e5ef92b2301386ce96260bd99efacbbYabin Cui                                                           const char* buf, size_t buf_size);
359b7f481f59126456b0e708a76f40fa88224f3531bYabin Cuistd::unique_ptr<Record> ReadRecordFromFile(const perf_event_attr& attr, FILE* fp);
3607d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin CuiMmapRecord CreateMmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
3617d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui                            uint64_t addr, uint64_t len, uint64_t pgoff,
3627d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui                            const std::string& filename);
3637d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin CuiCommRecord CreateCommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
3647d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui                            const std::string& comm);
36541d4ba9f6f2781155a0519a784606d5382cda88fYabin CuiForkRecord CreateForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid,
36641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui                            uint32_t ptid);
3678f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin CuiBuildIdRecord CreateBuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
3688f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui                                  const std::string& filename);
36973d8078e6e5ef92b2301386ce96260bd99efacbbYabin Cui
3709759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#endif  // SIMPLE_PERF_RECORD_H_
371