xref: /freebsd-src/contrib/llvm-project/llvm/lib/XRay/RecordInitializer.cpp (revision 5b27928474e6a4103d65b347544705c40c9618fd)
10b57cec5SDimitry Andric //===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "llvm/XRay/FDRRecords.h"
90b57cec5SDimitry Andric 
100b57cec5SDimitry Andric namespace llvm {
110b57cec5SDimitry Andric namespace xray {
120b57cec5SDimitry Andric 
visit(BufferExtents & R)130b57cec5SDimitry Andric Error RecordInitializer::visit(BufferExtents &R) {
140b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
15*8bcb0991SDimitry Andric     return createStringError(
16*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
17*8bcb0991SDimitry Andric         "Invalid offset for a buffer extent (%" PRId64 ").", OffsetPtr);
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
200b57cec5SDimitry Andric   R.Size = E.getU64(&OffsetPtr);
210b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
220b57cec5SDimitry Andric     return createStringError(std::make_error_code(std::errc::invalid_argument),
23*8bcb0991SDimitry Andric                              "Cannot read buffer extent at offset %" PRId64 ".",
240b57cec5SDimitry Andric                              OffsetPtr);
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
270b57cec5SDimitry Andric   return Error::success();
280b57cec5SDimitry Andric }
290b57cec5SDimitry Andric 
visit(WallclockRecord & R)300b57cec5SDimitry Andric Error RecordInitializer::visit(WallclockRecord &R) {
310b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
320b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
33*8bcb0991SDimitry Andric     return createStringError(
34*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
35*8bcb0991SDimitry Andric         "Invalid offset for a wallclock record (%" PRId64 ").", OffsetPtr);
360b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
370b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
380b57cec5SDimitry Andric   R.Seconds = E.getU64(&OffsetPtr);
390b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
400b57cec5SDimitry Andric     return createStringError(
410b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
42*8bcb0991SDimitry Andric         "Cannot read wall clock 'seconds' field at offset %" PRId64 ".",
43*8bcb0991SDimitry Andric         OffsetPtr);
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
460b57cec5SDimitry Andric   R.Nanos = E.getU32(&OffsetPtr);
470b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
480b57cec5SDimitry Andric     return createStringError(
490b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
50*8bcb0991SDimitry Andric         "Cannot read wall clock 'nanos' field at offset %" PRId64 ".",
51*8bcb0991SDimitry Andric         OffsetPtr);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // Align to metadata record size boundary.
540b57cec5SDimitry Andric   assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
550b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
560b57cec5SDimitry Andric   return Error::success();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
visit(NewCPUIDRecord & R)590b57cec5SDimitry Andric Error RecordInitializer::visit(NewCPUIDRecord &R) {
600b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
610b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
62*8bcb0991SDimitry Andric     return createStringError(
63*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
64*8bcb0991SDimitry Andric         "Invalid offset for a new cpu id record (%" PRId64 ").", OffsetPtr);
650b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
660b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
670b57cec5SDimitry Andric   R.CPUId = E.getU16(&OffsetPtr);
680b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
690b57cec5SDimitry Andric     return createStringError(std::make_error_code(std::errc::invalid_argument),
70*8bcb0991SDimitry Andric                              "Cannot read CPU id at offset %" PRId64 ".",
71*8bcb0991SDimitry Andric                              OffsetPtr);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
740b57cec5SDimitry Andric   R.TSC = E.getU64(&OffsetPtr);
750b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
760b57cec5SDimitry Andric     return createStringError(std::make_error_code(std::errc::invalid_argument),
77*8bcb0991SDimitry Andric                              "Cannot read CPU TSC at offset %" PRId64 ".",
78*8bcb0991SDimitry Andric                              OffsetPtr);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
810b57cec5SDimitry Andric   return Error::success();
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
visit(TSCWrapRecord & R)840b57cec5SDimitry Andric Error RecordInitializer::visit(TSCWrapRecord &R) {
850b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
860b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
87*8bcb0991SDimitry Andric     return createStringError(
88*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
89*8bcb0991SDimitry Andric         "Invalid offset for a new TSC wrap record (%" PRId64 ").", OffsetPtr);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
920b57cec5SDimitry Andric   R.BaseTSC = E.getU64(&OffsetPtr);
930b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
94*8bcb0991SDimitry Andric     return createStringError(
95*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
96*8bcb0991SDimitry Andric         "Cannot read TSC wrap record at offset %" PRId64 ".", OffsetPtr);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
990b57cec5SDimitry Andric   return Error::success();
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
visit(CustomEventRecord & R)1020b57cec5SDimitry Andric Error RecordInitializer::visit(CustomEventRecord &R) {
1030b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
1040b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
105*8bcb0991SDimitry Andric     return createStringError(
106*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
107*8bcb0991SDimitry Andric         "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
1100b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
1110b57cec5SDimitry Andric   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
1120b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
1130b57cec5SDimitry Andric     return createStringError(
1140b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
115*8bcb0991SDimitry Andric         "Cannot read a custom event record size field offset %" PRId64 ".",
116*8bcb0991SDimitry Andric         OffsetPtr);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   if (R.Size <= 0)
1190b57cec5SDimitry Andric     return createStringError(
1200b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
121*8bcb0991SDimitry Andric         "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
122*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
1250b57cec5SDimitry Andric   R.TSC = E.getU64(&OffsetPtr);
1260b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
1270b57cec5SDimitry Andric     return createStringError(
1280b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
129*8bcb0991SDimitry Andric         "Cannot read a custom event TSC field at offset %" PRId64 ".",
130*8bcb0991SDimitry Andric         OffsetPtr);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   // For version 4 onwards, of the FDR log, we want to also capture the CPU ID
1330b57cec5SDimitry Andric   // of the custom event.
1340b57cec5SDimitry Andric   if (Version >= 4) {
1350b57cec5SDimitry Andric     PreReadOffset = OffsetPtr;
1360b57cec5SDimitry Andric     R.CPU = E.getU16(&OffsetPtr);
1370b57cec5SDimitry Andric     if (PreReadOffset == OffsetPtr)
1380b57cec5SDimitry Andric       return createStringError(
1390b57cec5SDimitry Andric           std::make_error_code(std::errc::invalid_argument),
140*8bcb0991SDimitry Andric           "Missing CPU field at offset %" PRId64 ".", OffsetPtr);
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   assert(OffsetPtr > BeginOffset &&
1440b57cec5SDimitry Andric          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
1450b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   // Next we read in a fixed chunk of data from the given offset.
1480b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
1490b57cec5SDimitry Andric     return createStringError(
1500b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
151*8bcb0991SDimitry Andric         "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
152*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   std::vector<uint8_t> Buffer;
1550b57cec5SDimitry Andric   Buffer.resize(R.Size);
1560b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
1570b57cec5SDimitry Andric   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
1580b57cec5SDimitry Andric     return createStringError(
1590b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
160*8bcb0991SDimitry Andric         "Failed reading data into buffer of size %d at offset %" PRId64 ".",
161*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   assert(OffsetPtr >= PreReadOffset);
1640b57cec5SDimitry Andric   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
1650b57cec5SDimitry Andric     return createStringError(
1660b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
167*8bcb0991SDimitry Andric         "Failed reading enough bytes for the custom event payload -- read "
168*8bcb0991SDimitry Andric         "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
1690b57cec5SDimitry Andric         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   R.Data.assign(Buffer.begin(), Buffer.end());
1720b57cec5SDimitry Andric   return Error::success();
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
visit(CustomEventRecordV5 & R)1750b57cec5SDimitry Andric Error RecordInitializer::visit(CustomEventRecordV5 &R) {
1760b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
1770b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
178*8bcb0991SDimitry Andric     return createStringError(
179*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
180*8bcb0991SDimitry Andric         "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
1830b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
1860b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
1870b57cec5SDimitry Andric     return createStringError(
1880b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
189*8bcb0991SDimitry Andric         "Cannot read a custom event record size field offset %" PRId64 ".",
190*8bcb0991SDimitry Andric         OffsetPtr);
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   if (R.Size <= 0)
1930b57cec5SDimitry Andric     return createStringError(
1940b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
195*8bcb0991SDimitry Andric         "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
196*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
1990b57cec5SDimitry Andric   R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
2000b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
2010b57cec5SDimitry Andric     return createStringError(
2020b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
203*8bcb0991SDimitry Andric         "Cannot read a custom event record TSC delta field at offset "
204*8bcb0991SDimitry Andric         "%" PRId64 ".",
2050b57cec5SDimitry Andric         OffsetPtr);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   assert(OffsetPtr > BeginOffset &&
2080b57cec5SDimitry Andric          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
2090b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // Next we read in a fixed chunk of data from the given offset.
2120b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
2130b57cec5SDimitry Andric     return createStringError(
2140b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
215*8bcb0991SDimitry Andric         "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
216*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   std::vector<uint8_t> Buffer;
2190b57cec5SDimitry Andric   Buffer.resize(R.Size);
2200b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
2210b57cec5SDimitry Andric   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
2220b57cec5SDimitry Andric     return createStringError(
2230b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
224*8bcb0991SDimitry Andric         "Failed reading data into buffer of size %d at offset %" PRId64 ".",
225*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   assert(OffsetPtr >= PreReadOffset);
2280b57cec5SDimitry Andric   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
2290b57cec5SDimitry Andric     return createStringError(
2300b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
231*8bcb0991SDimitry Andric         "Failed reading enough bytes for the custom event payload -- read "
232*8bcb0991SDimitry Andric         "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
2330b57cec5SDimitry Andric         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   R.Data.assign(Buffer.begin(), Buffer.end());
2360b57cec5SDimitry Andric   return Error::success();
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
visit(TypedEventRecord & R)2390b57cec5SDimitry Andric Error RecordInitializer::visit(TypedEventRecord &R) {
2400b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
2410b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
242*8bcb0991SDimitry Andric     return createStringError(
243*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
244*8bcb0991SDimitry Andric         "Invalid offset for a typed event record (%" PRId64 ").", OffsetPtr);
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
2470b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
2500b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
2510b57cec5SDimitry Andric     return createStringError(
2520b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
253*8bcb0991SDimitry Andric         "Cannot read a typed event record size field offset %" PRId64 ".",
254*8bcb0991SDimitry Andric         OffsetPtr);
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (R.Size <= 0)
2570b57cec5SDimitry Andric     return createStringError(
2580b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
259*8bcb0991SDimitry Andric         "Invalid size for typed event (size = %d) at offset %" PRId64 ".",
260*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
2630b57cec5SDimitry Andric   R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
2640b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
2650b57cec5SDimitry Andric     return createStringError(
2660b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
267*8bcb0991SDimitry Andric         "Cannot read a typed event record TSC delta field at offset "
268*8bcb0991SDimitry Andric         "%" PRId64 ".",
2690b57cec5SDimitry Andric         OffsetPtr);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
2720b57cec5SDimitry Andric   R.EventType = E.getU16(&OffsetPtr);
2730b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
2740b57cec5SDimitry Andric     return createStringError(
2750b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
276*8bcb0991SDimitry Andric         "Cannot read a typed event record type field at offset %" PRId64 ".",
277*8bcb0991SDimitry Andric         OffsetPtr);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   assert(OffsetPtr > BeginOffset &&
2800b57cec5SDimitry Andric          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
2810b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   // Next we read in a fixed chunk of data from the given offset.
2840b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
2850b57cec5SDimitry Andric     return createStringError(
2860b57cec5SDimitry Andric         std::make_error_code(std::errc::bad_address),
287*8bcb0991SDimitry Andric         "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
288*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   std::vector<uint8_t> Buffer;
2910b57cec5SDimitry Andric   Buffer.resize(R.Size);
2920b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
2930b57cec5SDimitry Andric   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
2940b57cec5SDimitry Andric     return createStringError(
2950b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
296*8bcb0991SDimitry Andric         "Failed reading data into buffer of size %d at offset %" PRId64 ".",
297*8bcb0991SDimitry Andric         R.Size, OffsetPtr);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   assert(OffsetPtr >= PreReadOffset);
3000b57cec5SDimitry Andric   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
3010b57cec5SDimitry Andric     return createStringError(
3020b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
303*8bcb0991SDimitry Andric         "Failed reading enough bytes for the typed event payload -- read "
304*8bcb0991SDimitry Andric         "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
3050b57cec5SDimitry Andric         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   R.Data.assign(Buffer.begin(), Buffer.end());
3080b57cec5SDimitry Andric   return Error::success();
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
visit(CallArgRecord & R)3110b57cec5SDimitry Andric Error RecordInitializer::visit(CallArgRecord &R) {
3120b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
3130b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
314*8bcb0991SDimitry Andric     return createStringError(
315*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
316*8bcb0991SDimitry Andric         "Invalid offset for a call argument record (%" PRId64 ").",
3170b57cec5SDimitry Andric         OffsetPtr);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
3200b57cec5SDimitry Andric   R.Arg = E.getU64(&OffsetPtr);
3210b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
322*8bcb0991SDimitry Andric     return createStringError(
323*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
324*8bcb0991SDimitry Andric         "Cannot read a call arg record at offset %" PRId64 ".", OffsetPtr);
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
3270b57cec5SDimitry Andric   return Error::success();
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
visit(PIDRecord & R)3300b57cec5SDimitry Andric Error RecordInitializer::visit(PIDRecord &R) {
3310b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
3320b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
333*8bcb0991SDimitry Andric     return createStringError(
334*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
335*8bcb0991SDimitry Andric         "Invalid offset for a process ID record (%" PRId64 ").", OffsetPtr);
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
3380b57cec5SDimitry Andric   R.PID = E.getSigned(&OffsetPtr, 4);
3390b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
340*8bcb0991SDimitry Andric     return createStringError(
341*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
342*8bcb0991SDimitry Andric         "Cannot read a process ID record at offset %" PRId64 ".", OffsetPtr);
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
3450b57cec5SDimitry Andric   return Error::success();
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
visit(NewBufferRecord & R)3480b57cec5SDimitry Andric Error RecordInitializer::visit(NewBufferRecord &R) {
3490b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
3500b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
351*8bcb0991SDimitry Andric     return createStringError(
352*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
353*8bcb0991SDimitry Andric         "Invalid offset for a new buffer record (%" PRId64 ").", OffsetPtr);
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
3560b57cec5SDimitry Andric   R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
3570b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
358*8bcb0991SDimitry Andric     return createStringError(
359*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
360*8bcb0991SDimitry Andric         "Cannot read a new buffer record at offset %" PRId64 ".", OffsetPtr);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
3630b57cec5SDimitry Andric   return Error::success();
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
visit(EndBufferRecord & R)3660b57cec5SDimitry Andric Error RecordInitializer::visit(EndBufferRecord &R) {
3670b57cec5SDimitry Andric   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
3680b57cec5SDimitry Andric                                     MetadataRecord::kMetadataBodySize))
369*8bcb0991SDimitry Andric     return createStringError(
370*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
371*8bcb0991SDimitry Andric         "Invalid offset for an end-of-buffer record (%" PRId64 ").",
3720b57cec5SDimitry Andric         OffsetPtr);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   OffsetPtr += MetadataRecord::kMetadataBodySize;
3750b57cec5SDimitry Andric   return Error::success();
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
visit(FunctionRecord & R)3780b57cec5SDimitry Andric Error RecordInitializer::visit(FunctionRecord &R) {
3790b57cec5SDimitry Andric   // For function records, we need to retreat one byte back to read a full
3800b57cec5SDimitry Andric   // unsigned 32-bit value. The first four bytes will have the following
3810b57cec5SDimitry Andric   // layout:
3820b57cec5SDimitry Andric   //
3830b57cec5SDimitry Andric   //   bit  0     : function record indicator (must be 0)
3840b57cec5SDimitry Andric   //   bits 1..3  : function record type
3850b57cec5SDimitry Andric   //   bits 4..32 : function id
3860b57cec5SDimitry Andric   //
3870b57cec5SDimitry Andric   if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
3880b57cec5SDimitry Andric                             --OffsetPtr, FunctionRecord::kFunctionRecordSize))
389*8bcb0991SDimitry Andric     return createStringError(
390*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
391*8bcb0991SDimitry Andric         "Invalid offset for a function record (%" PRId64 ").", OffsetPtr);
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   auto BeginOffset = OffsetPtr;
3940b57cec5SDimitry Andric   auto PreReadOffset = BeginOffset;
3950b57cec5SDimitry Andric   uint32_t Buffer = E.getU32(&OffsetPtr);
3960b57cec5SDimitry Andric   if (PreReadOffset == OffsetPtr)
397*8bcb0991SDimitry Andric     return createStringError(
398*8bcb0991SDimitry Andric         std::make_error_code(std::errc::bad_address),
399*8bcb0991SDimitry Andric         "Cannot read function id field from offset %" PRId64 ".", OffsetPtr);
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   // To get the function record type, we shift the buffer one to the right
4020b57cec5SDimitry Andric   // (truncating the function record indicator) then take the three bits
4030b57cec5SDimitry Andric   // (0b0111) to get the record type as an unsigned value.
4040b57cec5SDimitry Andric   unsigned FunctionType = (Buffer >> 1) & 0x07u;
4050b57cec5SDimitry Andric   switch (FunctionType) {
4060b57cec5SDimitry Andric   case static_cast<unsigned>(RecordTypes::ENTER):
4070b57cec5SDimitry Andric   case static_cast<unsigned>(RecordTypes::ENTER_ARG):
4080b57cec5SDimitry Andric   case static_cast<unsigned>(RecordTypes::EXIT):
4090b57cec5SDimitry Andric   case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
4100b57cec5SDimitry Andric     R.Kind = static_cast<RecordTypes>(FunctionType);
4110b57cec5SDimitry Andric     break;
4120b57cec5SDimitry Andric   default:
413*8bcb0991SDimitry Andric     return createStringError(
414*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
415*8bcb0991SDimitry Andric         "Unknown function record type '%d' at offset %" PRId64 ".",
4160b57cec5SDimitry Andric         FunctionType, BeginOffset);
4170b57cec5SDimitry Andric   }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   R.FuncId = Buffer >> 4;
4200b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
4210b57cec5SDimitry Andric   R.Delta = E.getU32(&OffsetPtr);
4220b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
423*8bcb0991SDimitry Andric     return createStringError(
424*8bcb0991SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
425*8bcb0991SDimitry Andric         "Failed reading TSC delta from offset %" PRId64 ".", OffsetPtr);
4260b57cec5SDimitry Andric   assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset));
4270b57cec5SDimitry Andric   return Error::success();
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric } // namespace xray
4310b57cec5SDimitry Andric } // namespace llvm
432