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