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 "CallChainJoiner.h" 31 #include "OfflineUnwinder.h" 32 #include "build_id.h" 33 #include "perf_event.h" 34 35 namespace simpleperf { 36 37 enum user_record_type { 38 PERF_RECORD_USER_DEFINED_TYPE_START = 64, 39 PERF_RECORD_ATTR = 64, 40 PERF_RECORD_EVENT_TYPE, 41 PERF_RECORD_TRACING_DATA, 42 PERF_RECORD_BUILD_ID, 43 PERF_RECORD_FINISHED_ROUND, 44 45 PERF_RECORD_AUXTRACE_INFO = 70, 46 PERF_RECORD_AUXTRACE = 71, 47 PERF_RECORD_COMPRESSED = 81, 48 49 SIMPLE_PERF_RECORD_TYPE_START = 32768, 50 SIMPLE_PERF_RECORD_KERNEL_SYMBOL, 51 // TODO: remove DsoRecord and SymbolRecord. 52 SIMPLE_PERF_RECORD_DSO, 53 SIMPLE_PERF_RECORD_SYMBOL, 54 SIMPLE_PERF_RECORD_SPLIT, 55 SIMPLE_PERF_RECORD_SPLIT_END, 56 SIMPLE_PERF_RECORD_EVENT_ID, 57 SIMPLE_PERF_RECORD_CALLCHAIN, 58 SIMPLE_PERF_RECORD_UNWINDING_RESULT, 59 SIMPLE_PERF_RECORD_TRACING_DATA, 60 SIMPLE_PERF_RECORD_DEBUG, 61 }; 62 63 // perf_event_header uses u16 to store record size. However, that is not 64 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define 65 // a simpleperf_record_header struct to store record header for simpleperf 66 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START). 67 struct simpleperf_record_header { 68 uint32_t type; 69 uint16_t size1; 70 uint16_t size0; 71 }; 72 73 static_assert(sizeof(simpleperf_record_header) == sizeof(perf_event_header), 74 "simpleperf_record_header should have the same size as perf_event_header"); 75 76 struct PerfSampleIpType { 77 uint64_t ip; 78 }; 79 80 struct PerfSampleTidType { 81 uint32_t pid, tid; 82 }; 83 84 struct PerfSampleTimeType { 85 uint64_t time; 86 }; 87 88 struct PerfSampleAddrType { 89 uint64_t addr; 90 }; 91 92 struct PerfSampleIdType { 93 uint64_t id; 94 }; 95 96 struct PerfSampleStreamIdType { 97 uint64_t stream_id; 98 }; 99 100 struct PerfSampleCpuType { 101 uint32_t cpu, res; 102 }; 103 104 struct PerfSamplePeriodType { 105 uint64_t period; 106 }; 107 108 struct PerfSampleReadType { 109 uint64_t time_enabled = 0; 110 uint64_t time_running = 0; 111 std::vector<uint64_t> counts; 112 std::vector<uint64_t> ids; 113 }; 114 115 struct PerfSampleCallChainType { 116 uint64_t ip_nr; 117 uint64_t* ips; 118 }; 119 120 struct PerfSampleRawType { 121 uint32_t size; 122 const char* data; 123 }; 124 125 struct BranchStackItemType { 126 uint64_t from; 127 uint64_t to; 128 uint64_t flags; 129 }; 130 131 struct PerfSampleBranchStackType { 132 uint64_t stack_nr; 133 const BranchStackItemType* stack; 134 }; 135 136 struct PerfSampleRegsUserType { 137 uint64_t abi; 138 uint64_t reg_mask; 139 uint64_t reg_nr; 140 const uint64_t* regs; 141 }; 142 143 struct PerfSampleStackUserType { 144 uint64_t size; 145 char* data; 146 uint64_t dyn_size; 147 }; 148 149 struct RecordHeader { 150 public: 151 uint32_t type; 152 uint16_t misc; 153 uint32_t size; 154 RecordHeaderRecordHeader155 RecordHeader() : type(0), misc(0), size(0) {} 156 ParseRecordHeader157 bool Parse(const char* p) { 158 auto pheader = reinterpret_cast<const perf_event_header*>(p); 159 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) { 160 type = pheader->type; 161 misc = pheader->misc; 162 size = pheader->size; 163 } else { 164 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p); 165 type = sheader->type; 166 misc = 0; 167 size = (sheader->size1 << 16) | sheader->size0; 168 } 169 if (size < sizeof(perf_event_header)) { 170 LOG(ERROR) << "invalid record"; 171 return false; 172 } 173 return true; 174 } 175 MoveToBinaryFormatRecordHeader176 void MoveToBinaryFormat(char*& p) const { 177 if (type < SIMPLE_PERF_RECORD_TYPE_START) { 178 auto pheader = reinterpret_cast<perf_event_header*>(p); 179 pheader->type = type; 180 pheader->misc = misc; 181 CHECK_LT(size, 1u << 16); 182 pheader->size = static_cast<uint16_t>(size); 183 } else { 184 auto sheader = reinterpret_cast<simpleperf_record_header*>(p); 185 sheader->type = type; 186 CHECK_EQ(misc, 0u); 187 sheader->size1 = size >> 16; 188 sheader->size0 = size & 0xffff; 189 } 190 p += sizeof(perf_event_header); 191 } 192 }; 193 194 // SampleId is optional at the end of a record in binary format. Its content is 195 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the 196 // complexity of referring to perf_event_attr each time, we copy sample_id_all 197 // and sample_type inside the SampleId structure. 198 struct SampleId { 199 bool sample_id_all; 200 uint64_t sample_type; 201 202 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID. 203 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME. 204 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID. 205 PerfSampleStreamIdType stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID. 206 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU. 207 208 SampleId(); 209 210 // Create the content of sample_id. It depends on the attr we use. 211 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id); 212 213 // Parse sample_id from binary format in the buffer pointed by p. 214 bool ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end); 215 216 // Write the binary format of sample_id to the buffer pointed by p. 217 void WriteToBinaryFormat(char*& p) const; 218 void Dump(size_t indent) const; 219 size_t Size() const; 220 }; 221 222 // Usually one record contains the following three parts in order in binary 223 // format: 224 // RecordHeader (at the head of a record, containing type and size info) 225 // data depends on the record type 226 // SampleId (optional part at the end of a record) 227 // We hold the common parts (RecordHeader and SampleId) in the base class 228 // Record, and hold the type specific data part in classes derived from Record. 229 struct Record { 230 RecordHeader header; 231 SampleId sample_id; 232 RecordRecord233 Record() : binary_(nullptr), own_binary_(false) {} 234 Record(Record&& other) noexcept; 235 ~RecordRecord236 virtual ~Record() { 237 if (own_binary_) { 238 delete[] binary_; 239 } 240 } 241 242 virtual bool Parse(const perf_event_attr& attr, char* p, char* end) = 0; 243 OwnBinaryRecord244 void OwnBinary() { own_binary_ = true; } 245 typeRecord246 uint32_t type() const { return header.type; } 247 miscRecord248 uint16_t misc() const { return header.misc; } 249 sizeRecord250 uint32_t size() const { return header.size; } 251 header_sizeRecord252 static uint32_t header_size() { return sizeof(perf_event_header); } 253 InKernelRecord254 bool InKernel() const { 255 uint16_t cpumode = header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 256 return cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL; 257 } 258 SetTypeAndMiscRecord259 void SetTypeAndMisc(uint32_t type, uint16_t misc) { 260 header.type = type; 261 header.misc = misc; 262 } 263 SetSizeRecord264 void SetSize(uint32_t size) { header.size = size; } 265 266 void Dump(size_t indent = 0) const; 267 BinaryRecord268 const char* Binary() const { return binary_; } BinaryForTestingOnlyRecord269 char* BinaryForTestingOnly() { return binary_; } 270 271 virtual uint64_t Timestamp() const; 272 virtual uint32_t Cpu() const; 273 virtual uint64_t Id() const; 274 275 protected: 276 bool ParseHeader(char*& p, char*& end); 277 void UpdateBinary(char* new_binary); 278 virtual void DumpData(size_t) const = 0; 279 280 char* binary_; 281 bool own_binary_; 282 283 DISALLOW_COPY_AND_ASSIGN(Record); 284 }; 285 286 struct MmapRecord : public Record { 287 struct MmapRecordDataType { 288 uint32_t pid, tid; 289 uint64_t addr; 290 uint64_t len; 291 uint64_t pgoff; 292 }; 293 const MmapRecordDataType* data; 294 const char* filename; 295 MmapRecordMmapRecord296 MmapRecord() {} 297 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, uint64_t addr, 298 uint64_t len, uint64_t pgoff, const std::string& filename, uint64_t event_id, 299 uint64_t time = 0); 300 301 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 302 void SetDataAndFilename(const MmapRecordDataType& data, const std::string& filename); 303 304 protected: 305 void DumpData(size_t indent) const override; 306 }; 307 308 struct Mmap2Record : public Record { 309 struct Mmap2RecordDataType { 310 uint32_t pid, tid; 311 uint64_t addr; 312 uint64_t len; 313 uint64_t pgoff; 314 uint32_t maj; 315 uint32_t min; 316 uint64_t ino; 317 uint64_t ino_generation; 318 uint32_t prot, flags; 319 }; 320 const Mmap2RecordDataType* data; 321 const char* filename; 322 Mmap2RecordMmap2Record323 Mmap2Record() {} 324 Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, 325 uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot, 326 const std::string& filename, uint64_t event_id, uint64_t time = 0); 327 328 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 329 void SetDataAndFilename(const Mmap2RecordDataType& data, const std::string& filename); 330 331 protected: 332 void DumpData(size_t indent) const override; 333 }; 334 335 struct CommRecord : public Record { 336 struct CommRecordDataType { 337 uint32_t pid, tid; 338 }; 339 const CommRecordDataType* data; 340 const char* comm; 341 CommRecordCommRecord342 CommRecord() {} 343 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, const std::string& comm, 344 uint64_t event_id, uint64_t time); 345 346 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 347 void SetCommandName(const std::string& name); 348 349 protected: 350 void DumpData(size_t indent) const override; 351 }; 352 353 struct ExitOrForkRecord : public Record { 354 struct ExitOrForkRecordDataType { 355 uint32_t pid, ppid; 356 uint32_t tid, ptid; 357 uint64_t time; 358 }; 359 const ExitOrForkRecordDataType* data; 360 ExitOrForkRecordExitOrForkRecord361 ExitOrForkRecord() : data(nullptr) {} 362 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 363 364 protected: 365 void DumpData(size_t indent) const override; 366 }; 367 368 struct ExitRecord : public ExitOrForkRecord {}; 369 370 struct ForkRecord : public ExitOrForkRecord { ForkRecordForkRecord371 ForkRecord() {} 372 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid, uint32_t ptid, 373 uint64_t event_id); 374 }; 375 376 struct LostRecord : public Record { 377 uint64_t id; 378 uint64_t lost; 379 380 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 381 382 protected: 383 void DumpData(size_t indent) const override; 384 }; 385 386 struct SampleRecord : public Record { 387 uint64_t sample_type; // sample_type is a bit mask determining which fields 388 // below are valid. 389 uint64_t read_format; 390 391 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP. 392 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID. 393 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME. 394 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR. 395 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID. 396 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID. 397 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU. 398 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD. 399 PerfSampleReadType read_data; // Valid if PERF_SAMPLE_READ. 400 401 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN. 402 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW. 403 PerfSampleBranchStackType branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK. 404 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER. 405 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER. 406 SampleRecordSampleRecord407 SampleRecord() {} 408 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, uint32_t pid, uint32_t tid, 409 uint64_t time, uint32_t cpu, uint64_t period, const PerfSampleReadType& read_data, 410 const std::vector<uint64_t>& ips, const std::vector<char>& stack, 411 uint64_t dyn_stack_size); 412 413 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 414 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips); 415 // Remove kernel callchain, return true if there is a user space callchain left, otherwise 416 // return false. 417 bool ExcludeKernelCallChain(); 418 bool HasUserCallChain() const; 419 void UpdateUserCallChain(const std::vector<uint64_t>& user_ips); 420 421 uint64_t Timestamp() const override; 422 uint32_t Cpu() const override; 423 uint64_t Id() const override; 424 GetValidStackSizeSampleRecord425 uint64_t GetValidStackSize() const { 426 // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer(). 427 return stack_user_data.size; 428 } 429 430 void AdjustCallChainGeneratedByKernel(); 431 std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const; 432 433 protected: 434 void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips); 435 void DumpData(size_t indent) const override; 436 }; 437 438 struct AuxRecord : public Record { 439 struct DataType { 440 uint64_t aux_offset; 441 uint64_t aux_size; 442 uint64_t flags; 443 }* data; 444 445 bool Parse(const perf_event_attr& attr, char* p, char* end) override; UnformattedAuxRecord446 bool Unformatted() const { return data->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW; } 447 448 protected: 449 void DumpData(size_t indent) const override; 450 }; 451 452 struct SwitchRecord : public Record { 453 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 454 455 protected: DumpDataSwitchRecord456 void DumpData(size_t) const override {} 457 }; 458 459 struct SwitchCpuWideRecord : public Record { 460 PerfSampleTidType tid_data; 461 462 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 463 464 protected: 465 void DumpData(size_t indent) const override; 466 }; 467 468 // BuildIdRecord is defined in user-space, stored in BuildId feature section in 469 // record file. 470 struct BuildIdRecord : public Record { 471 uint32_t pid; 472 BuildId build_id; 473 const char* filename; 474 BuildIdRecordBuildIdRecord475 BuildIdRecord() {} 476 BuildIdRecord(bool in_kernel, uint32_t pid, const BuildId& build_id, const std::string& filename); 477 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 478 479 protected: 480 void DumpData(size_t indent) const override; 481 }; 482 483 struct AuxTraceInfoRecord : public Record { 484 // magic values to be compatible with linux perf 485 static constexpr uint32_t AUX_TYPE_ETM = 3; 486 static constexpr uint64_t MAGIC_ETM4 = 0x4040404040404040ULL; 487 static constexpr uint64_t MAGIC_ETE = 0x5050505050505050ULL; 488 489 struct ETM4Info { 490 uint64_t magic; 491 uint64_t cpu; 492 uint64_t nrtrcparams; 493 uint64_t trcconfigr; 494 uint64_t trctraceidr; 495 uint64_t trcidr0; 496 uint64_t trcidr1; 497 uint64_t trcidr2; 498 uint64_t trcidr8; 499 uint64_t trcauthstatus; 500 }; 501 502 struct ETEInfo { 503 uint64_t magic; 504 uint64_t cpu; 505 uint64_t nrtrcparams; 506 uint64_t trcconfigr; 507 uint64_t trctraceidr; 508 uint64_t trcidr0; 509 uint64_t trcidr1; 510 uint64_t trcidr2; 511 uint64_t trcidr8; 512 uint64_t trcauthstatus; 513 uint64_t trcdevarch; 514 }; 515 516 struct DataType { 517 uint32_t aux_type; 518 uint32_t reserved; 519 uint64_t version; 520 uint32_t nr_cpu; 521 uint32_t pmu_type; 522 uint64_t snapshot; 523 uint64_t info[0]; 524 }* data; 525 AuxTraceInfoRecordAuxTraceInfoRecord526 AuxTraceInfoRecord() {} 527 AuxTraceInfoRecord(const DataType& data, const std::vector<ETEInfo>& ete_info); 528 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 529 530 protected: 531 void DumpData(size_t indent) const override; 532 }; 533 534 struct AuxTraceRecord : public Record { 535 struct DataType { 536 uint64_t aux_size; 537 uint64_t offset; 538 uint64_t reserved0; // reference 539 uint32_t idx; 540 uint32_t tid; 541 uint32_t cpu; 542 uint32_t reserved1; 543 }* data; 544 // AuxTraceRecord is followed by aux tracing data with size data->aux_size. 545 // The location of aux tracing data in memory or file is kept in location. 546 struct AuxDataLocation { 547 const char* addr = nullptr; 548 uint64_t file_offset = 0; 549 } location; 550 AuxTraceRecordAuxTraceRecord551 AuxTraceRecord() {} 552 AuxTraceRecord(uint64_t aux_size, uint64_t offset, uint32_t idx, uint32_t tid, uint32_t cpu); 553 554 bool Parse(const perf_event_attr& attr, char* p, char* end) override; CpuAuxTraceRecord555 uint32_t Cpu() const override { return data->cpu; } SizeAuxTraceRecord556 static size_t Size() { return sizeof(perf_event_header) + sizeof(DataType); } 557 558 protected: 559 void DumpData(size_t indent) const override; 560 }; 561 562 struct KernelSymbolRecord : public Record { 563 uint32_t kallsyms_size; 564 const char* kallsyms; 565 KernelSymbolRecordKernelSymbolRecord566 KernelSymbolRecord() {} 567 explicit KernelSymbolRecord(const std::string& kallsyms); 568 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 569 570 protected: 571 void DumpData(size_t indent) const override; 572 }; 573 574 struct DsoRecord : public Record { 575 uint64_t dso_type; 576 uint64_t dso_id; 577 uint64_t min_vaddr; 578 const char* dso_name; 579 DsoRecordDsoRecord580 DsoRecord() {} 581 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name, uint64_t min_vaddr); 582 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 583 584 protected: 585 void DumpData(size_t indent) const override; 586 }; 587 588 struct SymbolRecord : public Record { 589 uint64_t addr; 590 uint64_t len; 591 uint64_t dso_id; 592 const char* name; 593 SymbolRecordSymbolRecord594 SymbolRecord() {} 595 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, uint64_t dso_id); 596 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 597 598 protected: 599 void DumpData(size_t indent) const override; 600 }; 601 602 struct TracingDataRecord : public Record { 603 uint32_t data_size; 604 const char* data; 605 TracingDataRecordTracingDataRecord606 TracingDataRecord() {} 607 explicit TracingDataRecord(const std::vector<char>& tracing_data); 608 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 609 610 protected: 611 void DumpData(size_t indent) const override; 612 }; 613 614 struct EventIdRecord : public Record { 615 uint64_t count; 616 struct EventIdData { 617 uint64_t attr_id; 618 uint64_t event_id; 619 } const* data; 620 EventIdRecordEventIdRecord621 EventIdRecord() {} 622 explicit EventIdRecord(const std::vector<uint64_t>& data); 623 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 624 625 protected: 626 void DumpData(size_t indent) const override; 627 }; 628 629 struct CallChainRecord : public Record { 630 uint32_t pid; 631 uint32_t tid; 632 uint64_t chain_type; 633 uint64_t time; 634 uint64_t ip_nr; 635 uint64_t* ips; 636 uint64_t* sps; 637 CallChainRecordCallChainRecord638 CallChainRecord() {} 639 640 CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time, 641 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps); 642 643 bool Parse(const perf_event_attr& attr, char* p, char* end) override; TimestampCallChainRecord644 uint64_t Timestamp() const override { return time; } 645 646 protected: 647 void DumpData(size_t indent) const override; 648 }; 649 650 struct UnwindingResultRecord : public Record { 651 uint64_t time; 652 UnwindingResult unwinding_result; 653 PerfSampleRegsUserType regs_user_data; 654 PerfSampleStackUserType stack_user_data; 655 656 struct CallChain { 657 uint64_t length = 0; 658 uint64_t* ips = nullptr; 659 uint64_t* sps = nullptr; 660 } callchain; 661 UnwindingResultRecordUnwindingResultRecord662 UnwindingResultRecord() {} 663 664 UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result, 665 const PerfSampleRegsUserType& regs_user_data, 666 const PerfSampleStackUserType& stack_user_data, 667 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps); 668 669 bool Parse(const perf_event_attr& attr, char* p, char* end) override; TimestampUnwindingResultRecord670 uint64_t Timestamp() const override { return time; } 671 672 protected: 673 void DumpData(size_t indent) const override; 674 }; 675 676 // Add a debug string in the recording file. 677 struct DebugRecord : public Record { 678 uint64_t time = 0; 679 char* s = nullptr; 680 DebugRecordDebugRecord681 DebugRecord() {} 682 683 DebugRecord(uint64_t time, const std::string& s); 684 685 bool Parse(const perf_event_attr& attr, char* p, char* end) override; TimestampDebugRecord686 uint64_t Timestamp() const override { return time; } 687 688 protected: 689 void DumpData(size_t indent) const override; 690 }; 691 692 // UnknownRecord is used for unknown record types, it makes sure all unknown 693 // records are not changed when modifying perf.data. 694 struct UnknownRecord : public Record { 695 const char* data; 696 697 bool Parse(const perf_event_attr& attr, char* p, char* end) override; 698 699 protected: 700 void DumpData(size_t indent) const override; 701 }; 702 703 // Read record from the buffer pointed by [p]. But the record doesn't own 704 // the buffer. 705 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p, 706 char* end); 707 708 // Read records from the buffer pointed by [buf]. None of the records own 709 // the buffer. 710 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr, char* buf, 711 size_t buf_size); 712 713 // Read one record from the buffer pointed by [p]. But the record doesn't 714 // own the buffer. 715 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p, char* end); 716 717 } // namespace simpleperf 718 719 #endif // SIMPLE_PERF_RECORD_H_ 720