Home | History | Annotate | Line # | Download | only in XRay
      1 //===- FDRRecords.h - XRay Flight Data Recorder Mode Records --------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // Define types and operations on these types that represent the different kinds
     10 // of records we encounter in XRay flight data recorder mode traces.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #ifndef LLVM_XRAY_FDRRECORDS_H
     14 #define LLVM_XRAY_FDRRECORDS_H
     15 
     16 #include <cstdint>
     17 #include <string>
     18 
     19 #include "llvm/ADT/StringRef.h"
     20 #include "llvm/Support/Casting.h"
     21 #include "llvm/Support/DataExtractor.h"
     22 #include "llvm/Support/Error.h"
     23 #include "llvm/XRay/XRayRecord.h"
     24 
     25 namespace llvm {
     26 namespace xray {
     27 
     28 class RecordVisitor;
     29 class RecordInitializer;
     30 
     31 class Record {
     32 public:
     33   enum class RecordKind {
     34     RK_Metadata,
     35     RK_Metadata_BufferExtents,
     36     RK_Metadata_WallClockTime,
     37     RK_Metadata_NewCPUId,
     38     RK_Metadata_TSCWrap,
     39     RK_Metadata_CustomEvent,
     40     RK_Metadata_CustomEventV5,
     41     RK_Metadata_CallArg,
     42     RK_Metadata_PIDEntry,
     43     RK_Metadata_NewBuffer,
     44     RK_Metadata_EndOfBuffer,
     45     RK_Metadata_TypedEvent,
     46     RK_Metadata_LastMetadata,
     47     RK_Function,
     48   };
     49 
     50   static StringRef kindToString(RecordKind K);
     51 
     52 private:
     53   const RecordKind T;
     54 
     55 public:
     56   Record(const Record &) = delete;
     57   Record(Record &&) = delete;
     58   Record &operator=(const Record &) = delete;
     59   Record &operator=(Record &&) = delete;
     60   explicit Record(RecordKind T) : T(T) {}
     61 
     62   RecordKind getRecordType() const { return T; }
     63 
     64   // Each Record should be able to apply an abstract visitor, and choose the
     65   // appropriate function in the visitor to invoke, given its own type.
     66   virtual Error apply(RecordVisitor &V) = 0;
     67 
     68   virtual ~Record() = default;
     69 };
     70 
     71 class MetadataRecord : public Record {
     72 public:
     73   enum class MetadataType : unsigned {
     74     Unknown,
     75     BufferExtents,
     76     WallClockTime,
     77     NewCPUId,
     78     TSCWrap,
     79     CustomEvent,
     80     CallArg,
     81     PIDEntry,
     82     NewBuffer,
     83     EndOfBuffer,
     84     TypedEvent,
     85   };
     86 
     87 protected:
     88   static constexpr int kMetadataBodySize = 15;
     89   friend class RecordInitializer;
     90 
     91 private:
     92   const MetadataType MT;
     93 
     94 public:
     95   explicit MetadataRecord(RecordKind T, MetadataType M) : Record(T), MT(M) {}
     96 
     97   static bool classof(const Record *R) {
     98     return R->getRecordType() >= RecordKind::RK_Metadata &&
     99            R->getRecordType() <= RecordKind::RK_Metadata_LastMetadata;
    100   }
    101 
    102   MetadataType metadataType() const { return MT; }
    103 
    104   virtual ~MetadataRecord() = default;
    105 };
    106 
    107 // What follows are specific Metadata record types which encapsulate the
    108 // information associated with specific metadata record types in an FDR mode
    109 // log.
    110 class BufferExtents : public MetadataRecord {
    111   uint64_t Size = 0;
    112   friend class RecordInitializer;
    113 
    114 public:
    115   BufferExtents()
    116       : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
    117                        MetadataType::BufferExtents) {}
    118 
    119   explicit BufferExtents(uint64_t S)
    120       : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
    121                        MetadataType::BufferExtents),
    122         Size(S) {}
    123 
    124   uint64_t size() const { return Size; }
    125 
    126   Error apply(RecordVisitor &V) override;
    127 
    128   static bool classof(const Record *R) {
    129     return R->getRecordType() == RecordKind::RK_Metadata_BufferExtents;
    130   }
    131 };
    132 
    133 class WallclockRecord : public MetadataRecord {
    134   uint64_t Seconds = 0;
    135   uint32_t Nanos = 0;
    136   friend class RecordInitializer;
    137 
    138 public:
    139   WallclockRecord()
    140       : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
    141                        MetadataType::WallClockTime) {}
    142 
    143   explicit WallclockRecord(uint64_t S, uint32_t N)
    144       : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
    145                        MetadataType::WallClockTime),
    146         Seconds(S), Nanos(N) {}
    147 
    148   uint64_t seconds() const { return Seconds; }
    149   uint32_t nanos() const { return Nanos; }
    150 
    151   Error apply(RecordVisitor &V) override;
    152 
    153   static bool classof(const Record *R) {
    154     return R->getRecordType() == RecordKind::RK_Metadata_WallClockTime;
    155   }
    156 };
    157 
    158 class NewCPUIDRecord : public MetadataRecord {
    159   uint16_t CPUId = 0;
    160   uint64_t TSC = 0;
    161   friend class RecordInitializer;
    162 
    163 public:
    164   NewCPUIDRecord()
    165       : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
    166                        MetadataType::NewCPUId) {}
    167 
    168   NewCPUIDRecord(uint16_t C, uint64_t T)
    169       : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
    170                        MetadataType::NewCPUId),
    171         CPUId(C), TSC(T) {}
    172 
    173   uint16_t cpuid() const { return CPUId; }
    174 
    175   uint64_t tsc() const { return TSC; }
    176 
    177   Error apply(RecordVisitor &V) override;
    178 
    179   static bool classof(const Record *R) {
    180     return R->getRecordType() == RecordKind::RK_Metadata_NewCPUId;
    181   }
    182 };
    183 
    184 class TSCWrapRecord : public MetadataRecord {
    185   uint64_t BaseTSC = 0;
    186   friend class RecordInitializer;
    187 
    188 public:
    189   TSCWrapRecord()
    190       : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap) {
    191   }
    192 
    193   explicit TSCWrapRecord(uint64_t B)
    194       : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap),
    195         BaseTSC(B) {}
    196 
    197   uint64_t tsc() const { return BaseTSC; }
    198 
    199   Error apply(RecordVisitor &V) override;
    200 
    201   static bool classof(const Record *R) {
    202     return R->getRecordType() == RecordKind::RK_Metadata_TSCWrap;
    203   }
    204 };
    205 
    206 class CustomEventRecord : public MetadataRecord {
    207   int32_t Size = 0;
    208   uint64_t TSC = 0;
    209   uint16_t CPU = 0;
    210   std::string Data{};
    211   friend class RecordInitializer;
    212 
    213 public:
    214   CustomEventRecord()
    215       : MetadataRecord(RecordKind::RK_Metadata_CustomEvent,
    216                        MetadataType::CustomEvent) {}
    217 
    218   explicit CustomEventRecord(uint64_t S, uint64_t T, uint16_t C, std::string D)
    219       : MetadataRecord(RecordKind::RK_Metadata_CustomEvent,
    220                        MetadataType::CustomEvent),
    221         Size(S), TSC(T), CPU(C), Data(std::move(D)) {}
    222 
    223   int32_t size() const { return Size; }
    224   uint64_t tsc() const { return TSC; }
    225   uint16_t cpu() const { return CPU; }
    226   StringRef data() const { return Data; }
    227 
    228   Error apply(RecordVisitor &V) override;
    229 
    230   static bool classof(const Record *R) {
    231     return R->getRecordType() == RecordKind::RK_Metadata_CustomEvent;
    232   }
    233 };
    234 
    235 class CustomEventRecordV5 : public MetadataRecord {
    236   int32_t Size = 0;
    237   int32_t Delta = 0;
    238   std::string Data{};
    239   friend class RecordInitializer;
    240 
    241 public:
    242   CustomEventRecordV5()
    243       : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5,
    244                        MetadataType::CustomEvent) {}
    245 
    246   explicit CustomEventRecordV5(int32_t S, int32_t D, std::string P)
    247       : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5,
    248                        MetadataType::CustomEvent),
    249         Size(S), Delta(D), Data(std::move(P)) {}
    250 
    251   int32_t size() const { return Size; }
    252   int32_t delta() const { return Delta; }
    253   StringRef data() const { return Data; }
    254 
    255   Error apply(RecordVisitor &V) override;
    256 
    257   static bool classof(const Record *R) {
    258     return R->getRecordType() == RecordKind::RK_Metadata_CustomEventV5;
    259   }
    260 };
    261 
    262 class TypedEventRecord : public MetadataRecord {
    263   int32_t Size = 0;
    264   int32_t Delta = 0;
    265   uint16_t EventType = 0;
    266   std::string Data{};
    267   friend class RecordInitializer;
    268 
    269 public:
    270   TypedEventRecord()
    271       : MetadataRecord(RecordKind::RK_Metadata_TypedEvent,
    272                        MetadataType::TypedEvent) {}
    273 
    274   explicit TypedEventRecord(int32_t S, int32_t D, uint16_t E, std::string P)
    275       : MetadataRecord(RecordKind::RK_Metadata_TypedEvent,
    276                        MetadataType::TypedEvent),
    277         Size(S), Delta(D), Data(std::move(P)) {}
    278 
    279   int32_t size() const { return Size; }
    280   int32_t delta() const { return Delta; }
    281   uint16_t eventType() const { return EventType; }
    282   StringRef data() const { return Data; }
    283 
    284   Error apply(RecordVisitor &V) override;
    285 
    286   static bool classof(const Record *R) {
    287     return R->getRecordType() == RecordKind::RK_Metadata_TypedEvent;
    288   }
    289 };
    290 
    291 class CallArgRecord : public MetadataRecord {
    292   uint64_t Arg = 0;
    293   friend class RecordInitializer;
    294 
    295 public:
    296   CallArgRecord()
    297       : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg) {
    298   }
    299 
    300   explicit CallArgRecord(uint64_t A)
    301       : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg),
    302         Arg(A) {}
    303 
    304   uint64_t arg() const { return Arg; }
    305 
    306   Error apply(RecordVisitor &V) override;
    307 
    308   static bool classof(const Record *R) {
    309     return R->getRecordType() == RecordKind::RK_Metadata_CallArg;
    310   }
    311 };
    312 
    313 class PIDRecord : public MetadataRecord {
    314   int32_t PID = 0;
    315   friend class RecordInitializer;
    316 
    317 public:
    318   PIDRecord()
    319       : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
    320                        MetadataType::PIDEntry) {}
    321 
    322   explicit PIDRecord(int32_t P)
    323       : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
    324                        MetadataType::PIDEntry),
    325         PID(P) {}
    326 
    327   int32_t pid() const { return PID; }
    328 
    329   Error apply(RecordVisitor &V) override;
    330 
    331   static bool classof(const Record *R) {
    332     return R->getRecordType() == RecordKind::RK_Metadata_PIDEntry;
    333   }
    334 };
    335 
    336 class NewBufferRecord : public MetadataRecord {
    337   int32_t TID = 0;
    338   friend class RecordInitializer;
    339 
    340 public:
    341   NewBufferRecord()
    342       : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
    343                        MetadataType::NewBuffer) {}
    344 
    345   explicit NewBufferRecord(int32_t T)
    346       : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
    347                        MetadataType::NewBuffer),
    348         TID(T) {}
    349 
    350   int32_t tid() const { return TID; }
    351 
    352   Error apply(RecordVisitor &V) override;
    353 
    354   static bool classof(const Record *R) {
    355     return R->getRecordType() == RecordKind::RK_Metadata_NewBuffer;
    356   }
    357 };
    358 
    359 class EndBufferRecord : public MetadataRecord {
    360 public:
    361   EndBufferRecord()
    362       : MetadataRecord(RecordKind::RK_Metadata_EndOfBuffer,
    363                        MetadataType::EndOfBuffer) {}
    364 
    365   Error apply(RecordVisitor &V) override;
    366 
    367   static bool classof(const Record *R) {
    368     return R->getRecordType() == RecordKind::RK_Metadata_EndOfBuffer;
    369   }
    370 };
    371 
    372 class FunctionRecord : public Record {
    373   RecordTypes Kind;
    374   int32_t FuncId = 0;
    375   uint32_t Delta = 0;
    376   friend class RecordInitializer;
    377 
    378   static constexpr unsigned kFunctionRecordSize = 8;
    379 
    380 public:
    381   FunctionRecord() : Record(RecordKind::RK_Function) {}
    382 
    383   explicit FunctionRecord(RecordTypes K, int32_t F, uint32_t D)
    384       : Record(RecordKind::RK_Function), Kind(K), FuncId(F), Delta(D) {}
    385 
    386   // A function record is a concrete record type which has a number of common
    387   // properties.
    388   RecordTypes recordType() const { return Kind; }
    389   int32_t functionId() const { return FuncId; }
    390   uint32_t delta() const { return Delta; }
    391 
    392   Error apply(RecordVisitor &V) override;
    393 
    394   static bool classof(const Record *R) {
    395     return R->getRecordType() == RecordKind::RK_Function;
    396   }
    397 };
    398 
    399 class RecordVisitor {
    400 public:
    401   virtual ~RecordVisitor() = default;
    402 
    403   // Support all specific kinds of records:
    404   virtual Error visit(BufferExtents &) = 0;
    405   virtual Error visit(WallclockRecord &) = 0;
    406   virtual Error visit(NewCPUIDRecord &) = 0;
    407   virtual Error visit(TSCWrapRecord &) = 0;
    408   virtual Error visit(CustomEventRecord &) = 0;
    409   virtual Error visit(CallArgRecord &) = 0;
    410   virtual Error visit(PIDRecord &) = 0;
    411   virtual Error visit(NewBufferRecord &) = 0;
    412   virtual Error visit(EndBufferRecord &) = 0;
    413   virtual Error visit(FunctionRecord &) = 0;
    414   virtual Error visit(CustomEventRecordV5 &) = 0;
    415   virtual Error visit(TypedEventRecord &) = 0;
    416 };
    417 
    418 class RecordInitializer : public RecordVisitor {
    419   DataExtractor &E;
    420   uint64_t &OffsetPtr;
    421   uint16_t Version;
    422 
    423 public:
    424   static constexpr uint16_t DefaultVersion = 5u;
    425 
    426   explicit RecordInitializer(DataExtractor &DE, uint64_t &OP, uint16_t V)
    427       : RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {}
    428 
    429   explicit RecordInitializer(DataExtractor &DE, uint64_t &OP)
    430       : RecordInitializer(DE, OP, DefaultVersion) {}
    431 
    432   Error visit(BufferExtents &) override;
    433   Error visit(WallclockRecord &) override;
    434   Error visit(NewCPUIDRecord &) override;
    435   Error visit(TSCWrapRecord &) override;
    436   Error visit(CustomEventRecord &) override;
    437   Error visit(CallArgRecord &) override;
    438   Error visit(PIDRecord &) override;
    439   Error visit(NewBufferRecord &) override;
    440   Error visit(EndBufferRecord &) override;
    441   Error visit(FunctionRecord &) override;
    442   Error visit(CustomEventRecordV5 &) override;
    443   Error visit(TypedEventRecord &) override;
    444 };
    445 
    446 } // namespace xray
    447 } // namespace llvm
    448 
    449 #endif // LLVM_XRAY_FDRRECORDS_H
    450