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