blob: ef2f6a47feea85ccfd76fe4e96effcdef35c205d [file] [log] [blame]
Dean Michael Berris146d57912018-08-31 08:04:56 +00001//===- 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
12namespace llvm {
13namespace xray {
14
15namespace {
16
17// Keep this in sync with the values written in the XRay FDR mode runtime in
18// compiler-rt.
19enum class MetadataRecordKinds : uint8_t {
20 NewBuffer,
21 EndOfBuffer,
22 NewCPUId,
23 TSCWrap,
24 WalltimeMarker,
25 CustomEventMarker,
26 CallArgument,
27 BufferExtents,
28 TypedEventMarker,
29 Pid,
30 // This is an end marker, used to identify the upper bound for this enum.
31 EnumEndMarker,
32};
33
34Expected<std::unique_ptr<Record>>
35metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
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 static constexpr MetadataRecordKinds Mapping[] = {
40 MetadataRecordKinds::NewBuffer,
41 MetadataRecordKinds::EndOfBuffer,
42 MetadataRecordKinds::NewCPUId,
43 MetadataRecordKinds::TSCWrap,
44 MetadataRecordKinds::WalltimeMarker,
45 MetadataRecordKinds::CustomEventMarker,
46 MetadataRecordKinds::CallArgument,
47 MetadataRecordKinds::BufferExtents,
48 MetadataRecordKinds::TypedEventMarker,
49 MetadataRecordKinds::Pid,
50 };
51 switch (Mapping[T]) {
52 case MetadataRecordKinds::NewBuffer:
53 return make_unique<NewBufferRecord>();
54 case MetadataRecordKinds::EndOfBuffer:
55 if (Header.Version >= 2)
56 return createStringError(
57 std::make_error_code(std::errc::executable_format_error),
58 "End of buffer records are no longer supported starting version "
59 "2 of the log.");
60 return make_unique<EndBufferRecord>();
61 case MetadataRecordKinds::NewCPUId:
62 return make_unique<NewCPUIDRecord>();
63 case MetadataRecordKinds::TSCWrap:
64 return make_unique<TSCWrapRecord>();
65 case MetadataRecordKinds::WalltimeMarker:
66 return make_unique<WallclockRecord>();
67 case MetadataRecordKinds::CustomEventMarker:
68 return make_unique<CustomEventRecord>();
69 case MetadataRecordKinds::CallArgument:
70 return make_unique<CallArgRecord>();
71 case MetadataRecordKinds::BufferExtents:
72 return make_unique<BufferExtents>();
73 case MetadataRecordKinds::TypedEventMarker:
74 return createStringError(std::make_error_code(std::errc::invalid_argument),
75 "Encountered an unsupported TypedEventMarker.");
76 case MetadataRecordKinds::Pid:
77 return make_unique<PIDRecord>();
78 case MetadataRecordKinds::EnumEndMarker:
79 llvm_unreachable("Invalid MetadataRecordKind");
80 }
Simon Pilgrim95f41202018-08-31 09:24:09 +000081 llvm_unreachable("Unhandled MetadataRecordKinds enum value");
Dean Michael Berris146d57912018-08-31 08:04:56 +000082}
83
84} // namespace
85
86Expected<std::unique_ptr<Record>> FileBasedRecordProducer::produce() {
87 // At the top level, we read one byte to determine the type of the record to
88 // create. This byte will comprise of the following bits:
89 //
90 // - offset 0: A '1' indicates a metadata record, a '0' indicates a function
91 // record.
92 // - offsets 1-7: For metadata records, this will indicate the kind of
93 // metadata record should be loaded.
94 //
95 // We read first byte, then create the appropriate type of record to consume
96 // the rest of the bytes.
97 auto PreReadOffset = OffsetPtr;
98 uint8_t FirstByte = E.getU8(&OffsetPtr);
99 std::unique_ptr<Record> R;
100
101 // For metadata records, handle especially here.
102 if (FirstByte & 0x01) {
103 auto LoadedType = FirstByte >> 1;
104 auto MetadataRecordOrErr = metadataRecordType(Header, LoadedType);
105 if (!MetadataRecordOrErr)
106 return joinErrors(
107 MetadataRecordOrErr.takeError(),
108 createStringError(
109 std::make_error_code(std::errc::executable_format_error),
110 "Encountered an unsupported metadata record (%d) at offset %d.",
111 LoadedType, PreReadOffset));
112 R = std::move(MetadataRecordOrErr.get());
113 } else {
114 R = llvm::make_unique<FunctionRecord>();
115 }
116 RecordInitializer RI(E, OffsetPtr);
117
118 if (auto Err = R->apply(RI))
119 return std::move(Err);
120
121 assert(R != nullptr);
122 return std::move(R);
123}
124
125} // namespace xray
126} // namespace llvm