Home | History | Annotate | Download | only in simpleperf
      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 };
     54 
     55 // perf_event_header uses u16 to store record size. However, that is not
     56 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
     57 // a simpleperf_record_header struct to store record header for simpleperf
     58 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
     59 struct simpleperf_record_header {
     60   uint32_t type;
     61   uint16_t size1;
     62   uint16_t size0;
     63 };
     64 
     65 static_assert(
     66     sizeof(simpleperf_record_header) == sizeof(perf_event_header),
     67     "simpleperf_record_header should have the same size as perf_event_header");
     68 
     69 struct PerfSampleIpType {
     70   uint64_t ip;
     71 };
     72 
     73 struct PerfSampleTidType {
     74   uint32_t pid, tid;
     75 };
     76 
     77 struct PerfSampleTimeType {
     78   uint64_t time;
     79 };
     80 
     81 struct PerfSampleAddrType {
     82   uint64_t addr;
     83 };
     84 
     85 struct PerfSampleIdType {
     86   uint64_t id;
     87 };
     88 
     89 struct PerfSampleStreamIdType {
     90   uint64_t stream_id;
     91 };
     92 
     93 struct PerfSampleCpuType {
     94   uint32_t cpu, res;
     95 };
     96 
     97 struct PerfSamplePeriodType {
     98   uint64_t period;
     99 };
    100 
    101 struct PerfSampleCallChainType {
    102   uint64_t ip_nr;
    103   uint64_t* ips;
    104 };
    105 
    106 struct PerfSampleRawType {
    107   uint32_t size;
    108   const char* data;
    109 };
    110 
    111 struct BranchStackItemType {
    112   uint64_t from;
    113   uint64_t to;
    114   uint64_t flags;
    115 };
    116 
    117 struct PerfSampleBranchStackType {
    118   uint64_t stack_nr;
    119   const BranchStackItemType* stack;
    120 };
    121 
    122 struct PerfSampleRegsUserType {
    123   uint64_t abi;
    124   uint64_t reg_mask;
    125   uint64_t reg_nr;
    126   const uint64_t* regs;
    127 };
    128 
    129 struct PerfSampleStackUserType {
    130   uint64_t size;
    131   char* data;
    132   uint64_t dyn_size;
    133 };
    134 
    135 struct RecordHeader {
    136  public:
    137   uint32_t type;
    138   uint16_t misc;
    139   uint32_t size;
    140 
    141   RecordHeader() : type(0), misc(0), size(0) {}
    142 
    143   explicit RecordHeader(const char* p) {
    144     auto pheader = reinterpret_cast<const perf_event_header*>(p);
    145     if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
    146       type = pheader->type;
    147       misc = pheader->misc;
    148       size = pheader->size;
    149     } else {
    150       auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
    151       type = sheader->type;
    152       misc = 0;
    153       size = (sheader->size1 << 16) | sheader->size0;
    154     }
    155   }
    156 
    157   void MoveToBinaryFormat(char*& p) const {
    158     if (type < SIMPLE_PERF_RECORD_TYPE_START) {
    159       auto pheader = reinterpret_cast<perf_event_header*>(p);
    160       pheader->type = type;
    161       pheader->misc = misc;
    162       CHECK_LT(size, 1u << 16);
    163       pheader->size = static_cast<uint16_t>(size);
    164     } else {
    165       auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
    166       sheader->type = type;
    167       CHECK_EQ(misc, 0u);
    168       sheader->size1 = size >> 16;
    169       sheader->size0 = size & 0xffff;
    170     }
    171     p += sizeof(perf_event_header);
    172   }
    173 };
    174 
    175 // SampleId is optional at the end of a record in binary format. Its content is
    176 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the
    177 // complexity of referring to perf_event_attr each time, we copy sample_id_all
    178 // and sample_type inside the SampleId structure.
    179 struct SampleId {
    180   bool sample_id_all;
    181   uint64_t sample_type;
    182 
    183   PerfSampleTidType tid_data;    // Valid if sample_id_all && PERF_SAMPLE_TID.
    184   PerfSampleTimeType time_data;  // Valid if sample_id_all && PERF_SAMPLE_TIME.
    185   PerfSampleIdType id_data;      // Valid if sample_id_all && PERF_SAMPLE_ID.
    186   PerfSampleStreamIdType
    187       stream_id_data;  // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
    188   PerfSampleCpuType cpu_data;  // Valid if sample_id_all && PERF_SAMPLE_CPU.
    189 
    190   SampleId();
    191 
    192   // Create the content of sample_id. It depends on the attr we use.
    193   size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
    194 
    195   // Parse sample_id from binary format in the buffer pointed by p.
    196   void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
    197                             const char* end);
    198 
    199   // Write the binary format of sample_id to the buffer pointed by p.
    200   void WriteToBinaryFormat(char*& p) const;
    201   void Dump(size_t indent) const;
    202   size_t Size() const;
    203 };
    204 
    205 // Usually one record contains the following three parts in order in binary
    206 // format:
    207 //   RecordHeader (at the head of a record, containing type and size info)
    208 //   data depends on the record type
    209 //   SampleId (optional part at the end of a record)
    210 // We hold the common parts (RecordHeader and SampleId) in the base class
    211 // Record, and hold the type specific data part in classes derived from Record.
    212 struct Record {
    213   RecordHeader header;
    214   SampleId sample_id;
    215 
    216   Record() : binary_(nullptr), own_binary_(false) {}
    217   explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {}
    218   Record(Record&& other);
    219 
    220   virtual ~Record() {
    221     if (own_binary_) {
    222       delete[] binary_;
    223     }
    224   }
    225 
    226   void OwnBinary() { own_binary_ = true; }
    227 
    228   uint32_t type() const { return header.type; }
    229 
    230   uint16_t misc() const { return header.misc; }
    231 
    232   uint32_t size() const { return header.size; }
    233 
    234   static uint32_t header_size() { return sizeof(perf_event_header); }
    235 
    236   bool InKernel() const {
    237     return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
    238            PERF_RECORD_MISC_KERNEL;
    239   }
    240 
    241   void SetTypeAndMisc(uint32_t type, uint16_t misc) {
    242     header.type = type;
    243     header.misc = misc;
    244   }
    245 
    246   void SetSize(uint32_t size) { header.size = size; }
    247 
    248   void Dump(size_t indent = 0) const;
    249 
    250   const char* Binary() const { return binary_; }
    251   char* BinaryForTestingOnly() { return binary_; }
    252 
    253   virtual uint64_t Timestamp() const;
    254   virtual uint32_t Cpu() const;
    255   virtual uint64_t Id() const;
    256 
    257  protected:
    258   void UpdateBinary(char* new_binary);
    259   virtual void DumpData(size_t) const = 0;
    260 
    261   char* binary_;
    262   bool own_binary_;
    263 
    264   DISALLOW_COPY_AND_ASSIGN(Record);
    265 };
    266 
    267 struct MmapRecord : public Record {
    268   struct MmapRecordDataType {
    269     uint32_t pid, tid;
    270     uint64_t addr;
    271     uint64_t len;
    272     uint64_t pgoff;
    273   };
    274   const MmapRecordDataType* data;
    275   const char* filename;
    276 
    277   MmapRecord(const perf_event_attr& attr, char* p);
    278 
    279   MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid,
    280              uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff,
    281              const std::string& filename, uint64_t event_id, uint64_t time = 0);
    282 
    283   void SetDataAndFilename(const MmapRecordDataType& data,
    284                           const std::string& filename);
    285 
    286  protected:
    287   void DumpData(size_t indent) const override;
    288 };
    289 
    290 struct Mmap2Record : public Record {
    291   struct Mmap2RecordDataType {
    292     uint32_t pid, tid;
    293     uint64_t addr;
    294     uint64_t len;
    295     uint64_t pgoff;
    296     uint32_t maj;
    297     uint32_t min;
    298     uint64_t ino;
    299     uint64_t ino_generation;
    300     uint32_t prot, flags;
    301   };
    302   const Mmap2RecordDataType* data;
    303   const char* filename;
    304 
    305   Mmap2Record(const perf_event_attr& attr, char* p);
    306 
    307   void SetDataAndFilename(const Mmap2RecordDataType& data,
    308                           const std::string& filename);
    309 
    310  protected:
    311   void DumpData(size_t indent) const override;
    312 };
    313 
    314 struct CommRecord : public Record {
    315   struct CommRecordDataType {
    316     uint32_t pid, tid;
    317   };
    318   const CommRecordDataType* data;
    319   const char* comm;
    320 
    321   CommRecord(const perf_event_attr& attr, char* p);
    322 
    323   CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
    324              const std::string& comm, uint64_t event_id, uint64_t time);
    325 
    326  protected:
    327   void DumpData(size_t indent) const override;
    328 };
    329 
    330 struct ExitOrForkRecord : public Record {
    331   struct ExitOrForkRecordDataType {
    332     uint32_t pid, ppid;
    333     uint32_t tid, ptid;
    334     uint64_t time;
    335   };
    336   const ExitOrForkRecordDataType* data;
    337 
    338   ExitOrForkRecord(const perf_event_attr& attr, char* p);
    339 
    340   ExitOrForkRecord() : data(nullptr) {}
    341 
    342  protected:
    343   void DumpData(size_t indent) const override;
    344 };
    345 
    346 struct ExitRecord : public ExitOrForkRecord {
    347   ExitRecord(const perf_event_attr& attr, char* p)
    348       : ExitOrForkRecord(attr, p) {}
    349 };
    350 
    351 struct ForkRecord : public ExitOrForkRecord {
    352   ForkRecord(const perf_event_attr& attr, char* p)
    353       : ExitOrForkRecord(attr, p) {}
    354 
    355   ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
    356              uint32_t ppid, uint32_t ptid, uint64_t event_id);
    357 };
    358 
    359 struct LostRecord : public Record {
    360   uint64_t id;
    361   uint64_t lost;
    362 
    363   LostRecord(const perf_event_attr& attr, char* p);
    364 
    365  protected:
    366   void DumpData(size_t indent) const override;
    367 };
    368 
    369 struct SampleRecord : public Record {
    370   uint64_t sample_type;  // sample_type is a bit mask determining which fields
    371                          // below are valid.
    372 
    373   PerfSampleIpType ip_data;               // Valid if PERF_SAMPLE_IP.
    374   PerfSampleTidType tid_data;             // Valid if PERF_SAMPLE_TID.
    375   PerfSampleTimeType time_data;           // Valid if PERF_SAMPLE_TIME.
    376   PerfSampleAddrType addr_data;           // Valid if PERF_SAMPLE_ADDR.
    377   PerfSampleIdType id_data;               // Valid if PERF_SAMPLE_ID.
    378   PerfSampleStreamIdType stream_id_data;  // Valid if PERF_SAMPLE_STREAM_ID.
    379   PerfSampleCpuType cpu_data;             // Valid if PERF_SAMPLE_CPU.
    380   PerfSamplePeriodType period_data;       // Valid if PERF_SAMPLE_PERIOD.
    381 
    382   PerfSampleCallChainType callchain_data;  // Valid if PERF_SAMPLE_CALLCHAIN.
    383   PerfSampleRawType raw_data;              // Valid if PERF_SAMPLE_RAW.
    384   PerfSampleBranchStackType
    385       branch_stack_data;                  // Valid if PERF_SAMPLE_BRANCH_STACK.
    386   PerfSampleRegsUserType regs_user_data;  // Valid if PERF_SAMPLE_REGS_USER.
    387   PerfSampleStackUserType stack_user_data;  // Valid if PERF_SAMPLE_STACK_USER.
    388 
    389   SampleRecord(const perf_event_attr& attr, char* p);
    390   SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip,
    391                uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu,
    392                uint64_t period, const std::vector<uint64_t>& ips);
    393 
    394   void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips);
    395   size_t ExcludeKernelCallChain();
    396   bool HasUserCallChain() const;
    397   void UpdateUserCallChain(const std::vector<uint64_t>& user_ips);
    398   void RemoveInvalidStackData();
    399 
    400   uint64_t Timestamp() const override;
    401   uint32_t Cpu() const override;
    402   uint64_t Id() const override;
    403 
    404   uint64_t GetValidStackSize() const {
    405     // If stack_user_data.dyn_size == 0, it may be because the kernel misses
    406     // the patch to update dyn_size, like in N9 (See b/22612370). So assume
    407     // all stack data is valid if dyn_size == 0.
    408     if (stack_user_data.dyn_size == 0) {
    409       return stack_user_data.size;
    410     }
    411     return stack_user_data.dyn_size;
    412   }
    413 
    414   void AdjustCallChainGeneratedByKernel();
    415 
    416  protected:
    417   void DumpData(size_t indent) const override;
    418 };
    419 
    420 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
    421 // record file.
    422 struct BuildIdRecord : public Record {
    423   uint32_t pid;
    424   BuildId build_id;
    425   const char* filename;
    426 
    427   explicit BuildIdRecord(char* p);
    428 
    429   BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
    430                 const std::string& filename);
    431 
    432  protected:
    433   void DumpData(size_t indent) const override;
    434 };
    435 
    436 struct KernelSymbolRecord : public Record {
    437   uint32_t kallsyms_size;
    438   const char* kallsyms;
    439 
    440   explicit KernelSymbolRecord(char* p);
    441 
    442   explicit KernelSymbolRecord(const std::string& kallsyms);
    443 
    444  protected:
    445   void DumpData(size_t indent) const override;
    446 };
    447 
    448 struct DsoRecord : public Record {
    449   uint64_t dso_type;
    450   uint64_t dso_id;
    451   uint64_t min_vaddr;
    452   const char* dso_name;
    453 
    454   explicit DsoRecord(char* p);
    455 
    456   DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
    457             uint64_t min_vaddr);
    458 
    459  protected:
    460   void DumpData(size_t indent) const override;
    461 };
    462 
    463 struct SymbolRecord : public Record {
    464   uint64_t addr;
    465   uint64_t len;
    466   uint64_t dso_id;
    467   const char* name;
    468 
    469   explicit SymbolRecord(char* p);
    470 
    471   SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
    472                uint64_t dso_id);
    473 
    474  protected:
    475   void DumpData(size_t indent) const override;
    476 };
    477 
    478 struct TracingDataRecord : public Record {
    479   uint32_t data_size;
    480   const char* data;
    481 
    482   explicit TracingDataRecord(char* p);
    483 
    484   explicit TracingDataRecord(const std::vector<char>& tracing_data);
    485 
    486  protected:
    487   void DumpData(size_t indent) const override;
    488 };
    489 
    490 struct EventIdRecord : public Record {
    491   uint64_t count;
    492   struct EventIdData {
    493     uint64_t attr_id;
    494     uint64_t event_id;
    495   } const* data;
    496 
    497   explicit EventIdRecord(char* p);
    498 
    499   explicit EventIdRecord(const std::vector<uint64_t>& data);
    500 
    501  protected:
    502   void DumpData(size_t indent) const override;
    503 };
    504 
    505 struct CallChainRecord : public Record {
    506   uint32_t pid;
    507   uint32_t tid;
    508   uint64_t chain_type;
    509   uint64_t time;
    510   uint64_t ip_nr;
    511   uint64_t* ips;
    512   uint64_t* sps;
    513 
    514   explicit CallChainRecord(char* p);
    515 
    516   CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time,
    517                   const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps);
    518 
    519   uint64_t Timestamp() const override {
    520     return time;
    521   }
    522 
    523  protected:
    524   void DumpData(size_t indent) const override;
    525 };
    526 
    527 struct UnwindingResultRecord : public Record {
    528   uint64_t time;
    529   simpleperf::UnwindingResult unwinding_result;
    530 
    531   explicit UnwindingResultRecord(char* p);
    532 
    533   UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result);
    534 
    535   uint64_t Timestamp() const override {
    536     return time;
    537   }
    538 
    539  protected:
    540   void DumpData(size_t indent) const override;
    541 };
    542 
    543 // UnknownRecord is used for unknown record types, it makes sure all unknown
    544 // records are not changed when modifying perf.data.
    545 struct UnknownRecord : public Record {
    546   const char* data;
    547 
    548   explicit UnknownRecord(char* p);
    549 
    550  protected:
    551   void DumpData(size_t indent) const override;
    552 };
    553 
    554 // Read record from the buffer pointed by [p]. But the record doesn't own
    555 // the buffer.
    556 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p);
    557 
    558 // Read record from the buffer pointed by [p]. And the record owns the buffer.
    559 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
    560                                                   uint32_t type, char* p);
    561 
    562 // Read records from the buffer pointed by [buf]. None of the records own
    563 // the buffer.
    564 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
    565     const perf_event_attr& attr, char* buf, size_t buf_size);
    566 
    567 // Read one record from the buffer pointed by [p]. But the record doesn't
    568 // own the buffer.
    569 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p);
    570 
    571 // RecordCache is a cache used when receiving records from the kernel.
    572 // It sorts received records based on type and timestamp, and pops records
    573 // in sorted order. Records from the kernel need to be sorted because
    574 // records may come from different cpus at the same time, and it is affected
    575 // by the order in which we collect records from different cpus.
    576 // RecordCache pushes records and pops sorted record online. It uses two checks
    577 // to help ensure that records are popped in order. Each time we pop a record A,
    578 // it is the earliest record among all records in the cache. In addition, we
    579 // have checks for min_cache_size and min_time_diff. For min_cache_size check,
    580 // we check if the cache size >= min_cache_size, which is based on the
    581 // assumption that if we have received (min_cache_size - 1) records after
    582 // record A, we are not likely to receive a record earlier than A. For
    583 // min_time_diff check, we check if record A is generated min_time_diff ns
    584 // earlier than the latest record, which is based on the assumption that if we
    585 // have received a record for time t, we are not likely to receive a record for
    586 // time (t - min_time_diff) or earlier.
    587 class RecordCache {
    588  public:
    589   explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
    590                        uint64_t min_time_diff_in_ns = 1000000u);
    591   ~RecordCache();
    592   void Push(std::unique_ptr<Record> record);
    593   void Push(std::vector<std::unique_ptr<Record>> records);
    594   std::unique_ptr<Record> Pop();
    595   std::vector<std::unique_ptr<Record>> PopAll();
    596   std::unique_ptr<Record> ForcedPop();
    597 
    598  private:
    599   struct RecordWithSeq {
    600     uint32_t seq;
    601     Record* record;
    602 
    603     RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
    604     bool IsHappensBefore(const RecordWithSeq& other) const;
    605   };
    606 
    607   struct RecordComparator {
    608     bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
    609   };
    610 
    611   bool has_timestamp_;
    612   size_t min_cache_size_;
    613   uint64_t min_time_diff_in_ns_;
    614   uint64_t last_time_;
    615   uint32_t cur_seq_;
    616   std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
    617                       RecordComparator> queue_;
    618 };
    619 
    620 #endif  // SIMPLE_PERF_RECORD_H_
    621