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 PerfSampleCallChainType { 107 uint64_t ip_nr; 108 uint64_t* ips; 109 }; 110 111 struct PerfSampleRawType { 112 uint32_t size; 113 const char* data; 114 }; 115 116 struct BranchStackItemType { 117 uint64_t from; 118 uint64_t to; 119 uint64_t flags; 120 }; 121 122 struct PerfSampleBranchStackType { 123 uint64_t stack_nr; 124 const BranchStackItemType* stack; 125 }; 126 127 struct PerfSampleRegsUserType { 128 uint64_t abi; 129 uint64_t reg_mask; 130 uint64_t reg_nr; 131 const uint64_t* regs; 132 }; 133 134 struct PerfSampleStackUserType { 135 uint64_t size; 136 char* data; 137 uint64_t dyn_size; 138 }; 139 140 struct RecordHeader { 141 public: 142 uint32_t type; 143 uint16_t misc; 144 uint32_t size; 145 RecordHeaderRecordHeader146 RecordHeader() : type(0), misc(0), size(0) {} 147 RecordHeaderRecordHeader148 explicit RecordHeader(const char* p) { 149 auto pheader = reinterpret_cast<const perf_event_header*>(p); 150 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) { 151 type = pheader->type; 152 misc = pheader->misc; 153 size = pheader->size; 154 } else { 155 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p); 156 type = sheader->type; 157 misc = 0; 158 size = (sheader->size1 << 16) | sheader->size0; 159 } 160 } 161 MoveToBinaryFormatRecordHeader162 void MoveToBinaryFormat(char*& p) const { 163 if (type < SIMPLE_PERF_RECORD_TYPE_START) { 164 auto pheader = reinterpret_cast<perf_event_header*>(p); 165 pheader->type = type; 166 pheader->misc = misc; 167 CHECK_LT(size, 1u << 16); 168 pheader->size = static_cast<uint16_t>(size); 169 } else { 170 auto sheader = reinterpret_cast<simpleperf_record_header*>(p); 171 sheader->type = type; 172 CHECK_EQ(misc, 0u); 173 sheader->size1 = size >> 16; 174 sheader->size0 = size & 0xffff; 175 } 176 p += sizeof(perf_event_header); 177 } 178 }; 179 180 // SampleId is optional at the end of a record in binary format. Its content is 181 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the 182 // complexity of referring to perf_event_attr each time, we copy sample_id_all 183 // and sample_type inside the SampleId structure. 184 struct SampleId { 185 bool sample_id_all; 186 uint64_t sample_type; 187 188 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID. 189 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME. 190 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID. 191 PerfSampleStreamIdType stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID. 192 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU. 193 194 SampleId(); 195 196 // Create the content of sample_id. It depends on the attr we use. 197 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id); 198 199 // Parse sample_id from binary format in the buffer pointed by p. 200 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, const char* end); 201 202 // Write the binary format of sample_id to the buffer pointed by p. 203 void WriteToBinaryFormat(char*& p) const; 204 void Dump(size_t indent) const; 205 size_t Size() const; 206 }; 207 208 // Usually one record contains the following three parts in order in binary 209 // format: 210 // RecordHeader (at the head of a record, containing type and size info) 211 // data depends on the record type 212 // SampleId (optional part at the end of a record) 213 // We hold the common parts (RecordHeader and SampleId) in the base class 214 // Record, and hold the type specific data part in classes derived from Record. 215 struct Record { 216 RecordHeader header; 217 SampleId sample_id; 218 RecordRecord219 Record() : binary_(nullptr), own_binary_(false) {} RecordRecord220 explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {} 221 Record(Record&& other) noexcept; 222 ~RecordRecord223 virtual ~Record() { 224 if (own_binary_) { 225 delete[] binary_; 226 } 227 } 228 OwnBinaryRecord229 void OwnBinary() { own_binary_ = true; } 230 typeRecord231 uint32_t type() const { return header.type; } 232 miscRecord233 uint16_t misc() const { return header.misc; } 234 sizeRecord235 uint32_t size() const { return header.size; } 236 header_sizeRecord237 static uint32_t header_size() { return sizeof(perf_event_header); } 238 InKernelRecord239 bool InKernel() const { 240 uint16_t cpumode = header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 241 return cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL; 242 } 243 SetTypeAndMiscRecord244 void SetTypeAndMisc(uint32_t type, uint16_t misc) { 245 header.type = type; 246 header.misc = misc; 247 } 248 SetSizeRecord249 void SetSize(uint32_t size) { header.size = size; } 250 251 void Dump(size_t indent = 0) const; 252 BinaryRecord253 const char* Binary() const { return binary_; } BinaryForTestingOnlyRecord254 char* BinaryForTestingOnly() { return binary_; } 255 256 virtual uint64_t Timestamp() const; 257 virtual uint32_t Cpu() const; 258 virtual uint64_t Id() const; 259 260 protected: 261 void UpdateBinary(char* new_binary); 262 virtual void DumpData(size_t) const = 0; 263 264 char* binary_; 265 bool own_binary_; 266 267 DISALLOW_COPY_AND_ASSIGN(Record); 268 }; 269 270 struct MmapRecord : public Record { 271 struct MmapRecordDataType { 272 uint32_t pid, tid; 273 uint64_t addr; 274 uint64_t len; 275 uint64_t pgoff; 276 }; 277 const MmapRecordDataType* data; 278 const char* filename; 279 280 MmapRecord(const perf_event_attr& attr, char* p); 281 282 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, uint64_t addr, 283 uint64_t len, uint64_t pgoff, const std::string& filename, uint64_t event_id, 284 uint64_t time = 0); 285 286 void SetDataAndFilename(const MmapRecordDataType& data, const std::string& filename); 287 288 protected: 289 void DumpData(size_t indent) const override; 290 }; 291 292 struct Mmap2Record : public Record { 293 struct Mmap2RecordDataType { 294 uint32_t pid, tid; 295 uint64_t addr; 296 uint64_t len; 297 uint64_t pgoff; 298 uint32_t maj; 299 uint32_t min; 300 uint64_t ino; 301 uint64_t ino_generation; 302 uint32_t prot, flags; 303 }; 304 const Mmap2RecordDataType* data; 305 const char* filename; 306 307 Mmap2Record(const perf_event_attr& attr, char* p); 308 Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, 309 uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot, 310 const std::string& filename, uint64_t event_id, uint64_t time = 0); 311 312 void SetDataAndFilename(const Mmap2RecordDataType& data, const std::string& filename); 313 314 protected: 315 void DumpData(size_t indent) const override; 316 }; 317 318 struct CommRecord : public Record { 319 struct CommRecordDataType { 320 uint32_t pid, tid; 321 }; 322 const CommRecordDataType* data; 323 const char* comm; 324 325 CommRecord(const perf_event_attr& attr, char* p); 326 327 CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, const std::string& comm, 328 uint64_t event_id, uint64_t time); 329 330 void SetCommandName(const std::string& name); 331 332 protected: 333 void DumpData(size_t indent) const override; 334 }; 335 336 struct ExitOrForkRecord : public Record { 337 struct ExitOrForkRecordDataType { 338 uint32_t pid, ppid; 339 uint32_t tid, ptid; 340 uint64_t time; 341 }; 342 const ExitOrForkRecordDataType* data; 343 344 ExitOrForkRecord(const perf_event_attr& attr, char* p); 345 ExitOrForkRecordExitOrForkRecord346 ExitOrForkRecord() : data(nullptr) {} 347 348 protected: 349 void DumpData(size_t indent) const override; 350 }; 351 352 struct ExitRecord : public ExitOrForkRecord { ExitRecordExitRecord353 ExitRecord(const perf_event_attr& attr, char* p) : ExitOrForkRecord(attr, p) {} 354 }; 355 356 struct ForkRecord : public ExitOrForkRecord { ForkRecordForkRecord357 ForkRecord(const perf_event_attr& attr, char* p) : ExitOrForkRecord(attr, p) {} 358 359 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, uint32_t ppid, uint32_t ptid, 360 uint64_t event_id); 361 }; 362 363 struct LostRecord : public Record { 364 uint64_t id; 365 uint64_t lost; 366 367 LostRecord(const perf_event_attr& attr, char* p); 368 369 protected: 370 void DumpData(size_t indent) const override; 371 }; 372 373 struct SampleRecord : public Record { 374 uint64_t sample_type; // sample_type is a bit mask determining which fields 375 // below are valid. 376 377 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP. 378 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID. 379 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME. 380 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR. 381 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID. 382 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID. 383 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU. 384 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD. 385 386 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN. 387 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW. 388 PerfSampleBranchStackType branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK. 389 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER. 390 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER. 391 392 SampleRecord(const perf_event_attr& attr, char* p); 393 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, uint32_t pid, uint32_t tid, 394 uint64_t time, uint32_t cpu, uint64_t period, const std::vector<uint64_t>& ips, 395 const std::vector<char>& stack, uint64_t dyn_stack_size); 396 397 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips); 398 // Remove kernel callchain, return true if there is a user space callchain left, otherwise 399 // return false. 400 bool ExcludeKernelCallChain(); 401 bool HasUserCallChain() const; 402 void UpdateUserCallChain(const std::vector<uint64_t>& user_ips); 403 404 uint64_t Timestamp() const override; 405 uint32_t Cpu() const override; 406 uint64_t Id() const override; 407 GetValidStackSizeSampleRecord408 uint64_t GetValidStackSize() const { 409 // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer(). 410 return stack_user_data.size; 411 } 412 413 void AdjustCallChainGeneratedByKernel(); 414 std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const; 415 416 protected: 417 void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips); 418 void DumpData(size_t indent) const override; 419 }; 420 421 struct AuxRecord : public Record { 422 struct DataType { 423 uint64_t aux_offset; 424 uint64_t aux_size; 425 uint64_t flags; 426 } * data; 427 428 AuxRecord(const perf_event_attr& attr, char* p); 429 430 protected: 431 void DumpData(size_t indent) const override; 432 }; 433 434 // BuildIdRecord is defined in user-space, stored in BuildId feature section in 435 // record file. 436 struct BuildIdRecord : public Record { 437 uint32_t pid; 438 BuildId build_id; 439 const char* filename; 440 441 explicit BuildIdRecord(char* p); 442 443 BuildIdRecord(bool in_kernel, uint32_t pid, const BuildId& build_id, const std::string& filename); 444 445 protected: 446 void DumpData(size_t indent) const override; 447 }; 448 449 struct AuxTraceInfoRecord : public Record { 450 // magic values to be compatible with linux perf 451 static const uint32_t AUX_TYPE_ETM = 3; 452 static const uint64_t MAGIC_ETM4 = 0x4040404040404040ULL; 453 454 struct ETM4Info { 455 uint64_t magic; 456 uint64_t cpu; 457 uint64_t trcconfigr; 458 uint64_t trctraceidr; 459 uint64_t trcidr0; 460 uint64_t trcidr1; 461 uint64_t trcidr2; 462 uint64_t trcidr8; 463 uint64_t trcauthstatus; 464 }; 465 466 struct DataType { 467 uint32_t aux_type; 468 uint32_t reserved; 469 uint64_t version; 470 uint32_t nr_cpu; 471 uint32_t pmu_type; 472 uint64_t snapshot; 473 ETM4Info etm4_info[0]; 474 } * data; 475 476 explicit AuxTraceInfoRecord(char* p); 477 AuxTraceInfoRecord(const DataType& data, const std::vector<ETM4Info>& etm4_info); 478 479 protected: 480 void DumpData(size_t indent) const override; 481 }; 482 483 struct AuxTraceRecord : public Record { 484 struct DataType { 485 uint64_t aux_size; 486 uint64_t offset; 487 uint64_t reserved0; // reference 488 uint32_t idx; 489 uint32_t tid; 490 uint32_t cpu; 491 uint32_t reserved1; 492 } * data; 493 // AuxTraceRecord is followed by aux tracing data with size data->aux_size. 494 // The location of aux tracing data in memory or file is kept in location. 495 struct AuxDataLocation { 496 const char* addr = nullptr; 497 uint64_t file_offset = 0; 498 } location; 499 500 explicit AuxTraceRecord(char* p); 501 AuxTraceRecord(uint64_t aux_size, uint64_t offset, uint32_t idx, uint32_t tid, uint32_t cpu); 502 SizeAuxTraceRecord503 static size_t Size() { return sizeof(perf_event_header) + sizeof(DataType); } 504 505 protected: 506 void DumpData(size_t indent) const override; 507 }; 508 509 struct KernelSymbolRecord : public Record { 510 uint32_t kallsyms_size; 511 const char* kallsyms; 512 513 explicit KernelSymbolRecord(char* p); 514 515 explicit KernelSymbolRecord(const std::string& kallsyms); 516 517 protected: 518 void DumpData(size_t indent) const override; 519 }; 520 521 struct DsoRecord : public Record { 522 uint64_t dso_type; 523 uint64_t dso_id; 524 uint64_t min_vaddr; 525 const char* dso_name; 526 527 explicit DsoRecord(char* p); 528 529 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name, uint64_t min_vaddr); 530 531 protected: 532 void DumpData(size_t indent) const override; 533 }; 534 535 struct SymbolRecord : public Record { 536 uint64_t addr; 537 uint64_t len; 538 uint64_t dso_id; 539 const char* name; 540 541 explicit SymbolRecord(char* p); 542 543 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, uint64_t dso_id); 544 545 protected: 546 void DumpData(size_t indent) const override; 547 }; 548 549 struct TracingDataRecord : public Record { 550 uint32_t data_size; 551 const char* data; 552 553 explicit TracingDataRecord(char* p); 554 555 explicit TracingDataRecord(const std::vector<char>& tracing_data); 556 557 protected: 558 void DumpData(size_t indent) const override; 559 }; 560 561 struct EventIdRecord : public Record { 562 uint64_t count; 563 struct EventIdData { 564 uint64_t attr_id; 565 uint64_t event_id; 566 } const* data; 567 568 explicit EventIdRecord(char* p); 569 570 explicit EventIdRecord(const std::vector<uint64_t>& data); 571 572 protected: 573 void DumpData(size_t indent) const override; 574 }; 575 576 struct CallChainRecord : public Record { 577 uint32_t pid; 578 uint32_t tid; 579 uint64_t chain_type; 580 uint64_t time; 581 uint64_t ip_nr; 582 uint64_t* ips; 583 uint64_t* sps; 584 585 explicit CallChainRecord(char* p); 586 587 CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time, 588 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps); 589 TimestampCallChainRecord590 uint64_t Timestamp() const override { return time; } 591 592 protected: 593 void DumpData(size_t indent) const override; 594 }; 595 596 struct UnwindingResultRecord : public Record { 597 uint64_t time; 598 UnwindingResult unwinding_result; 599 PerfSampleRegsUserType regs_user_data; 600 PerfSampleStackUserType stack_user_data; 601 602 struct CallChain { 603 uint64_t length = 0; 604 uint64_t* ips = nullptr; 605 uint64_t* sps = nullptr; 606 } callchain; 607 608 explicit UnwindingResultRecord(char* p); 609 610 UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result, 611 const PerfSampleRegsUserType& regs_user_data, 612 const PerfSampleStackUserType& stack_user_data, 613 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps); 614 TimestampUnwindingResultRecord615 uint64_t Timestamp() const override { return time; } 616 617 protected: 618 void DumpData(size_t indent) const override; 619 }; 620 621 // UnknownRecord is used for unknown record types, it makes sure all unknown 622 // records are not changed when modifying perf.data. 623 struct UnknownRecord : public Record { 624 const char* data; 625 626 explicit UnknownRecord(char* p); 627 628 protected: 629 void DumpData(size_t indent) const override; 630 }; 631 632 // Read record from the buffer pointed by [p]. But the record doesn't own 633 // the buffer. 634 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p); 635 636 // Read record from the buffer pointed by [p]. And the record owns the buffer. 637 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr, uint32_t type, 638 char* p); 639 640 // Read records from the buffer pointed by [buf]. None of the records own 641 // the buffer. 642 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr& attr, char* buf, 643 size_t buf_size); 644 645 // Read one record from the buffer pointed by [p]. But the record doesn't 646 // own the buffer. 647 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p); 648 649 } // namespace simpleperf 650 651 #endif // SIMPLE_PERF_RECORD_H_ 652