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