2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef SIMPLE_PERF_RECORD_H_
18 #define SIMPLE_PERF_RECORD_H_
21 #include <sys/types.h>
28 #include <android-base/logging.h>
31 #include "CallChainJoiner.h"
32 #include "OfflineUnwinder.h"
33 #include "perf_event.h"
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,
41 PERF_RECORD_FINISHED_ROUND,
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,
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 {
66 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
67 "simpleperf_record_header should have the same size as perf_event_header");
69 struct PerfSampleIpType {
73 struct PerfSampleTidType {
77 struct PerfSampleTimeType {
81 struct PerfSampleAddrType {
85 struct PerfSampleIdType {
89 struct PerfSampleStreamIdType {
93 struct PerfSampleCpuType {
97 struct PerfSamplePeriodType {
101 struct PerfSampleCallChainType {
106 struct PerfSampleRawType {
111 struct BranchStackItemType {
117 struct PerfSampleBranchStackType {
119 const BranchStackItemType* stack;
122 struct PerfSampleRegsUserType {
126 const uint64_t* regs;
129 struct PerfSampleStackUserType {
135 struct RecordHeader {
141 RecordHeader() : type(0), misc(0), size(0) {}
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;
150 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
151 type = sheader->type;
153 size = (sheader->size1 << 16) | sheader->size0;
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);
165 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
166 sheader->type = type;
168 sheader->size1 = size >> 16;
169 sheader->size0 = size & 0xffff;
171 p += sizeof(perf_event_header);
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.
181 uint64_t sample_type;
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.
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);
195 // Parse sample_id from binary format in the buffer pointed by p.
196 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
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;
205 // Usually one record contains the following three parts in order in binary
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.
216 Record() : binary_(nullptr), own_binary_(false) {}
217 explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {}
218 Record(Record&& other);
226 void OwnBinary() { own_binary_ = true; }
228 uint32_t type() const { return header.type; }
230 uint16_t misc() const { return header.misc; }
232 uint32_t size() const { return header.size; }
234 static uint32_t header_size() { return sizeof(perf_event_header); }
236 bool InKernel() const {
237 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
238 PERF_RECORD_MISC_KERNEL;
241 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
246 void SetSize(uint32_t size) { header.size = size; }
248 void Dump(size_t indent = 0) const;
250 const char* Binary() const { return binary_; }
251 char* BinaryForTestingOnly() { return binary_; }
253 virtual uint64_t Timestamp() const;
254 virtual uint32_t Cpu() const;
255 virtual uint64_t Id() const;
258 void UpdateBinary(char* new_binary);
259 virtual void DumpData(size_t) const = 0;
264 DISALLOW_COPY_AND_ASSIGN(Record);
267 struct MmapRecord : public Record {
268 struct MmapRecordDataType {
274 const MmapRecordDataType* data;
275 const char* filename;
277 MmapRecord(const perf_event_attr& attr, char* p);
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);
283 void SetDataAndFilename(const MmapRecordDataType& data,
284 const std::string& filename);
287 void DumpData(size_t indent) const override;
290 struct Mmap2Record : public Record {
291 struct Mmap2RecordDataType {
299 uint64_t ino_generation;
300 uint32_t prot, flags;
302 const Mmap2RecordDataType* data;
303 const char* filename;
305 Mmap2Record(const perf_event_attr& attr, char* p);
307 void SetDataAndFilename(const Mmap2RecordDataType& data,
308 const std::string& filename);
311 void DumpData(size_t indent) const override;
314 struct CommRecord : public Record {
315 struct CommRecordDataType {
318 const CommRecordDataType* data;
321 CommRecord(const perf_event_attr& attr, char* p);
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);
327 void DumpData(size_t indent) const override;
330 struct ExitOrForkRecord : public Record {
331 struct ExitOrForkRecordDataType {
336 const ExitOrForkRecordDataType* data;
338 ExitOrForkRecord(const perf_event_attr& attr, char* p);
340 ExitOrForkRecord() : data(nullptr) {}
343 void DumpData(size_t indent) const override;
346 struct ExitRecord : public ExitOrForkRecord {
347 ExitRecord(const perf_event_attr& attr, char* p)
348 : ExitOrForkRecord(attr, p) {}
351 struct ForkRecord : public ExitOrForkRecord {
352 ForkRecord(const perf_event_attr& attr, char* p)
353 : ExitOrForkRecord(attr, p) {}
355 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
356 uint32_t ppid, uint32_t ptid, uint64_t event_id);
359 struct LostRecord : public Record {
363 LostRecord(const perf_event_attr& attr, char* p);
366 void DumpData(size_t indent) const override;
369 struct SampleRecord : public Record {
370 uint64_t sample_type; // sample_type is a bit mask determining which fields
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.
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.
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);
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();
400 uint64_t Timestamp() const override;
401 uint32_t Cpu() const override;
402 uint64_t Id() const override;
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;
411 return stack_user_data.dyn_size;
414 void AdjustCallChainGeneratedByKernel();
417 void DumpData(size_t indent) const override;
420 // BuildIdRecord is defined in user-space, stored in BuildId feature section in
422 struct BuildIdRecord : public Record {
425 const char* filename;
427 explicit BuildIdRecord(char* p);
429 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
430 const std::string& filename);
433 void DumpData(size_t indent) const override;
436 struct KernelSymbolRecord : public Record {
437 uint32_t kallsyms_size;
438 const char* kallsyms;
440 explicit KernelSymbolRecord(char* p);
442 explicit KernelSymbolRecord(const std::string& kallsyms);
445 void DumpData(size_t indent) const override;
448 struct DsoRecord : public Record {
452 const char* dso_name;
454 explicit DsoRecord(char* p);
456 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name,
460 void DumpData(size_t indent) const override;
463 struct SymbolRecord : public Record {
469 explicit SymbolRecord(char* p);
471 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
475 void DumpData(size_t indent) const override;
478 struct TracingDataRecord : public Record {
482 explicit TracingDataRecord(char* p);
484 explicit TracingDataRecord(const std::vector<char>& tracing_data);
487 void DumpData(size_t indent) const override;
490 struct EventIdRecord : public Record {
497 explicit EventIdRecord(char* p);
499 explicit EventIdRecord(const std::vector<uint64_t>& data);
502 void DumpData(size_t indent) const override;
505 struct CallChainRecord : public Record {
514 explicit CallChainRecord(char* p);
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);
519 uint64_t Timestamp() const override {
524 void DumpData(size_t indent) const override;
527 struct UnwindingResultRecord : public Record {
529 simpleperf::UnwindingResult unwinding_result;
531 explicit UnwindingResultRecord(char* p);
533 UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result);
535 uint64_t Timestamp() const override {
540 void DumpData(size_t indent) const override;
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 {
548 explicit UnknownRecord(char* p);
551 void DumpData(size_t indent) const override;
554 // Read record from the buffer pointed by [p]. But the record doesn't own
556 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p);
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);
562 // Read records from the buffer pointed by [buf]. None of the records own
564 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
565 const perf_event_attr& attr, char* buf, size_t buf_size);
567 // Read one record from the buffer pointed by [p]. But the record doesn't
569 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p);
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.
589 explicit RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
590 uint64_t min_time_diff_in_ns = 1000000u);
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();
599 struct RecordWithSeq {
603 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {}
604 bool IsHappensBefore(const RecordWithSeq& other) const;
607 struct RecordComparator {
608 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
612 size_t min_cache_size_;
613 uint64_t min_time_diff_in_ns_;
616 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
617 RecordComparator> queue_;
620 #endif // SIMPLE_PERF_RECORD_H_