1343171Sdim//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===//
2343171Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343171Sdim//
7343171Sdim//===----------------------------------------------------------------------===//
8343171Sdim#include "llvm/XRay/FDRRecords.h"
9343171Sdim
10343171Sdimnamespace llvm {
11343171Sdimnamespace xray {
12343171Sdim
13343171SdimError RecordInitializer::visit(BufferExtents &R) {
14343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
15360784Sdim    return createStringError(
16360784Sdim        std::make_error_code(std::errc::bad_address),
17360784Sdim        "Invalid offset for a buffer extent (%" PRId64 ").", OffsetPtr);
18343171Sdim
19343171Sdim  auto PreReadOffset = OffsetPtr;
20343171Sdim  R.Size = E.getU64(&OffsetPtr);
21343171Sdim  if (PreReadOffset == OffsetPtr)
22343171Sdim    return createStringError(std::make_error_code(std::errc::invalid_argument),
23360784Sdim                             "Cannot read buffer extent at offset %" PRId64 ".",
24343171Sdim                             OffsetPtr);
25343171Sdim
26343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
27343171Sdim  return Error::success();
28343171Sdim}
29343171Sdim
30343171SdimError RecordInitializer::visit(WallclockRecord &R) {
31343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
32343171Sdim                                    MetadataRecord::kMetadataBodySize))
33360784Sdim    return createStringError(
34360784Sdim        std::make_error_code(std::errc::bad_address),
35360784Sdim        "Invalid offset for a wallclock record (%" PRId64 ").", OffsetPtr);
36343171Sdim  auto BeginOffset = OffsetPtr;
37343171Sdim  auto PreReadOffset = OffsetPtr;
38343171Sdim  R.Seconds = E.getU64(&OffsetPtr);
39343171Sdim  if (OffsetPtr == PreReadOffset)
40343171Sdim    return createStringError(
41343171Sdim        std::make_error_code(std::errc::invalid_argument),
42360784Sdim        "Cannot read wall clock 'seconds' field at offset %" PRId64 ".",
43360784Sdim        OffsetPtr);
44343171Sdim
45343171Sdim  PreReadOffset = OffsetPtr;
46343171Sdim  R.Nanos = E.getU32(&OffsetPtr);
47343171Sdim  if (OffsetPtr == PreReadOffset)
48343171Sdim    return createStringError(
49343171Sdim        std::make_error_code(std::errc::invalid_argument),
50360784Sdim        "Cannot read wall clock 'nanos' field at offset %" PRId64 ".",
51360784Sdim        OffsetPtr);
52343171Sdim
53343171Sdim  // Align to metadata record size boundary.
54343171Sdim  assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
55343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
56343171Sdim  return Error::success();
57343171Sdim}
58343171Sdim
59343171SdimError RecordInitializer::visit(NewCPUIDRecord &R) {
60343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
61343171Sdim                                    MetadataRecord::kMetadataBodySize))
62360784Sdim    return createStringError(
63360784Sdim        std::make_error_code(std::errc::bad_address),
64360784Sdim        "Invalid offset for a new cpu id record (%" PRId64 ").", OffsetPtr);
65343171Sdim  auto BeginOffset = OffsetPtr;
66343171Sdim  auto PreReadOffset = OffsetPtr;
67343171Sdim  R.CPUId = E.getU16(&OffsetPtr);
68343171Sdim  if (OffsetPtr == PreReadOffset)
69343171Sdim    return createStringError(std::make_error_code(std::errc::invalid_argument),
70360784Sdim                             "Cannot read CPU id at offset %" PRId64 ".",
71360784Sdim                             OffsetPtr);
72343171Sdim
73343171Sdim  PreReadOffset = OffsetPtr;
74343171Sdim  R.TSC = E.getU64(&OffsetPtr);
75343171Sdim  if (OffsetPtr == PreReadOffset)
76343171Sdim    return createStringError(std::make_error_code(std::errc::invalid_argument),
77360784Sdim                             "Cannot read CPU TSC at offset %" PRId64 ".",
78360784Sdim                             OffsetPtr);
79343171Sdim
80343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
81343171Sdim  return Error::success();
82343171Sdim}
83343171Sdim
84343171SdimError RecordInitializer::visit(TSCWrapRecord &R) {
85343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
86343171Sdim                                    MetadataRecord::kMetadataBodySize))
87360784Sdim    return createStringError(
88360784Sdim        std::make_error_code(std::errc::bad_address),
89360784Sdim        "Invalid offset for a new TSC wrap record (%" PRId64 ").", OffsetPtr);
90343171Sdim
91343171Sdim  auto PreReadOffset = OffsetPtr;
92343171Sdim  R.BaseTSC = E.getU64(&OffsetPtr);
93343171Sdim  if (PreReadOffset == OffsetPtr)
94360784Sdim    return createStringError(
95360784Sdim        std::make_error_code(std::errc::invalid_argument),
96360784Sdim        "Cannot read TSC wrap record at offset %" PRId64 ".", OffsetPtr);
97343171Sdim
98343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
99343171Sdim  return Error::success();
100343171Sdim}
101343171Sdim
102343171SdimError RecordInitializer::visit(CustomEventRecord &R) {
103343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
104343171Sdim                                    MetadataRecord::kMetadataBodySize))
105360784Sdim    return createStringError(
106360784Sdim        std::make_error_code(std::errc::bad_address),
107360784Sdim        "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
108343171Sdim
109343171Sdim  auto BeginOffset = OffsetPtr;
110343171Sdim  auto PreReadOffset = OffsetPtr;
111343171Sdim  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
112343171Sdim  if (PreReadOffset == OffsetPtr)
113343171Sdim    return createStringError(
114343171Sdim        std::make_error_code(std::errc::invalid_argument),
115360784Sdim        "Cannot read a custom event record size field offset %" PRId64 ".",
116360784Sdim        OffsetPtr);
117343171Sdim
118343171Sdim  if (R.Size <= 0)
119343171Sdim    return createStringError(
120343171Sdim        std::make_error_code(std::errc::bad_address),
121360784Sdim        "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
122360784Sdim        R.Size, OffsetPtr);
123343171Sdim
124343171Sdim  PreReadOffset = OffsetPtr;
125343171Sdim  R.TSC = E.getU64(&OffsetPtr);
126343171Sdim  if (PreReadOffset == OffsetPtr)
127343171Sdim    return createStringError(
128343171Sdim        std::make_error_code(std::errc::invalid_argument),
129360784Sdim        "Cannot read a custom event TSC field at offset %" PRId64 ".",
130360784Sdim        OffsetPtr);
131343171Sdim
132343171Sdim  // For version 4 onwards, of the FDR log, we want to also capture the CPU ID
133343171Sdim  // of the custom event.
134343171Sdim  if (Version >= 4) {
135343171Sdim    PreReadOffset = OffsetPtr;
136343171Sdim    R.CPU = E.getU16(&OffsetPtr);
137343171Sdim    if (PreReadOffset == OffsetPtr)
138343171Sdim      return createStringError(
139343171Sdim          std::make_error_code(std::errc::invalid_argument),
140360784Sdim          "Missing CPU field at offset %" PRId64 ".", OffsetPtr);
141343171Sdim  }
142343171Sdim
143343171Sdim  assert(OffsetPtr > BeginOffset &&
144343171Sdim         OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
145343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
146343171Sdim
147343171Sdim  // Next we read in a fixed chunk of data from the given offset.
148343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
149343171Sdim    return createStringError(
150343171Sdim        std::make_error_code(std::errc::bad_address),
151360784Sdim        "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
152360784Sdim        R.Size, OffsetPtr);
153343171Sdim
154343171Sdim  std::vector<uint8_t> Buffer;
155343171Sdim  Buffer.resize(R.Size);
156343171Sdim  PreReadOffset = OffsetPtr;
157343171Sdim  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
158343171Sdim    return createStringError(
159343171Sdim        std::make_error_code(std::errc::invalid_argument),
160360784Sdim        "Failed reading data into buffer of size %d at offset %" PRId64 ".",
161360784Sdim        R.Size, OffsetPtr);
162343171Sdim
163343171Sdim  assert(OffsetPtr >= PreReadOffset);
164343171Sdim  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
165343171Sdim    return createStringError(
166343171Sdim        std::make_error_code(std::errc::invalid_argument),
167360784Sdim        "Failed reading enough bytes for the custom event payload -- read "
168360784Sdim        "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
169343171Sdim        OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
170343171Sdim
171343171Sdim  R.Data.assign(Buffer.begin(), Buffer.end());
172343171Sdim  return Error::success();
173343171Sdim}
174343171Sdim
175343171SdimError RecordInitializer::visit(CustomEventRecordV5 &R) {
176343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
177343171Sdim                                    MetadataRecord::kMetadataBodySize))
178360784Sdim    return createStringError(
179360784Sdim        std::make_error_code(std::errc::bad_address),
180360784Sdim        "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
181343171Sdim
182343171Sdim  auto BeginOffset = OffsetPtr;
183343171Sdim  auto PreReadOffset = OffsetPtr;
184343171Sdim
185343171Sdim  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
186343171Sdim  if (PreReadOffset == OffsetPtr)
187343171Sdim    return createStringError(
188343171Sdim        std::make_error_code(std::errc::invalid_argument),
189360784Sdim        "Cannot read a custom event record size field offset %" PRId64 ".",
190360784Sdim        OffsetPtr);
191343171Sdim
192343171Sdim  if (R.Size <= 0)
193343171Sdim    return createStringError(
194343171Sdim        std::make_error_code(std::errc::bad_address),
195360784Sdim        "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
196360784Sdim        R.Size, OffsetPtr);
197343171Sdim
198343171Sdim  PreReadOffset = OffsetPtr;
199343171Sdim  R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
200343171Sdim  if (PreReadOffset == OffsetPtr)
201343171Sdim    return createStringError(
202343171Sdim        std::make_error_code(std::errc::invalid_argument),
203360784Sdim        "Cannot read a custom event record TSC delta field at offset "
204360784Sdim        "%" PRId64 ".",
205343171Sdim        OffsetPtr);
206343171Sdim
207343171Sdim  assert(OffsetPtr > BeginOffset &&
208343171Sdim         OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
209343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
210343171Sdim
211343171Sdim  // Next we read in a fixed chunk of data from the given offset.
212343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
213343171Sdim    return createStringError(
214343171Sdim        std::make_error_code(std::errc::bad_address),
215360784Sdim        "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
216360784Sdim        R.Size, OffsetPtr);
217343171Sdim
218343171Sdim  std::vector<uint8_t> Buffer;
219343171Sdim  Buffer.resize(R.Size);
220343171Sdim  PreReadOffset = OffsetPtr;
221343171Sdim  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
222343171Sdim    return createStringError(
223343171Sdim        std::make_error_code(std::errc::invalid_argument),
224360784Sdim        "Failed reading data into buffer of size %d at offset %" PRId64 ".",
225360784Sdim        R.Size, OffsetPtr);
226343171Sdim
227343171Sdim  assert(OffsetPtr >= PreReadOffset);
228343171Sdim  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
229343171Sdim    return createStringError(
230343171Sdim        std::make_error_code(std::errc::invalid_argument),
231360784Sdim        "Failed reading enough bytes for the custom event payload -- read "
232360784Sdim        "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
233343171Sdim        OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
234343171Sdim
235343171Sdim  R.Data.assign(Buffer.begin(), Buffer.end());
236343171Sdim  return Error::success();
237343171Sdim}
238343171Sdim
239343171SdimError RecordInitializer::visit(TypedEventRecord &R) {
240343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
241343171Sdim                                    MetadataRecord::kMetadataBodySize))
242360784Sdim    return createStringError(
243360784Sdim        std::make_error_code(std::errc::bad_address),
244360784Sdim        "Invalid offset for a typed event record (%" PRId64 ").", OffsetPtr);
245343171Sdim
246343171Sdim  auto BeginOffset = OffsetPtr;
247343171Sdim  auto PreReadOffset = OffsetPtr;
248343171Sdim
249343171Sdim  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
250343171Sdim  if (PreReadOffset == OffsetPtr)
251343171Sdim    return createStringError(
252343171Sdim        std::make_error_code(std::errc::invalid_argument),
253360784Sdim        "Cannot read a typed event record size field offset %" PRId64 ".",
254360784Sdim        OffsetPtr);
255343171Sdim
256343171Sdim  if (R.Size <= 0)
257343171Sdim    return createStringError(
258343171Sdim        std::make_error_code(std::errc::bad_address),
259360784Sdim        "Invalid size for typed event (size = %d) at offset %" PRId64 ".",
260360784Sdim        R.Size, OffsetPtr);
261343171Sdim
262343171Sdim  PreReadOffset = OffsetPtr;
263343171Sdim  R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
264343171Sdim  if (PreReadOffset == OffsetPtr)
265343171Sdim    return createStringError(
266343171Sdim        std::make_error_code(std::errc::invalid_argument),
267360784Sdim        "Cannot read a typed event record TSC delta field at offset "
268360784Sdim        "%" PRId64 ".",
269343171Sdim        OffsetPtr);
270343171Sdim
271343171Sdim  PreReadOffset = OffsetPtr;
272343171Sdim  R.EventType = E.getU16(&OffsetPtr);
273343171Sdim  if (PreReadOffset == OffsetPtr)
274343171Sdim    return createStringError(
275343171Sdim        std::make_error_code(std::errc::invalid_argument),
276360784Sdim        "Cannot read a typed event record type field at offset %" PRId64 ".",
277360784Sdim        OffsetPtr);
278343171Sdim
279343171Sdim  assert(OffsetPtr > BeginOffset &&
280343171Sdim         OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
281343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
282343171Sdim
283343171Sdim  // Next we read in a fixed chunk of data from the given offset.
284343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
285343171Sdim    return createStringError(
286343171Sdim        std::make_error_code(std::errc::bad_address),
287360784Sdim        "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
288360784Sdim        R.Size, OffsetPtr);
289343171Sdim
290343171Sdim  std::vector<uint8_t> Buffer;
291343171Sdim  Buffer.resize(R.Size);
292343171Sdim  PreReadOffset = OffsetPtr;
293343171Sdim  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
294343171Sdim    return createStringError(
295343171Sdim        std::make_error_code(std::errc::invalid_argument),
296360784Sdim        "Failed reading data into buffer of size %d at offset %" PRId64 ".",
297360784Sdim        R.Size, OffsetPtr);
298343171Sdim
299343171Sdim  assert(OffsetPtr >= PreReadOffset);
300343171Sdim  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
301343171Sdim    return createStringError(
302343171Sdim        std::make_error_code(std::errc::invalid_argument),
303360784Sdim        "Failed reading enough bytes for the typed event payload -- read "
304360784Sdim        "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
305343171Sdim        OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
306343171Sdim
307343171Sdim  R.Data.assign(Buffer.begin(), Buffer.end());
308343171Sdim  return Error::success();
309343171Sdim}
310343171Sdim
311343171SdimError RecordInitializer::visit(CallArgRecord &R) {
312343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
313343171Sdim                                    MetadataRecord::kMetadataBodySize))
314360784Sdim    return createStringError(
315360784Sdim        std::make_error_code(std::errc::bad_address),
316360784Sdim        "Invalid offset for a call argument record (%" PRId64 ").",
317360784Sdim        OffsetPtr);
318343171Sdim
319343171Sdim  auto PreReadOffset = OffsetPtr;
320343171Sdim  R.Arg = E.getU64(&OffsetPtr);
321343171Sdim  if (PreReadOffset == OffsetPtr)
322360784Sdim    return createStringError(
323360784Sdim        std::make_error_code(std::errc::invalid_argument),
324360784Sdim        "Cannot read a call arg record at offset %" PRId64 ".", OffsetPtr);
325343171Sdim
326343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
327343171Sdim  return Error::success();
328343171Sdim}
329343171Sdim
330343171SdimError RecordInitializer::visit(PIDRecord &R) {
331343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
332343171Sdim                                    MetadataRecord::kMetadataBodySize))
333360784Sdim    return createStringError(
334360784Sdim        std::make_error_code(std::errc::bad_address),
335360784Sdim        "Invalid offset for a process ID record (%" PRId64 ").", OffsetPtr);
336343171Sdim
337343171Sdim  auto PreReadOffset = OffsetPtr;
338343171Sdim  R.PID = E.getSigned(&OffsetPtr, 4);
339343171Sdim  if (PreReadOffset == OffsetPtr)
340360784Sdim    return createStringError(
341360784Sdim        std::make_error_code(std::errc::invalid_argument),
342360784Sdim        "Cannot read a process ID record at offset %" PRId64 ".", OffsetPtr);
343343171Sdim
344343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
345343171Sdim  return Error::success();
346343171Sdim}
347343171Sdim
348343171SdimError RecordInitializer::visit(NewBufferRecord &R) {
349343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
350343171Sdim                                    MetadataRecord::kMetadataBodySize))
351360784Sdim    return createStringError(
352360784Sdim        std::make_error_code(std::errc::bad_address),
353360784Sdim        "Invalid offset for a new buffer record (%" PRId64 ").", OffsetPtr);
354343171Sdim
355343171Sdim  auto PreReadOffset = OffsetPtr;
356343171Sdim  R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
357343171Sdim  if (PreReadOffset == OffsetPtr)
358360784Sdim    return createStringError(
359360784Sdim        std::make_error_code(std::errc::invalid_argument),
360360784Sdim        "Cannot read a new buffer record at offset %" PRId64 ".", OffsetPtr);
361343171Sdim
362343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
363343171Sdim  return Error::success();
364343171Sdim}
365343171Sdim
366343171SdimError RecordInitializer::visit(EndBufferRecord &R) {
367343171Sdim  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
368343171Sdim                                    MetadataRecord::kMetadataBodySize))
369360784Sdim    return createStringError(
370360784Sdim        std::make_error_code(std::errc::bad_address),
371360784Sdim        "Invalid offset for an end-of-buffer record (%" PRId64 ").",
372360784Sdim        OffsetPtr);
373343171Sdim
374343171Sdim  OffsetPtr += MetadataRecord::kMetadataBodySize;
375343171Sdim  return Error::success();
376343171Sdim}
377343171Sdim
378343171SdimError RecordInitializer::visit(FunctionRecord &R) {
379343171Sdim  // For function records, we need to retreat one byte back to read a full
380343171Sdim  // unsigned 32-bit value. The first four bytes will have the following
381343171Sdim  // layout:
382343171Sdim  //
383343171Sdim  //   bit  0     : function record indicator (must be 0)
384343171Sdim  //   bits 1..3  : function record type
385343171Sdim  //   bits 4..32 : function id
386343171Sdim  //
387343171Sdim  if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
388343171Sdim                            --OffsetPtr, FunctionRecord::kFunctionRecordSize))
389360784Sdim    return createStringError(
390360784Sdim        std::make_error_code(std::errc::bad_address),
391360784Sdim        "Invalid offset for a function record (%" PRId64 ").", OffsetPtr);
392343171Sdim
393343171Sdim  auto BeginOffset = OffsetPtr;
394343171Sdim  auto PreReadOffset = BeginOffset;
395343171Sdim  uint32_t Buffer = E.getU32(&OffsetPtr);
396343171Sdim  if (PreReadOffset == OffsetPtr)
397360784Sdim    return createStringError(
398360784Sdim        std::make_error_code(std::errc::bad_address),
399360784Sdim        "Cannot read function id field from offset %" PRId64 ".", OffsetPtr);
400343171Sdim
401343171Sdim  // To get the function record type, we shift the buffer one to the right
402343171Sdim  // (truncating the function record indicator) then take the three bits
403343171Sdim  // (0b0111) to get the record type as an unsigned value.
404343171Sdim  unsigned FunctionType = (Buffer >> 1) & 0x07u;
405343171Sdim  switch (FunctionType) {
406343171Sdim  case static_cast<unsigned>(RecordTypes::ENTER):
407343171Sdim  case static_cast<unsigned>(RecordTypes::ENTER_ARG):
408343171Sdim  case static_cast<unsigned>(RecordTypes::EXIT):
409343171Sdim  case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
410343171Sdim    R.Kind = static_cast<RecordTypes>(FunctionType);
411343171Sdim    break;
412343171Sdim  default:
413360784Sdim    return createStringError(
414360784Sdim        std::make_error_code(std::errc::invalid_argument),
415360784Sdim        "Unknown function record type '%d' at offset %" PRId64 ".",
416360784Sdim        FunctionType, BeginOffset);
417343171Sdim  }
418343171Sdim
419343171Sdim  R.FuncId = Buffer >> 4;
420343171Sdim  PreReadOffset = OffsetPtr;
421343171Sdim  R.Delta = E.getU32(&OffsetPtr);
422343171Sdim  if (OffsetPtr == PreReadOffset)
423360784Sdim    return createStringError(
424360784Sdim        std::make_error_code(std::errc::invalid_argument),
425360784Sdim        "Failed reading TSC delta from offset %" PRId64 ".", OffsetPtr);
426343171Sdim  assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset));
427343171Sdim  return Error::success();
428343171Sdim}
429343171Sdim
430343171Sdim} // namespace xray
431343171Sdim} // namespace llvm
432