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 SIMPLE_PERF_RECORD_TYPE_START = 32768, 44 SIMPLE_PERF_RECORD_KERNEL_SYMBOL, 45 // TODO: remove DsoRecord and SymbolRecord. 46 SIMPLE_PERF_RECORD_DSO, 47 SIMPLE_PERF_RECORD_SYMBOL, 48 SIMPLE_PERF_RECORD_SPLIT, 49 SIMPLE_PERF_RECORD_SPLIT_END, 50 SIMPLE_PERF_RECORD_EVENT_ID, 51 SIMPLE_PERF_RECORD_CALLCHAIN, 52 SIMPLE_PERF_RECORD_UNWINDING_RESULT, 53 SIMPLE_PERF_RECORD_TRACING_DATA, 54 }; 55 56 // perf_event_header uses u16 to store record size. However, that is not 57 // enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define 58 // a simpleperf_record_header struct to store record header for simpleperf 59 // defined records (type > SIMPLE_PERF_RECORD_TYPE_START). 60 struct simpleperf_record_header { 61 uint32_t type; 62 uint16_t size1; 63 uint16_t size0; 64 }; 65 66 static_assert( 67 sizeof(simpleperf_record_header) == sizeof(perf_event_header), 68 "simpleperf_record_header should have the same size as perf_event_header"); 69 70 struct PerfSampleIpType { 71 uint64_t ip; 72 }; 73 74 struct PerfSampleTidType { 75 uint32_t pid, tid; 76 }; 77 78 struct PerfSampleTimeType { 79 uint64_t time; 80 }; 81 82 struct PerfSampleAddrType { 83 uint64_t addr; 84 }; 85 86 struct PerfSampleIdType { 87 uint64_t id; 88 }; 89 90 struct PerfSampleStreamIdType { 91 uint64_t stream_id; 92 }; 93 94 struct PerfSampleCpuType { 95 uint32_t cpu, res; 96 }; 97 98 struct PerfSamplePeriodType { 99 uint64_t period; 100 }; 101 102 struct PerfSampleCallChainType { 103 uint64_t ip_nr; 104 uint64_t* ips; 105 }; 106 107 struct PerfSampleRawType { 108 uint32_t size; 109 const char* data; 110 }; 111 112 struct BranchStackItemType { 113 uint64_t from; 114 uint64_t to; 115 uint64_t flags; 116 }; 117 118 struct PerfSampleBranchStackType { 119 uint64_t stack_nr; 120 const BranchStackItemType* stack; 121 }; 122 123 struct PerfSampleRegsUserType { 124 uint64_t abi; 125 uint64_t reg_mask; 126 uint64_t reg_nr; 127 const uint64_t* regs; 128 }; 129 130 struct PerfSampleStackUserType { 131 uint64_t size; 132 char* data; 133 uint64_t dyn_size; 134 }; 135 136 struct RecordHeader { 137 public: 138 uint32_t type; 139 uint16_t misc; 140 uint32_t size; 141 RecordHeaderRecordHeader142 RecordHeader() : type(0), misc(0), size(0) {} 143 RecordHeaderRecordHeader144 explicit RecordHeader(const char* p) { 145 auto pheader = reinterpret_cast<const perf_event_header*>(p); 146 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) { 147 type = pheader->type; 148 misc = pheader->misc; 149 size = pheader->size; 150 } else { 151 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p); 152 type = sheader->type; 153 misc = 0; 154 size = (sheader->size1 << 16) | sheader->size0; 155 } 156 } 157 MoveToBinaryFormatRecordHeader158 void MoveToBinaryFormat(char*& p) const { 159 if (type < SIMPLE_PERF_RECORD_TYPE_START) { 160 auto pheader = reinterpret_cast<perf_event_header*>(p); 161 pheader->type = type; 162 pheader->misc = misc; 163 CHECK_LT(size, 1u << 16); 164 pheader->size = static_cast<uint16_t>(size); 165 } else { 166 auto sheader = reinterpret_cast<simpleperf_record_header*>(p); 167 sheader->type = type; 168 CHECK_EQ(misc, 0u); 169 sheader->size1 = size >> 16; 170 sheader->size0 = size & 0xffff; 171 } 172 p += sizeof(perf_event_header); 173 } 174 }; 175 176 // SampleId is optional at the end of a record in binary format. Its content is 177 // determined by sample_id_all and sample_type in perf_event_attr. To avoid the 178 // complexity of referring to perf_event_attr each time, we copy sample_id_all 179 // and sample_type inside the SampleId structure. 180 struct SampleId { 181 bool sample_id_all; 182 uint64_t sample_type; 183 184 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID. 185 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME. 186 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID. 187 PerfSampleStreamIdType 188 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID. 189 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU. 190 191 SampleId(); 192 193 // Create the content of sample_id. It depends on the attr we use. 194 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id); 195 196 // Parse sample_id from binary format in the buffer pointed by p. 197 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p, 198 const char* end); 199 200 // Write the binary format of sample_id to the buffer pointed by p. 201 void WriteToBinaryFormat(char*& p) const; 202 void Dump(size_t indent) const; 203 size_t Size() const; 204 }; 205 206 // Usually one record contains the following three parts in order in binary 207 // format: 208 // RecordHeader (at the head of a record, containing type and size info) 209 // data depends on the record type 210 // SampleId (optional part at the end of a record) 211 // We hold the common parts (RecordHeader and SampleId) in the base class 212 // Record, and hold the type specific data part in classes derived from Record. 213 struct Record { 214 RecordHeader header; 215 SampleId sample_id; 216 RecordRecord217 Record() : binary_(nullptr), own_binary_(false) {} RecordRecord218 explicit Record(char* p) : header(p), binary_(p), own_binary_(false) {} 219 Record(Record&& other) noexcept; 220 ~RecordRecord221 virtual ~Record() { 222 if (own_binary_) { 223 delete[] binary_; 224 } 225 } 226 OwnBinaryRecord227 void OwnBinary() { own_binary_ = true; } 228 typeRecord229 uint32_t type() const { return header.type; } 230 miscRecord231 uint16_t misc() const { return header.misc; } 232 sizeRecord233 uint32_t size() const { return header.size; } 234 header_sizeRecord235 static uint32_t header_size() { return sizeof(perf_event_header); } 236 InKernelRecord237 bool InKernel() const { 238 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == 239 PERF_RECORD_MISC_KERNEL; 240 } 241 SetTypeAndMiscRecord242 void SetTypeAndMisc(uint32_t type, uint16_t misc) { 243 header.type = type; 244 header.misc = misc; 245 } 246 SetSizeRecord247 void SetSize(uint32_t size) { header.size = size; } 248 249 void Dump(size_t indent = 0) const; 250 BinaryRecord251 const char* Binary() const { return binary_; } BinaryForTestingOnlyRecord252 char* BinaryForTestingOnly() { return binary_; } 253 254 virtual uint64_t Timestamp() const; 255 virtual uint32_t Cpu() const; 256 virtual uint64_t Id() const; 257 258 protected: 259 void UpdateBinary(char* new_binary); 260 virtual void DumpData(size_t) const = 0; 261 262 char* binary_; 263 bool own_binary_; 264 265 DISALLOW_COPY_AND_ASSIGN(Record); 266 }; 267 268 struct MmapRecord : public Record { 269 struct MmapRecordDataType { 270 uint32_t pid, tid; 271 uint64_t addr; 272 uint64_t len; 273 uint64_t pgoff; 274 }; 275 const MmapRecordDataType* data; 276 const char* filename; 277 278 MmapRecord(const perf_event_attr& attr, char* p); 279 280 MmapRecord(const perf_event_attr& attr, bool in_kernel, uint32_t pid, 281 uint32_t tid, uint64_t addr, uint64_t len, uint64_t pgoff, 282 const std::string& filename, uint64_t event_id, uint64_t time = 0); 283 284 void SetDataAndFilename(const MmapRecordDataType& data, 285 const std::string& filename); 286 287 protected: 288 void DumpData(size_t indent) const override; 289 }; 290 291 struct Mmap2Record : public Record { 292 struct Mmap2RecordDataType { 293 uint32_t pid, tid; 294 uint64_t addr; 295 uint64_t len; 296 uint64_t pgoff; 297 uint32_t maj; 298 uint32_t min; 299 uint64_t ino; 300 uint64_t ino_generation; 301 uint32_t prot, flags; 302 }; 303 const Mmap2RecordDataType* data; 304 const char* filename; 305 306 Mmap2Record(const perf_event_attr& attr, char* p); 307 Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid, 308 uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot, 309 const std::string& filename, uint64_t event_id, uint64_t time = 0); 310 311 void SetDataAndFilename(const Mmap2RecordDataType& data, 312 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, 328 const std::string& comm, 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) 354 : ExitOrForkRecord(attr, p) {} 355 }; 356 357 struct ForkRecord : public ExitOrForkRecord { ForkRecordForkRecord358 ForkRecord(const perf_event_attr& attr, char* p) 359 : ExitOrForkRecord(attr, p) {} 360 361 ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, 362 uint32_t ppid, uint32_t ptid, uint64_t event_id); 363 }; 364 365 struct LostRecord : public Record { 366 uint64_t id; 367 uint64_t lost; 368 369 LostRecord(const perf_event_attr& attr, char* p); 370 371 protected: 372 void DumpData(size_t indent) const override; 373 }; 374 375 struct SampleRecord : public Record { 376 uint64_t sample_type; // sample_type is a bit mask determining which fields 377 // below are valid. 378 379 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP. 380 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID. 381 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME. 382 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR. 383 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID. 384 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID. 385 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU. 386 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD. 387 388 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN. 389 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW. 390 PerfSampleBranchStackType 391 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK. 392 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER. 393 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER. 394 395 SampleRecord(const perf_event_attr& attr, char* p); 396 SampleRecord(const perf_event_attr& attr, uint64_t id, uint64_t ip, 397 uint32_t pid, uint32_t tid, uint64_t time, uint32_t cpu, 398 uint64_t period, const std::vector<uint64_t>& ips, 399 const std::vector<char>& stack, uint64_t dyn_stack_size); 400 401 void ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips); 402 // Remove kernel callchain, return true if there is a user space callchain left, otherwise 403 // return false. 404 bool ExcludeKernelCallChain(); 405 bool HasUserCallChain() const; 406 void UpdateUserCallChain(const std::vector<uint64_t>& user_ips); 407 408 uint64_t Timestamp() const override; 409 uint32_t Cpu() const override; 410 uint64_t Id() const override; 411 GetValidStackSizeSampleRecord412 uint64_t GetValidStackSize() const { 413 // Invaid stack data has been removed by RecordReadThread::PushRecordToRecordBuffer(). 414 return stack_user_data.size; 415 } 416 417 void AdjustCallChainGeneratedByKernel(); 418 std::vector<uint64_t> GetCallChain(size_t* kernel_ip_count) const; 419 420 protected: 421 void BuildBinaryWithNewCallChain(uint32_t new_size, const std::vector<uint64_t>& ips); 422 void DumpData(size_t indent) const override; 423 }; 424 425 // BuildIdRecord is defined in user-space, stored in BuildId feature section in 426 // record file. 427 struct BuildIdRecord : public Record { 428 uint32_t pid; 429 BuildId build_id; 430 const char* filename; 431 432 explicit BuildIdRecord(char* p); 433 434 BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id, 435 const std::string& filename); 436 437 protected: 438 void DumpData(size_t indent) const override; 439 }; 440 441 struct KernelSymbolRecord : public Record { 442 uint32_t kallsyms_size; 443 const char* kallsyms; 444 445 explicit KernelSymbolRecord(char* p); 446 447 explicit KernelSymbolRecord(const std::string& kallsyms); 448 449 protected: 450 void DumpData(size_t indent) const override; 451 }; 452 453 struct DsoRecord : public Record { 454 uint64_t dso_type; 455 uint64_t dso_id; 456 uint64_t min_vaddr; 457 const char* dso_name; 458 459 explicit DsoRecord(char* p); 460 461 DsoRecord(uint64_t dso_type, uint64_t dso_id, const std::string& dso_name, 462 uint64_t min_vaddr); 463 464 protected: 465 void DumpData(size_t indent) const override; 466 }; 467 468 struct SymbolRecord : public Record { 469 uint64_t addr; 470 uint64_t len; 471 uint64_t dso_id; 472 const char* name; 473 474 explicit SymbolRecord(char* p); 475 476 SymbolRecord(uint64_t addr, uint64_t len, const std::string& name, 477 uint64_t dso_id); 478 479 protected: 480 void DumpData(size_t indent) const override; 481 }; 482 483 struct TracingDataRecord : public Record { 484 uint32_t data_size; 485 const char* data; 486 487 explicit TracingDataRecord(char* p); 488 489 explicit TracingDataRecord(const std::vector<char>& tracing_data); 490 491 protected: 492 void DumpData(size_t indent) const override; 493 }; 494 495 struct EventIdRecord : public Record { 496 uint64_t count; 497 struct EventIdData { 498 uint64_t attr_id; 499 uint64_t event_id; 500 } const* data; 501 502 explicit EventIdRecord(char* p); 503 504 explicit EventIdRecord(const std::vector<uint64_t>& data); 505 506 protected: 507 void DumpData(size_t indent) const override; 508 }; 509 510 struct CallChainRecord : public Record { 511 uint32_t pid; 512 uint32_t tid; 513 uint64_t chain_type; 514 uint64_t time; 515 uint64_t ip_nr; 516 uint64_t* ips; 517 uint64_t* sps; 518 519 explicit CallChainRecord(char* p); 520 521 CallChainRecord(pid_t pid, pid_t tid, simpleperf::CallChainJoiner::ChainType type, uint64_t time, 522 const std::vector<uint64_t>& ips, const std::vector<uint64_t>& sps); 523 TimestampCallChainRecord524 uint64_t Timestamp() const override { 525 return time; 526 } 527 528 protected: 529 void DumpData(size_t indent) const override; 530 }; 531 532 struct UnwindingResultRecord : public Record { 533 uint64_t time; 534 simpleperf::UnwindingResult unwinding_result; 535 536 explicit UnwindingResultRecord(char* p); 537 538 UnwindingResultRecord(uint64_t time, const simpleperf::UnwindingResult& unwinding_result); 539 TimestampUnwindingResultRecord540 uint64_t Timestamp() const override { 541 return time; 542 } 543 544 protected: 545 void DumpData(size_t indent) const override; 546 }; 547 548 // UnknownRecord is used for unknown record types, it makes sure all unknown 549 // records are not changed when modifying perf.data. 550 struct UnknownRecord : public Record { 551 const char* data; 552 553 explicit UnknownRecord(char* p); 554 555 protected: 556 void DumpData(size_t indent) const override; 557 }; 558 559 // Read record from the buffer pointed by [p]. But the record doesn't own 560 // the buffer. 561 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p); 562 563 // Read record from the buffer pointed by [p]. And the record owns the buffer. 564 std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr, 565 uint32_t type, char* p); 566 567 // Read records from the buffer pointed by [buf]. None of the records own 568 // the buffer. 569 std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer( 570 const perf_event_attr& attr, char* buf, size_t buf_size); 571 572 // Read one record from the buffer pointed by [p]. But the record doesn't 573 // own the buffer. 574 std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p); 575 576 #endif // SIMPLE_PERF_RECORD_H_ 577