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