blob: 11b0710234b06cc21bbfe48d09404e7c8bfb0291 [file] [log] [blame]
Dean Michael Berrisa6c63432018-08-30 07:22:21 +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/FDRRecords.h"
10
11namespace llvm {
12namespace xray {
13
14Error RecordInitializer::visit(BufferExtents &R) {
15 if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
16 return createStringError(std::make_error_code(std::errc::bad_address),
17 "Invalid offset for a buffer extent (%d).",
18 OffsetPtr);
19
20 auto PreReadOffset = OffsetPtr;
21 R.Size = E.getU64(&OffsetPtr);
22 if (PreReadOffset == OffsetPtr)
23 return createStringError(std::make_error_code(std::errc::bad_message),
24 "Cannot read buffer extent at offset %d.",
25 OffsetPtr);
26
27 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
28 return Error::success();
29}
30
31Error RecordInitializer::visit(WallclockRecord &R) {
32 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
33 MetadataRecord::kMetadataBodySize))
34 return createStringError(std::make_error_code(std::errc::bad_address),
35 "Invalid offset for a wallclock record (%d).",
36 OffsetPtr);
37 auto BeginOffset = OffsetPtr;
38 auto PreReadOffset = OffsetPtr;
39 R.Seconds = E.getU64(&OffsetPtr);
40 if (OffsetPtr == PreReadOffset)
41 return createStringError(
42 std::make_error_code(std::errc::bad_message),
43 "Cannot read wall clock 'seconds' field at offset %d.", OffsetPtr);
44
45 PreReadOffset = OffsetPtr;
46 R.Nanos = E.getU32(&OffsetPtr);
47 if (OffsetPtr == PreReadOffset)
48 return createStringError(
49 std::make_error_code(std::errc::bad_message),
50 "Cannot read wall clock 'nanos' field at offset %d.", OffsetPtr);
51
52 // Align to metadata record size boundary.
53 assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
54 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
55 return Error::success();
56}
57
58Error RecordInitializer::visit(NewCPUIDRecord &R) {
59 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
60 MetadataRecord::kMetadataBodySize))
61 return createStringError(std::make_error_code(std::errc::bad_address),
62 "Invalid offset for a new cpu id record (%d).",
63 OffsetPtr);
64 auto PreReadOffset = OffsetPtr;
65 R.CPUId = E.getU16(&OffsetPtr);
66 if (OffsetPtr == PreReadOffset)
67 return createStringError(std::make_error_code(std::errc::bad_message),
68 "Cannot read CPU id at offset %d.", OffsetPtr);
69
70 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
71 return Error::success();
72}
73
74Error RecordInitializer::visit(TSCWrapRecord &R) {
75 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
76 MetadataRecord::kMetadataBodySize))
77 return createStringError(std::make_error_code(std::errc::bad_address),
78 "Invalid offset for a new TSC wrap record (%d).",
79 OffsetPtr);
80
81 auto PreReadOffset = OffsetPtr;
82 R.BaseTSC = E.getU64(&OffsetPtr);
83 if (PreReadOffset == OffsetPtr)
84 return createStringError(std::make_error_code(std::errc::bad_message),
85 "Cannot read TSC wrap record at offset %d.",
86 OffsetPtr);
87
88 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
89 return Error::success();
90}
91
92Error RecordInitializer::visit(CustomEventRecord &R) {
93 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
94 MetadataRecord::kMetadataBodySize))
95 return createStringError(std::make_error_code(std::errc::bad_address),
96 "Invalid offset for a custom event record (%d).",
97 OffsetPtr);
98
99 auto BeginOffset = OffsetPtr;
100 auto PreReadOffset = OffsetPtr;
101 R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
102 if (PreReadOffset == OffsetPtr)
103 return createStringError(
104 std::make_error_code(std::errc::bad_message),
105 "Cannot read a custom event record size field offset %d.", OffsetPtr);
106
107 PreReadOffset = OffsetPtr;
108 R.TSC = E.getU64(&OffsetPtr);
109 if (PreReadOffset == OffsetPtr)
110 return createStringError(
111 std::make_error_code(std::errc::bad_message),
112 "Cannot read a custom event TSC field at offset %d.", OffsetPtr);
113
114 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
115
116 // Next we read in a fixed chunk of data from the given offset.
117 if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
118 return createStringError(
119 std::make_error_code(std::errc::bad_address),
120 "Cannot read %d bytes of custom event data from offset %d.", R.Size,
121 OffsetPtr);
122
123 std::vector<uint8_t> Buffer;
124 Buffer.resize(R.Size);
125 if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
126 return createStringError(
127 std::make_error_code(std::errc::bad_message),
128 "Failed reading data into buffer of size %d at offset %d.", R.Size,
129 OffsetPtr);
130 R.Data.assign(Buffer.begin(), Buffer.end());
131 return Error::success();
132}
133
134Error RecordInitializer::visit(CallArgRecord &R) {
135 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
136 MetadataRecord::kMetadataBodySize))
137 return createStringError(std::make_error_code(std::errc::bad_address),
138 "Invalid offset for a call argument record (%d).",
139 OffsetPtr);
140
141 auto PreReadOffset = OffsetPtr;
142 R.Arg = E.getU64(&OffsetPtr);
143 if (PreReadOffset == OffsetPtr)
144 return createStringError(std::make_error_code(std::errc::bad_message),
145 "Cannot read a call arg record at offset %d.",
146 OffsetPtr);
147
148 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
149 return Error::success();
150}
151
152Error RecordInitializer::visit(PIDRecord &R) {
153 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
154 MetadataRecord::kMetadataBodySize))
155 return createStringError(std::make_error_code(std::errc::bad_address),
156 "Invalid offset for a process ID record (%d).",
157 OffsetPtr);
158
159 auto PreReadOffset = OffsetPtr;
160 R.PID = E.getU64(&OffsetPtr);
161 if (PreReadOffset == OffsetPtr)
162 return createStringError(std::make_error_code(std::errc::bad_message),
163 "Cannot read a process ID record at offset %d.",
164 OffsetPtr);
165
166 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
167 return Error::success();
168}
169
170Error RecordInitializer::visit(NewBufferRecord &R) {
171 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
172 MetadataRecord::kMetadataBodySize))
173 return createStringError(std::make_error_code(std::errc::bad_address),
174 "Invalid offset for a new buffer record (%d).",
175 OffsetPtr);
176
177 auto PreReadOffset = OffsetPtr;
178 R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
179 if (PreReadOffset == OffsetPtr)
180 return createStringError(std::make_error_code(std::errc::bad_message),
181 "Cannot read a new buffer record at offset %d.",
182 OffsetPtr);
183
184 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
185 return Error::success();
186}
187
188Error RecordInitializer::visit(EndBufferRecord &R) {
189 if (!E.isValidOffsetForDataOfSize(OffsetPtr,
190 MetadataRecord::kMetadataBodySize))
191 return createStringError(std::make_error_code(std::errc::bad_address),
192 "Invalid offset for an end-of-buffer record (%d).",
193 OffsetPtr);
194
195 OffsetPtr += MetadataRecord::kMetadataBodySize;
196 return Error::success();
197}
198
199Error RecordInitializer::visit(FunctionRecord &R) {
200 // For function records, we need to retreat one byte back to read a full
201 // unsigned 32-bit value. The first four bytes will have the following
202 // layout:
203 //
204 // bit 0 : function record indicator (must be 0)
205 // bits 1..3 : function record type
206 // bits 4..32 : function id
207 //
208 if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
209 --OffsetPtr, FunctionRecord::kFunctionRecordSize))
210 return createStringError(std::make_error_code(std::errc::bad_address),
211 "Invalid offset for a function record (%d).",
212 OffsetPtr);
213
214 auto BeginOffset = OffsetPtr;
215 auto PreReadOffset = BeginOffset;
216 uint32_t Buffer = E.getU32(&OffsetPtr);
217 if (PreReadOffset == OffsetPtr)
218 return createStringError(std::make_error_code(std::errc::bad_address),
219 "Cannot read function id field from offset %d.",
220 OffsetPtr);
221 unsigned FunctionType = (Buffer >> 1) & 0x07;
222 switch (FunctionType) {
223 case static_cast<unsigned>(RecordTypes::ENTER):
224 case static_cast<unsigned>(RecordTypes::ENTER_ARG):
225 case static_cast<unsigned>(RecordTypes::EXIT):
226 case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
227 R.Kind = static_cast<RecordTypes>(FunctionType);
228 break;
229 default:
230 return createStringError(std::make_error_code(std::errc::bad_message),
231 "Unknown function record type '%d' at offset %d.",
232 FunctionType, BeginOffset);
233 }
234
235 R.FuncId = Buffer >> 4;
236 PreReadOffset = OffsetPtr;
237 R.Delta = E.getU32(&OffsetPtr);
238 if (OffsetPtr == PreReadOffset)
239 return createStringError(std::make_error_code(std::errc::bad_message),
240 "Failed reading TSC delta from offset %d.",
241 OffsetPtr);
242 assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset));
243 return Error::success();
244}
245
246} // namespace xray
247} // namespace llvm