• 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 "build_id.h"
31 #include "CallChainJoiner.h"
32 #include "OfflineUnwinder.h"
33 #include "perf_event.h"
34 
35 enum user_record_type {
36   PERF_RECORD_USER_DEFINED_TYPE_START = 64,
37   PERF_RECORD_ATTR = 64,
38   PERF_RECORD_EVENT_TYPE,
39   PERF_RECORD_TRACING_DATA,
40   PERF_RECORD_BUILD_ID,
41   PERF_RECORD_FINISHED_ROUND,
42 
43   SIMPLE_PERF_RECORD_TYPE_START = 32768,
44   SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
45   // TODO: remove DsoRecord and SymbolRecord.
46   SIMPLE_PERF_RECORD_DSO,
47   SIMPLE_PERF_RECORD_SYMBOL,
48   SIMPLE_PERF_RECORD_SPLIT,
49   SIMPLE_PERF_RECORD_SPLIT_END,
50   SIMPLE_PERF_RECORD_EVENT_ID,
51   SIMPLE_PERF_RECORD_CALLCHAIN,
52   SIMPLE_PERF_RECORD_UNWINDING_RESULT,
53   SIMPLE_PERF_RECORD_TRACING_DATA,
54 };
55 
56 // perf_event_header uses u16 to store record size. However, that is not
57 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
58 // a simpleperf_record_header struct to store record header for simpleperf
59 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
60 struct simpleperf_record_header {
61   uint32_t type;
62   uint16_t size1;
63   uint16_t size0;
64 };
65 
66 static_assert(
67     sizeof(simpleperf_record_header) == sizeof(perf_event_header),
68     "simpleperf_record_header should have the same size as perf_event_header");
69 
70 struct PerfSampleIpType {
71   uint64_t ip;
72 };
73 
74 struct PerfSampleTidType {
75   uint32_t pid, tid;
76 };
77 
78 struct PerfSampleTimeType {
79   uint64_t time;
80 };
81 
82 struct PerfSampleAddrType {
83   uint64_t addr;
84 };
85 
86 struct PerfSampleIdType {
87   uint64_t id;
88 };
89 
90 struct PerfSampleStreamIdType {
91   uint64_t stream_id;
92 };
93 
94 struct PerfSampleCpuType {
95   uint32_t cpu, res;
96 };
97 
98 struct PerfSamplePeriodType {
99   uint64_t period;
100 };
101 
102 struct PerfSampleCallChainType {
103   uint64_t ip_nr;
104   uint64_t* ips;
105 };
106 
107 struct PerfSampleRawType {
108   uint32_t size;
109   const char* data;
110 };
111 
112 struct BranchStackItemType {
113   uint64_t from;
114   uint64_t to;
115   uint64_t flags;
116 };
117 
118 struct PerfSampleBranchStackType {
119   uint64_t stack_nr;
120   const BranchStackItemType* stack;
121 };
122 
123 struct PerfSampleRegsUserType {
124   uint64_t abi;
125   uint64_t reg_mask;
126   uint64_t reg_nr;
127   const uint64_t* regs;
128 };
129 
130 struct PerfSampleStackUserType {
131   uint64_t size;
132   char* data;
133   uint64_t dyn_size;
134 };
135 
136 struct RecordHeader {
137  public:
138   uint32_t type;
139   uint16_t misc;
140   uint32_t size;
141 
RecordHeaderRecordHeader142   RecordHeader() : type(0), misc(0), size(0) {}
143 
RecordHeaderRecordHeader144   explicit RecordHeader(const char* p) {
145     auto pheader = reinterpret_cast<const perf_event_header*>(p);
146     if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
147       type = pheader->type;
148       misc = pheader->misc;
149       size = pheader->size;
150     } else {
151       auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
152       type = sheader->type;
153       misc = 0;
154       size = (sheader->size1 << 16) | sheader->size0;
155     }
156   }
157 
MoveToBinaryFormatRecordHeader158   void MoveToBinaryFormat(char*& p) const {
159     if (type < SIMPLE_PERF_RECORD_TYPE_START) {
160       auto pheader = reinterpret_cast<perf_event_header*>(p);
161       pheader->type = type;
162       pheader->misc = misc;
163       CHECK_LT(size, 1u << 16);
164       pheader->size = static_cast<uint16_t>(size);
165     } else {
166       auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
167       sheader->type = type;
168       CHECK_EQ(misc, 0u);
169       sheader->size1 = size >> 16;
170       sheader->size0 = size & 0xffff;
171     }
172     p += sizeof(perf_event_header);
173   }
174 };
175 
176 // SampleId is optional at the end of a record in binary format. Its content is
177 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the
178 // complexity of referring to perf_event_attr each time, we copy sample_id_all
179 // and sample_type inside the SampleId structure.
180 struct SampleId {
181   bool sample_id_all;
182   uint64_t sample_type;
183 
184   PerfSampleTidType tid_data;    // Valid if sample_id_all && PERF_SAMPLE_TID.
185   PerfSampleTimeType time_data;  // Valid if sample_id_all && PERF_SAMPLE_TIME.
186   PerfSampleIdType id_data;      // Valid if sample_id_all && PERF_SAMPLE_ID.
187   PerfSampleStreamIdType
188       stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
189   PerfSampleCpuType cpu_data;  // Valid if sample_id_all && PERF_SAMPLE_CPU.
190 
191   SampleId();
192 
193   // Create the content of sample_id. It depends on the attr we use.
194   size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
195 
196   // Parse sample_id from binary format in the buffer pointed by p.
197   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
198                             const char* end);
199 
200   // Write the binary format of sample_id to the buffer pointed by p.
201   void WriteToBinaryFormat(char*& p) const;
202   void Dump(size_t indent) const;
203   size_t Size() const;
204 };
205 
206 // Usually one record contains the following three parts in order in binary
207 // format:
208 //   RecordHeader (at the head of a record, containing type and size info)
209 //   data depends on the record type
210 //   SampleId (optional part at the end of a record)
211 // We hold the common parts (RecordHeader and SampleId) in the base class
212 // Record, and hold the type specific data part in classes derived from Record.
213 struct Record {
214   RecordHeader header;
215   SampleId sample_id;
216 
RecordRecord217   Record() : binary_(nullptr), own_binary_(false) {}
RecordRecord218   explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {}
219   Record(Record&& other) noexcept;
220 
~RecordRecord221   virtual ~Record() {
222     if (own_binary_) {
223       delete[] binary_;
224     }
225   }
226 
OwnBinaryRecord227   void OwnBinary() { own_binary_ = true; }
228 
typeRecord229   uint32_t type() const { return header.type; }
230 
miscRecord231   uint16_t misc() const { return header.misc; }
232 
sizeRecord233   uint32_t size() const { return header.size; }
234 
header_sizeRecord235   static uint32_t header_size() { return sizeof(perf_event_header); }
236 
InKernelRecord237   bool InKernel() const {
238     return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
239            PERF_RECORD_MISC_KERNEL;
240   }
241 
SetTypeAndMiscRecord242   void SetTypeAndMisc(uint32_t type, uint16_t misc) {
243     header.type = type;
244     header.misc = misc;
245   }
246 
SetSizeRecord247   void SetSize(uint32_t size) { header.size = size; }
248 
249   void Dump(size_t indent = 0) const;
250 
BinaryRecord251   const char* Binary() const { return binary_; }
BinaryForTestingOnlyRecord252   char* BinaryForTestingOnly() { return binary_; }
253 
254   virtual uint64_t Timestamp() const;
255   virtual uint32_t Cpu() const;
256   virtual uint64_t Id() const;
257 
258  protected:
259   void UpdateBinary(char* new_binary);
260   virtual void DumpData(size_t) const = 0;
261 
262   char* binary_;
263   bool own_binary_;
264 
265   DISALLOW_COPY_AND_ASSIGN(Record);
266 };
267 
268 struct MmapRecord : public Record {
269   struct MmapRecordDataType {
270     uint32_t pid, tid;
271     uint64_t addr;
272     uint64_t len;
273     uint64_t pgoff;
274   };
275   const MmapRecordDataType* data;
276   const char* filename;
277 
278   MmapRecord(const perf_event_attr& attr, char* p);
279 
280   MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
281              uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
282              const std::string& filename, uint64_t event_id, uint64_t time = 0);
283 
284   void SetDataAndFilename(const MmapRecordDataType& data,
285                           const std::string& filename);
286 
287  protected:
288   void DumpData(size_t indent) const override;
289 };
290 
291 struct Mmap2Record : public Record {
292   struct Mmap2RecordDataType {
293     uint32_t pid, tid;
294     uint64_t addr;
295     uint64_t len;
296     uint64_t pgoff;
297     uint32_t maj;
298     uint32_t min;
299     uint64_t ino;
300     uint64_t ino_generation;
301     uint32_t prot, flags;
302   };
303   const Mmap2RecordDataType* data;
304   const char* filename;
305 
306   Mmap2Record(const perf_event_attr& attr, char* p);
307   Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
308               uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot,
309               const std::string& filename, uint64_t event_id, uint64_t time = 0);
310 
311   void SetDataAndFilename(const Mmap2RecordDataType& data,
312                           const std::string& filename);
313 
314  protected:
315   void DumpData(size_t indent) const override;
316 };
317 
318 struct CommRecord : public Record {
319   struct CommRecordDataType {
320     uint32_t pid, tid;
321   };
322   const CommRecordDataType* data;
323   const char* comm;
324 
325   CommRecord(const perf_event_attr& attr, char* p);
326 
327   CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
328              const std::string& comm, uint64_t event_id, uint64_t time);
329 
330   void SetCommandName(const std::string& name);
331 
332  protected:
333   void DumpData(size_t indent) const override;
334 };
335 
336 struct ExitOrForkRecord : public Record {
337   struct ExitOrForkRecordDataType {
338     uint32_t pid, ppid;
339     uint32_t tid, ptid;
340     uint64_t time;
341   };
342   const ExitOrForkRecordDataType* data;
343 
344   ExitOrForkRecord(const perf_event_attr& attr, char* p);
345 
ExitOrForkRecordExitOrForkRecord346   ExitOrForkRecord() : data(nullptr) {}
347 
348  protected:
349   void DumpData(size_t indent) const override;
350 };
351 
352 struct ExitRecord : public ExitOrForkRecord {
ExitRecordExitRecord353   ExitRecord(const perf_event_attr& attr, char* p)
354       : ExitOrForkRecord(attr, p) {}
355 };
356 
357 struct ForkRecord : public ExitOrForkRecord {
ForkRecordForkRecord358   ForkRecord(const perf_event_attr& attr, char* p)
359       : ExitOrForkRecord(attr, p) {}
360 
361   ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
362              uint32_t ppid, uint32_t ptid, uint64_t event_id);
363 };
364 
365 struct LostRecord : public Record {
366   uint64_t id;
367   uint64_t lost;
368 
369   LostRecord(const perf_event_attr& attr, char* p);
370 
371  protected:
372   void DumpData(size_t indent) const override;
373 };
374 
375 struct SampleRecord : public Record {
376   uint64_t sample_type;  // sample_type is a bit mask determining which fields
377                          // below are valid.
378 
379   PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
380   PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
381   PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
382   PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
383   PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
384   PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
385   PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
386   PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
387 
388   PerfSampleCallChainType callchain_data;  // Valid if PERF_SAMPLE_CALLCHAIN.
389   PerfSampleRawType raw_data;              // Valid if PERF_SAMPLE_RAW.
390   PerfSampleBranchStackType
391       branch_stack_data;                  // Valid if PERF_SAMPLE_BRANCH_STACK.
392   PerfSampleRegsUserType regs_user_data;  // Valid if PERF_SAMPLE_REGS_USER.
393   PerfSampleStackUserType stack_user_data;  // Valid if PERF_SAMPLE_STACK_USER.
394 
395   SampleRecord(const perf_event_attr& attr, char* p);
396   SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip,
397                uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu,
398                uint64_t period, const std::vector<uint64_t>& ips,
399                const std::vector<char>& stack, uint64_t dyn_stack_size);
400 
401   void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
402   // Remove kernel callchain, return true if there is a user space callchain left, otherwise
403   // return false.
404   bool ExcludeKernelCallChain();
405   bool HasUserCallChain() const;
406   void UpdateUserCallChain(const std::vector<uint64_t>& user_ips);
407 
408   uint64_t Timestamp() const override;
409   uint32_t Cpu() const override;
410   uint64_t Id() const override;
411 
GetValidStackSizeSampleRecord412   uint64_t GetValidStackSize() const {
413     // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer().
414     return stack_user_data.size;
415   }
416 
417   void AdjustCallChainGeneratedByKernel();
418   std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const;
419 
420  protected:
421   void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips);
422   void DumpData(size_t indent) const override;
423 };
424 
425 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
426 // record file.
427 struct BuildIdRecord : public Record {
428   uint32_t pid;
429   BuildId build_id;
430   const char* filename;
431 
432   explicit BuildIdRecord(char* p);
433 
434   BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
435                 const std::string& filename);
436 
437  protected:
438   void DumpData(size_t indent) const override;
439 };
440 
441 struct KernelSymbolRecord : public Record {
442   uint32_t kallsyms_size;
443   const char* kallsyms;
444 
445   explicit KernelSymbolRecord(char* p);
446 
447   explicit KernelSymbolRecord(const std::string& kallsyms);
448 
449  protected:
450   void DumpData(size_t indent) const override;
451 };
452 
453 struct DsoRecord : public Record {
454   uint64_t dso_type;
455   uint64_t dso_id;
456   uint64_t min_vaddr;
457   const char* dso_name;
458 
459   explicit DsoRecord(char* p);
460 
461   DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
462             uint64_t min_vaddr);
463 
464  protected:
465   void DumpData(size_t indent) const override;
466 };
467 
468 struct SymbolRecord : public Record {
469   uint64_t addr;
470   uint64_t len;
471   uint64_t dso_id;
472   const char* name;
473 
474   explicit SymbolRecord(char* p);
475 
476   SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
477                uint64_t dso_id);
478 
479  protected:
480   void DumpData(size_t indent) const override;
481 };
482 
483 struct TracingDataRecord : public Record {
484   uint32_t data_size;
485   const char* data;
486 
487   explicit TracingDataRecord(char* p);
488 
489   explicit TracingDataRecord(const std::vector<char>& tracing_data);
490 
491  protected:
492   void DumpData(size_t indent) const override;
493 };
494 
495 struct EventIdRecord : public Record {
496   uint64_t count;
497   struct EventIdData {
498     uint64_t attr_id;
499     uint64_t event_id;
500   } const* data;
501 
502   explicit EventIdRecord(char* p);
503 
504   explicit EventIdRecord(const std::vector<uint64_t>& data);
505 
506  protected:
507   void DumpData(size_t indent) const override;
508 };
509 
510 struct CallChainRecord : public Record {
511   uint32_t pid;
512   uint32_t tid;
513   uint64_t chain_type;
514   uint64_t time;
515   uint64_t ip_nr;
516   uint64_t* ips;
517   uint64_t* sps;
518 
519   explicit CallChainRecord(char* p);
520 
521   CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time,
522                   const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
523 
TimestampCallChainRecord524   uint64_t Timestamp() const override {
525     return time;
526   }
527 
528  protected:
529   void DumpData(size_t indent) const override;
530 };
531 
532 struct UnwindingResultRecord : public Record {
533   uint64_t time;
534   simpleperf::UnwindingResult unwinding_result;
535 
536   explicit UnwindingResultRecord(char* p);
537 
538   UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result);
539 
TimestampUnwindingResultRecord540   uint64_t Timestamp() const override {
541     return time;
542   }
543 
544  protected:
545   void DumpData(size_t indent) const override;
546 };
547 
548 // UnknownRecord is used for unknown record types, it makes sure all unknown
549 // records are not changed when modifying perf.data.
550 struct UnknownRecord : public Record {
551   const char* data;
552 
553   explicit UnknownRecord(char* p);
554 
555  protected:
556   void DumpData(size_t indent) const override;
557 };
558 
559 // Read record from the buffer pointed by [p]. But the record doesn't own
560 // the buffer.
561 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p);
562 
563 // Read record from the buffer pointed by [p]. And the record owns the buffer.
564 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
565                                                   uint32_t type, char* p);
566 
567 // Read records from the buffer pointed by [buf]. None of the records own
568 // the buffer.
569 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
570     const perf_event_attr& attr, char* buf, size_t buf_size);
571 
572 // Read one record from the buffer pointed by [p]. But the record doesn't
573 // own the buffer.
574 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p);
575 
576 #endif  // SIMPLE_PERF_RECORD_H_
577