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 <string>
21 #include <vector>
22 
23 #include "build_id.h"
24 #include "perf_event.h"
25 
26 struct KernelMmap;
27 struct ModuleMmap;
28 struct ThreadComm;
29 struct ThreadMmap;
30 
31 enum user_record_type {
32   PERF_RECORD_ATTR = 64,
33   PERF_RECORD_EVENT_TYPE,
34   PERF_RECORD_TRACING_DATA,
35   PERF_RECORD_BUILD_ID,
36   PERF_RECORD_FINISHED_ROUND,
37 };
38 
39 struct PerfSampleIpType {
40   uint64_t ip;
41 };
42 
43 struct PerfSampleTidType {
44   uint32_t pid, tid;
45 };
46 
47 struct PerfSampleTimeType {
48   uint64_t time;
49 };
50 
51 struct PerfSampleAddrType {
52   uint64_t addr;
53 };
54 
55 struct PerfSampleIdType {
56   uint64_t id;
57 };
58 
59 struct PerfSampleStreamIdType {
60   uint64_t stream_id;
61 };
62 
63 struct PerfSampleCpuType {
64   uint32_t cpu, res;
65 };
66 
67 struct PerfSamplePeriodType {
68   uint64_t period;
69 };
70 
71 // SampleId is optional at the end of a record in binary format. Its content is determined by
72 // sample_id_all and sample_type in perf_event_attr. To avoid the complexity of referring to
73 // perf_event_attr each time, we copy sample_id_all and sample_type inside the SampleId structure.
74 struct SampleId {
75   bool sample_id_all;
76   uint64_t sample_type;
77 
78   PerfSampleTidType tid_data;             // Valid if sample_id_all && PERF_SAMPLE_TID.
79   PerfSampleTimeType time_data;           // Valid if sample_id_all && PERF_SAMPLE_TIME.
80   PerfSampleIdType id_data;               // Valid if sample_id_all && PERF_SAMPLE_ID.
81   PerfSampleStreamIdType stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
82   PerfSampleCpuType cpu_data;             // Valid if sample_id_all && PERF_SAMPLE_CPU.
83 
84   SampleId();
85 
86   // Create the content of sample_id. It depends on the attr we use.
87   size_t CreateContent(const perf_event_attr& attr);
88 
89   // Parse sample_id from binary format in the buffer pointed by p.
90   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end);
91 
92   // Write the binary format of sample_id to the buffer pointed by p.
93   void WriteToBinaryFormat(char*& p) const;
94   void Dump(size_t indent) const;
95 };
96 
97 // Usually one record contains the following three parts in order in binary format:
98 //   perf_event_header (at the head of a record, containing type and size information)
99 //   data depends on the record type
100 //   sample_id (optional part at the end of a record)
101 // We hold the common parts (perf_event_header and sample_id) in the base class Record, and
102 // hold the type specific data part in classes derived from Record.
103 struct Record {
104   perf_event_header header;
105   SampleId sample_id;
106 
107   Record();
108   Record(const perf_event_header* pheader);
109 
~RecordRecord110   virtual ~Record() {
111   }
112 
113   void Dump(size_t indent = 0) const;
114 
115  protected:
DumpDataRecord116   virtual void DumpData(size_t) const {
117   }
118 };
119 
120 struct MmapRecord : public Record {
121   struct MmapRecordDataType {
122     uint32_t pid, tid;
123     uint64_t addr;
124     uint64_t len;
125     uint64_t pgoff;
126   } data;
127   std::string filename;
128 
MmapRecordMmapRecord129   MmapRecord() {  // For storage in std::vector.
130   }
131 
132   MmapRecord(const perf_event_attr& attr, const perf_event_header* pheader);
133   std::vector<char> BinaryFormat() const;
134 
135  protected:
136   void DumpData(size_t indent) const override;
137 };
138 
139 struct CommRecord : public Record {
140   struct CommRecordDataType {
141     uint32_t pid, tid;
142   } data;
143   std::string comm;
144 
CommRecordCommRecord145   CommRecord() {
146   }
147 
148   CommRecord(const perf_event_attr& attr, const perf_event_header* pheader);
149   std::vector<char> BinaryFormat() const;
150 
151  protected:
152   void DumpData(size_t indent) const override;
153 };
154 
155 struct ExitRecord : public Record {
156   struct ExitRecordDataType {
157     uint32_t pid, ppid;
158     uint32_t tid, ptid;
159     uint64_t time;
160   } data;
161 
162   ExitRecord(const perf_event_attr& attr, const perf_event_header* pheader);
163 
164  protected:
165   void DumpData(size_t indent) const override;
166 };
167 
168 struct SampleRecord : public Record {
169   uint64_t sample_type;  // sample_type is a bit mask determining which fields below are valid.
170 
171   PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
172   PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
173   PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
174   PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
175   PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
176   PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
177   PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
178   PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
179 
180   SampleRecord(const perf_event_attr& attr, const perf_event_header* pheader);
181 
182  protected:
183   void DumpData(size_t indent) const override;
184 };
185 
186 // BuildIdRecord is defined in user-space, stored in BuildId feature section in record file.
187 struct BuildIdRecord : public Record {
188   uint32_t pid;
189   BuildId build_id;
190   std::string filename;
191 
BuildIdRecordBuildIdRecord192   BuildIdRecord() {
193   }
194 
195   BuildIdRecord(const perf_event_header* pheader);
196   std::vector<char> BinaryFormat() const;
197 
198  protected:
199   void DumpData(size_t indent) const override;
200 };
201 
202 std::unique_ptr<const Record> ReadRecordFromBuffer(const perf_event_attr& attr,
203                                                    const perf_event_header* pheader);
204 MmapRecord CreateMmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
205                             uint64_t addr, uint64_t len, uint64_t pgoff,
206                             const std::string& filename);
207 CommRecord CreateCommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
208                             const std::string& comm);
209 BuildIdRecord CreateBuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
210                                   const std::string& filename);
211 #endif  // SIMPLE_PERF_RECORD_H_
212