LLVM  10.0.0svn
RecordInitializer.cpp
Go to the documentation of this file.
1 //===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "llvm/XRay/FDRRecords.h"
9 
10 namespace llvm {
11 namespace xray {
12 
14  if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
15  return createStringError(
16  std::make_error_code(std::errc::bad_address),
17  "Invalid offset for a buffer extent (%" PRId64 ").", OffsetPtr);
18 
19  auto PreReadOffset = OffsetPtr;
20  R.Size = E.getU64(&OffsetPtr);
21  if (PreReadOffset == OffsetPtr)
22  return createStringError(std::make_error_code(std::errc::invalid_argument),
23  "Cannot read buffer extent at offset %" PRId64 ".",
24  OffsetPtr);
25 
26  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
27  return Error::success();
28 }
29 
31  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
33  return createStringError(
34  std::make_error_code(std::errc::bad_address),
35  "Invalid offset for a wallclock record (%" PRId64 ").", OffsetPtr);
36  auto BeginOffset = OffsetPtr;
37  auto PreReadOffset = OffsetPtr;
38  R.Seconds = E.getU64(&OffsetPtr);
39  if (OffsetPtr == PreReadOffset)
40  return createStringError(
41  std::make_error_code(std::errc::invalid_argument),
42  "Cannot read wall clock 'seconds' field at offset %" PRId64 ".",
43  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::invalid_argument),
50  "Cannot read wall clock 'nanos' field at offset %" PRId64 ".",
51  OffsetPtr);
52 
53  // Align to metadata record size boundary.
54  assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
55  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
56  return Error::success();
57 }
58 
60  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
62  return createStringError(
63  std::make_error_code(std::errc::bad_address),
64  "Invalid offset for a new cpu id record (%" PRId64 ").", OffsetPtr);
65  auto BeginOffset = OffsetPtr;
66  auto PreReadOffset = OffsetPtr;
67  R.CPUId = E.getU16(&OffsetPtr);
68  if (OffsetPtr == PreReadOffset)
69  return createStringError(std::make_error_code(std::errc::invalid_argument),
70  "Cannot read CPU id at offset %" PRId64 ".",
71  OffsetPtr);
72 
73  PreReadOffset = OffsetPtr;
74  R.TSC = E.getU64(&OffsetPtr);
75  if (OffsetPtr == PreReadOffset)
76  return createStringError(std::make_error_code(std::errc::invalid_argument),
77  "Cannot read CPU TSC at offset %" PRId64 ".",
78  OffsetPtr);
79 
80  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
81  return Error::success();
82 }
83 
85  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
87  return createStringError(
88  std::make_error_code(std::errc::bad_address),
89  "Invalid offset for a new TSC wrap record (%" PRId64 ").", OffsetPtr);
90 
91  auto PreReadOffset = OffsetPtr;
92  R.BaseTSC = E.getU64(&OffsetPtr);
93  if (PreReadOffset == OffsetPtr)
94  return createStringError(
95  std::make_error_code(std::errc::invalid_argument),
96  "Cannot read TSC wrap record at offset %" PRId64 ".", OffsetPtr);
97 
98  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
99  return Error::success();
100 }
101 
103  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
105  return createStringError(
106  std::make_error_code(std::errc::bad_address),
107  "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
108 
109  auto BeginOffset = OffsetPtr;
110  auto PreReadOffset = OffsetPtr;
111  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
112  if (PreReadOffset == OffsetPtr)
113  return createStringError(
114  std::make_error_code(std::errc::invalid_argument),
115  "Cannot read a custom event record size field offset %" PRId64 ".",
116  OffsetPtr);
117 
118  if (R.Size <= 0)
119  return createStringError(
120  std::make_error_code(std::errc::bad_address),
121  "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
122  R.Size, OffsetPtr);
123 
124  PreReadOffset = OffsetPtr;
125  R.TSC = E.getU64(&OffsetPtr);
126  if (PreReadOffset == OffsetPtr)
127  return createStringError(
128  std::make_error_code(std::errc::invalid_argument),
129  "Cannot read a custom event TSC field at offset %" PRId64 ".",
130  OffsetPtr);
131 
132  // For version 4 onwards, of the FDR log, we want to also capture the CPU ID
133  // of the custom event.
134  if (Version >= 4) {
135  PreReadOffset = OffsetPtr;
136  R.CPU = E.getU16(&OffsetPtr);
137  if (PreReadOffset == OffsetPtr)
138  return createStringError(
139  std::make_error_code(std::errc::invalid_argument),
140  "Missing CPU field at offset %" PRId64 ".", OffsetPtr);
141  }
142 
143  assert(OffsetPtr > BeginOffset &&
144  OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
145  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
146 
147  // Next we read in a fixed chunk of data from the given offset.
148  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
149  return createStringError(
150  std::make_error_code(std::errc::bad_address),
151  "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
152  R.Size, OffsetPtr);
153 
154  std::vector<uint8_t> Buffer;
155  Buffer.resize(R.Size);
156  PreReadOffset = OffsetPtr;
157  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
158  return createStringError(
159  std::make_error_code(std::errc::invalid_argument),
160  "Failed reading data into buffer of size %d at offset %" PRId64 ".",
161  R.Size, OffsetPtr);
162 
163  assert(OffsetPtr >= PreReadOffset);
164  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
165  return createStringError(
166  std::make_error_code(std::errc::invalid_argument),
167  "Failed reading enough bytes for the custom event payload -- read "
168  "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
169  OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
170 
171  R.Data.assign(Buffer.begin(), Buffer.end());
172  return Error::success();
173 }
174 
176  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
178  return createStringError(
179  std::make_error_code(std::errc::bad_address),
180  "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr);
181 
182  auto BeginOffset = OffsetPtr;
183  auto PreReadOffset = OffsetPtr;
184 
185  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
186  if (PreReadOffset == OffsetPtr)
187  return createStringError(
188  std::make_error_code(std::errc::invalid_argument),
189  "Cannot read a custom event record size field offset %" PRId64 ".",
190  OffsetPtr);
191 
192  if (R.Size <= 0)
193  return createStringError(
194  std::make_error_code(std::errc::bad_address),
195  "Invalid size for custom event (size = %d) at offset %" PRId64 ".",
196  R.Size, OffsetPtr);
197 
198  PreReadOffset = OffsetPtr;
199  R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
200  if (PreReadOffset == OffsetPtr)
201  return createStringError(
202  std::make_error_code(std::errc::invalid_argument),
203  "Cannot read a custom event record TSC delta field at offset "
204  "%" PRId64 ".",
205  OffsetPtr);
206 
207  assert(OffsetPtr > BeginOffset &&
208  OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
209  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
210 
211  // Next we read in a fixed chunk of data from the given offset.
212  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
213  return createStringError(
214  std::make_error_code(std::errc::bad_address),
215  "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
216  R.Size, OffsetPtr);
217 
218  std::vector<uint8_t> Buffer;
219  Buffer.resize(R.Size);
220  PreReadOffset = OffsetPtr;
221  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
222  return createStringError(
223  std::make_error_code(std::errc::invalid_argument),
224  "Failed reading data into buffer of size %d at offset %" PRId64 ".",
225  R.Size, OffsetPtr);
226 
227  assert(OffsetPtr >= PreReadOffset);
228  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
229  return createStringError(
230  std::make_error_code(std::errc::invalid_argument),
231  "Failed reading enough bytes for the custom event payload -- read "
232  "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
233  OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
234 
235  R.Data.assign(Buffer.begin(), Buffer.end());
236  return Error::success();
237 }
238 
240  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
242  return createStringError(
243  std::make_error_code(std::errc::bad_address),
244  "Invalid offset for a typed event record (%" PRId64 ").", OffsetPtr);
245 
246  auto BeginOffset = OffsetPtr;
247  auto PreReadOffset = OffsetPtr;
248 
249  R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
250  if (PreReadOffset == OffsetPtr)
251  return createStringError(
252  std::make_error_code(std::errc::invalid_argument),
253  "Cannot read a typed event record size field offset %" PRId64 ".",
254  OffsetPtr);
255 
256  if (R.Size <= 0)
257  return createStringError(
258  std::make_error_code(std::errc::bad_address),
259  "Invalid size for typed event (size = %d) at offset %" PRId64 ".",
260  R.Size, OffsetPtr);
261 
262  PreReadOffset = OffsetPtr;
263  R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
264  if (PreReadOffset == OffsetPtr)
265  return createStringError(
266  std::make_error_code(std::errc::invalid_argument),
267  "Cannot read a typed event record TSC delta field at offset "
268  "%" PRId64 ".",
269  OffsetPtr);
270 
271  PreReadOffset = OffsetPtr;
272  R.EventType = E.getU16(&OffsetPtr);
273  if (PreReadOffset == OffsetPtr)
274  return createStringError(
275  std::make_error_code(std::errc::invalid_argument),
276  "Cannot read a typed event record type field at offset %" PRId64 ".",
277  OffsetPtr);
278 
279  assert(OffsetPtr > BeginOffset &&
280  OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
281  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
282 
283  // Next we read in a fixed chunk of data from the given offset.
284  if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
285  return createStringError(
286  std::make_error_code(std::errc::bad_address),
287  "Cannot read %d bytes of custom event data from offset %" PRId64 ".",
288  R.Size, OffsetPtr);
289 
290  std::vector<uint8_t> Buffer;
291  Buffer.resize(R.Size);
292  PreReadOffset = OffsetPtr;
293  if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
294  return createStringError(
295  std::make_error_code(std::errc::invalid_argument),
296  "Failed reading data into buffer of size %d at offset %" PRId64 ".",
297  R.Size, OffsetPtr);
298 
299  assert(OffsetPtr >= PreReadOffset);
300  if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
301  return createStringError(
302  std::make_error_code(std::errc::invalid_argument),
303  "Failed reading enough bytes for the typed event payload -- read "
304  "%" PRId64 " expecting %d bytes at offset %" PRId64 ".",
305  OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
306 
307  R.Data.assign(Buffer.begin(), Buffer.end());
308  return Error::success();
309 }
310 
312  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
314  return createStringError(
315  std::make_error_code(std::errc::bad_address),
316  "Invalid offset for a call argument record (%" PRId64 ").",
317  OffsetPtr);
318 
319  auto PreReadOffset = OffsetPtr;
320  R.Arg = E.getU64(&OffsetPtr);
321  if (PreReadOffset == OffsetPtr)
322  return createStringError(
323  std::make_error_code(std::errc::invalid_argument),
324  "Cannot read a call arg record at offset %" PRId64 ".", OffsetPtr);
325 
326  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
327  return Error::success();
328 }
329 
331  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
333  return createStringError(
334  std::make_error_code(std::errc::bad_address),
335  "Invalid offset for a process ID record (%" PRId64 ").", OffsetPtr);
336 
337  auto PreReadOffset = OffsetPtr;
338  R.PID = E.getSigned(&OffsetPtr, 4);
339  if (PreReadOffset == OffsetPtr)
340  return createStringError(
341  std::make_error_code(std::errc::invalid_argument),
342  "Cannot read a process ID record at offset %" PRId64 ".", OffsetPtr);
343 
344  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
345  return Error::success();
346 }
347 
349  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
351  return createStringError(
352  std::make_error_code(std::errc::bad_address),
353  "Invalid offset for a new buffer record (%" PRId64 ").", OffsetPtr);
354 
355  auto PreReadOffset = OffsetPtr;
356  R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
357  if (PreReadOffset == OffsetPtr)
358  return createStringError(
359  std::make_error_code(std::errc::invalid_argument),
360  "Cannot read a new buffer record at offset %" PRId64 ".", OffsetPtr);
361 
362  OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
363  return Error::success();
364 }
365 
367  if (!E.isValidOffsetForDataOfSize(OffsetPtr,
369  return createStringError(
370  std::make_error_code(std::errc::bad_address),
371  "Invalid offset for an end-of-buffer record (%" PRId64 ").",
372  OffsetPtr);
373 
375  return Error::success();
376 }
377 
379  // For function records, we need to retreat one byte back to read a full
380  // unsigned 32-bit value. The first four bytes will have the following
381  // layout:
382  //
383  // bit 0 : function record indicator (must be 0)
384  // bits 1..3 : function record type
385  // bits 4..32 : function id
386  //
387  if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
388  --OffsetPtr, FunctionRecord::kFunctionRecordSize))
389  return createStringError(
390  std::make_error_code(std::errc::bad_address),
391  "Invalid offset for a function record (%" PRId64 ").", OffsetPtr);
392 
393  auto BeginOffset = OffsetPtr;
394  auto PreReadOffset = BeginOffset;
395  uint32_t Buffer = E.getU32(&OffsetPtr);
396  if (PreReadOffset == OffsetPtr)
397  return createStringError(
398  std::make_error_code(std::errc::bad_address),
399  "Cannot read function id field from offset %" PRId64 ".", OffsetPtr);
400 
401  // To get the function record type, we shift the buffer one to the right
402  // (truncating the function record indicator) then take the three bits
403  // (0b0111) to get the record type as an unsigned value.
404  unsigned FunctionType = (Buffer >> 1) & 0x07u;
405  switch (FunctionType) {
406  case static_cast<unsigned>(RecordTypes::ENTER):
407  case static_cast<unsigned>(RecordTypes::ENTER_ARG):
408  case static_cast<unsigned>(RecordTypes::EXIT):
409  case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
410  R.Kind = static_cast<RecordTypes>(FunctionType);
411  break;
412  default:
413  return createStringError(
414  std::make_error_code(std::errc::invalid_argument),
415  "Unknown function record type '%d' at offset %" PRId64 ".",
416  FunctionType, BeginOffset);
417  }
418 
419  R.FuncId = Buffer >> 4;
420  PreReadOffset = OffsetPtr;
421  R.Delta = E.getU32(&OffsetPtr);
422  if (OffsetPtr == PreReadOffset)
423  return createStringError(
424  std::make_error_code(std::errc::invalid_argument),
425  "Failed reading TSC delta from offset %" PRId64 ".", OffsetPtr);
426  assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset));
427  return Error::success();
428 }
429 
430 } // namespace xray
431 } // namespace llvm
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static constexpr int kMetadataBodySize
Definition: FDRRecords.h:88
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
std::error_code make_error_code(BitcodeError E)
Class to represent function types.
Definition: DerivedTypes.h:103
RecordTypes
Determines the supported types of records that could be seen in XRay traces.
Definition: XRayRecord.h:57
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Error visit(BufferExtents &) override
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
uint64_t getU64(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint64_t value from *offset_ptr.
int64_t getSigned(uint64_t *offset_ptr, uint32_t size) const
Extract an signed integer of size byte_size from *offset_ptr.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1177