1 //===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "llvm/XRay/FDRRecordProducer.h" 10 #include "llvm/Support/DataExtractor.h" 11 12 namespace llvm { 13 namespace xray { 14 15 namespace { 16 17 Expected<std::unique_ptr<Record>> 18 metadataRecordType(const XRayFileHeader &Header, uint8_t T) { 19 // Keep this in sync with the values written in the XRay FDR mode runtime in 20 // compiler-rt. 21 enum MetadataRecordKinds : uint8_t { 22 NewBufferKind, 23 EndOfBufferKind, 24 NewCPUIdKind, 25 TSCWrapKind, 26 WalltimeMarkerKind, 27 CustomEventMarkerKind, 28 CallArgumentKind, 29 BufferExtentsKind, 30 TypedEventMarkerKind, 31 PidKind, 32 // This is an end marker, used to identify the upper bound for this enum. 33 EnumEndMarker, 34 }; 35 36 if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker)) 37 return createStringError(std::make_error_code(std::errc::invalid_argument), 38 "Invalid metadata record type: %d", T); 39 switch (T) { 40 case MetadataRecordKinds::NewBufferKind: 41 return make_unique<NewBufferRecord>(); 42 case MetadataRecordKinds::EndOfBufferKind: 43 if (Header.Version >= 2) 44 return createStringError( 45 std::make_error_code(std::errc::executable_format_error), 46 "End of buffer records are no longer supported starting version " 47 "2 of the log."); 48 return make_unique<EndBufferRecord>(); 49 case MetadataRecordKinds::NewCPUIdKind: 50 return make_unique<NewCPUIDRecord>(); 51 case MetadataRecordKinds::TSCWrapKind: 52 return make_unique<TSCWrapRecord>(); 53 case MetadataRecordKinds::WalltimeMarkerKind: 54 return make_unique<WallclockRecord>(); 55 case MetadataRecordKinds::CustomEventMarkerKind: 56 return make_unique<CustomEventRecord>(); 57 case MetadataRecordKinds::CallArgumentKind: 58 return make_unique<CallArgRecord>(); 59 case MetadataRecordKinds::BufferExtentsKind: 60 return make_unique<BufferExtents>(); 61 case MetadataRecordKinds::TypedEventMarkerKind: 62 return createStringError(std::make_error_code(std::errc::invalid_argument), 63 "Encountered an unsupported TypedEventMarker."); 64 case MetadataRecordKinds::PidKind: 65 return make_unique<PIDRecord>(); 66 case MetadataRecordKinds::EnumEndMarker: 67 llvm_unreachable("Invalid MetadataRecordKind"); 68 } 69 llvm_unreachable("Unhandled MetadataRecordKinds enum value"); 70 } 71 72 } // namespace 73 74 Expected<std::unique_ptr<Record>> FileBasedRecordProducer::produce() { 75 // At the top level, we read one byte to determine the type of the record to 76 // create. This byte will comprise of the following bits: 77 // 78 // - offset 0: A '1' indicates a metadata record, a '0' indicates a function 79 // record. 80 // - offsets 1-7: For metadata records, this will indicate the kind of 81 // metadata record should be loaded. 82 // 83 // We read first byte, then create the appropriate type of record to consume 84 // the rest of the bytes. 85 auto PreReadOffset = OffsetPtr; 86 uint8_t FirstByte = E.getU8(&OffsetPtr); 87 std::unique_ptr<Record> R; 88 89 // For metadata records, handle especially here. 90 if (FirstByte & 0x01) { 91 auto LoadedType = FirstByte >> 1; 92 auto MetadataRecordOrErr = metadataRecordType(Header, LoadedType); 93 if (!MetadataRecordOrErr) 94 return joinErrors( 95 MetadataRecordOrErr.takeError(), 96 createStringError( 97 std::make_error_code(std::errc::executable_format_error), 98 "Encountered an unsupported metadata record (%d) at offset %d.", 99 LoadedType, PreReadOffset)); 100 R = std::move(MetadataRecordOrErr.get()); 101 } else { 102 R = llvm::make_unique<FunctionRecord>(); 103 } 104 RecordInitializer RI(E, OffsetPtr); 105 106 if (auto Err = R->apply(RI)) 107 return std::move(Err); 108 109 assert(R != nullptr); 110 return std::move(R); 111 } 112 113 } // namespace xray 114 } // namespace llvm 115