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