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