]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/XRay/RecordInitializer.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / XRay / RecordInitializer.cpp
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
13 Error RecordInitializer::visit(BufferExtents &R) {
14   if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t)))
15     return createStringError(std::make_error_code(std::errc::bad_address),
16                              "Invalid offset for a buffer extent (%d).",
17                              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 %d.",
24                              OffsetPtr);
25
26   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
27   return Error::success();
28 }
29
30 Error RecordInitializer::visit(WallclockRecord &R) {
31   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
32                                     MetadataRecord::kMetadataBodySize))
33     return createStringError(std::make_error_code(std::errc::bad_address),
34                              "Invalid offset for a wallclock record (%d).",
35                              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 %d.", OffsetPtr);
43
44   PreReadOffset = OffsetPtr;
45   R.Nanos = E.getU32(&OffsetPtr);
46   if (OffsetPtr == PreReadOffset)
47     return createStringError(
48         std::make_error_code(std::errc::invalid_argument),
49         "Cannot read wall clock 'nanos' field at offset %d.", OffsetPtr);
50
51   // Align to metadata record size boundary.
52   assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
53   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
54   return Error::success();
55 }
56
57 Error RecordInitializer::visit(NewCPUIDRecord &R) {
58   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
59                                     MetadataRecord::kMetadataBodySize))
60     return createStringError(std::make_error_code(std::errc::bad_address),
61                              "Invalid offset for a new cpu id record (%d).",
62                              OffsetPtr);
63   auto BeginOffset = OffsetPtr;
64   auto PreReadOffset = OffsetPtr;
65   R.CPUId = E.getU16(&OffsetPtr);
66   if (OffsetPtr == PreReadOffset)
67     return createStringError(std::make_error_code(std::errc::invalid_argument),
68                              "Cannot read CPU id at offset %d.", OffsetPtr);
69
70   PreReadOffset = OffsetPtr;
71   R.TSC = E.getU64(&OffsetPtr);
72   if (OffsetPtr == PreReadOffset)
73     return createStringError(std::make_error_code(std::errc::invalid_argument),
74                              "Cannot read CPU TSC at offset %d.", OffsetPtr);
75
76   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
77   return Error::success();
78 }
79
80 Error RecordInitializer::visit(TSCWrapRecord &R) {
81   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
82                                     MetadataRecord::kMetadataBodySize))
83     return createStringError(std::make_error_code(std::errc::bad_address),
84                              "Invalid offset for a new TSC wrap record (%d).",
85                              OffsetPtr);
86
87   auto PreReadOffset = OffsetPtr;
88   R.BaseTSC = E.getU64(&OffsetPtr);
89   if (PreReadOffset == OffsetPtr)
90     return createStringError(std::make_error_code(std::errc::invalid_argument),
91                              "Cannot read TSC wrap record at offset %d.",
92                              OffsetPtr);
93
94   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
95   return Error::success();
96 }
97
98 Error RecordInitializer::visit(CustomEventRecord &R) {
99   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
100                                     MetadataRecord::kMetadataBodySize))
101     return createStringError(std::make_error_code(std::errc::bad_address),
102                              "Invalid offset for a custom event record (%d).",
103                              OffsetPtr);
104
105   auto BeginOffset = OffsetPtr;
106   auto PreReadOffset = OffsetPtr;
107   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
108   if (PreReadOffset == OffsetPtr)
109     return createStringError(
110         std::make_error_code(std::errc::invalid_argument),
111         "Cannot read a custom event record size field offset %d.", OffsetPtr);
112
113   if (R.Size <= 0)
114     return createStringError(
115         std::make_error_code(std::errc::bad_address),
116         "Invalid size for custom event (size = %d) at offset %d.", R.Size,
117         OffsetPtr);
118
119   PreReadOffset = OffsetPtr;
120   R.TSC = E.getU64(&OffsetPtr);
121   if (PreReadOffset == OffsetPtr)
122     return createStringError(
123         std::make_error_code(std::errc::invalid_argument),
124         "Cannot read a custom event TSC field at offset %d.", OffsetPtr);
125
126   // For version 4 onwards, of the FDR log, we want to also capture the CPU ID
127   // of the custom event.
128   if (Version >= 4) {
129     PreReadOffset = OffsetPtr;
130     R.CPU = E.getU16(&OffsetPtr);
131     if (PreReadOffset == OffsetPtr)
132       return createStringError(
133           std::make_error_code(std::errc::invalid_argument),
134           "Missing CPU field at offset %d", OffsetPtr);
135   }
136
137   assert(OffsetPtr > BeginOffset &&
138          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
139   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
140
141   // Next we read in a fixed chunk of data from the given offset.
142   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
143     return createStringError(
144         std::make_error_code(std::errc::bad_address),
145         "Cannot read %d bytes of custom event data from offset %d.", R.Size,
146         OffsetPtr);
147
148   std::vector<uint8_t> Buffer;
149   Buffer.resize(R.Size);
150   PreReadOffset = OffsetPtr;
151   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
152     return createStringError(
153         std::make_error_code(std::errc::invalid_argument),
154         "Failed reading data into buffer of size %d at offset %d.", R.Size,
155         OffsetPtr);
156
157   assert(OffsetPtr >= PreReadOffset);
158   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
159     return createStringError(
160         std::make_error_code(std::errc::invalid_argument),
161         "Failed reading enough bytes for the custom event payload -- read %d "
162         "expecting %d bytes at offset %d.",
163         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
164
165   R.Data.assign(Buffer.begin(), Buffer.end());
166   return Error::success();
167 }
168
169 Error RecordInitializer::visit(CustomEventRecordV5 &R) {
170   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
171                                     MetadataRecord::kMetadataBodySize))
172     return createStringError(std::make_error_code(std::errc::bad_address),
173                              "Invalid offset for a custom event record (%d).",
174                              OffsetPtr);
175
176   auto BeginOffset = OffsetPtr;
177   auto PreReadOffset = OffsetPtr;
178
179   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
180   if (PreReadOffset == OffsetPtr)
181     return createStringError(
182         std::make_error_code(std::errc::invalid_argument),
183         "Cannot read a custom event record size field offset %d.", OffsetPtr);
184
185   if (R.Size <= 0)
186     return createStringError(
187         std::make_error_code(std::errc::bad_address),
188         "Invalid size for custom event (size = %d) at offset %d.", R.Size,
189         OffsetPtr);
190
191   PreReadOffset = OffsetPtr;
192   R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
193   if (PreReadOffset == OffsetPtr)
194     return createStringError(
195         std::make_error_code(std::errc::invalid_argument),
196         "Cannot read a custom event record TSC delta field at offset %d.",
197         OffsetPtr);
198
199   assert(OffsetPtr > BeginOffset &&
200          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
201   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
202
203   // Next we read in a fixed chunk of data from the given offset.
204   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
205     return createStringError(
206         std::make_error_code(std::errc::bad_address),
207         "Cannot read %d bytes of custom event data from offset %d.", R.Size,
208         OffsetPtr);
209
210   std::vector<uint8_t> Buffer;
211   Buffer.resize(R.Size);
212   PreReadOffset = OffsetPtr;
213   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
214     return createStringError(
215         std::make_error_code(std::errc::invalid_argument),
216         "Failed reading data into buffer of size %d at offset %d.", R.Size,
217         OffsetPtr);
218
219   assert(OffsetPtr >= PreReadOffset);
220   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
221     return createStringError(
222         std::make_error_code(std::errc::invalid_argument),
223         "Failed reading enough bytes for the custom event payload -- read %d "
224         "expecting %d bytes at offset %d.",
225         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
226
227   R.Data.assign(Buffer.begin(), Buffer.end());
228   return Error::success();
229 }
230
231 Error RecordInitializer::visit(TypedEventRecord &R) {
232   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
233                                     MetadataRecord::kMetadataBodySize))
234     return createStringError(std::make_error_code(std::errc::bad_address),
235                              "Invalid offset for a typed event record (%d).",
236                              OffsetPtr);
237
238   auto BeginOffset = OffsetPtr;
239   auto PreReadOffset = OffsetPtr;
240
241   R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t));
242   if (PreReadOffset == OffsetPtr)
243     return createStringError(
244         std::make_error_code(std::errc::invalid_argument),
245         "Cannot read a typed event record size field offset %d.", OffsetPtr);
246
247   if (R.Size <= 0)
248     return createStringError(
249         std::make_error_code(std::errc::bad_address),
250         "Invalid size for typed event (size = %d) at offset %d.", R.Size,
251         OffsetPtr);
252
253   PreReadOffset = OffsetPtr;
254   R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t));
255   if (PreReadOffset == OffsetPtr)
256     return createStringError(
257         std::make_error_code(std::errc::invalid_argument),
258         "Cannot read a typed event record TSC delta field at offset %d.",
259         OffsetPtr);
260
261   PreReadOffset = OffsetPtr;
262   R.EventType = E.getU16(&OffsetPtr);
263   if (PreReadOffset == OffsetPtr)
264     return createStringError(
265         std::make_error_code(std::errc::invalid_argument),
266         "Cannot read a typed event record type field at offset %d.", OffsetPtr);
267
268   assert(OffsetPtr > BeginOffset &&
269          OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize);
270   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset);
271
272   // Next we read in a fixed chunk of data from the given offset.
273   if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size))
274     return createStringError(
275         std::make_error_code(std::errc::bad_address),
276         "Cannot read %d bytes of custom event data from offset %d.", R.Size,
277         OffsetPtr);
278
279   std::vector<uint8_t> Buffer;
280   Buffer.resize(R.Size);
281   PreReadOffset = OffsetPtr;
282   if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data())
283     return createStringError(
284         std::make_error_code(std::errc::invalid_argument),
285         "Failed reading data into buffer of size %d at offset %d.", R.Size,
286         OffsetPtr);
287
288   assert(OffsetPtr >= PreReadOffset);
289   if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size))
290     return createStringError(
291         std::make_error_code(std::errc::invalid_argument),
292         "Failed reading enough bytes for the typed event payload -- read %d "
293         "expecting %d bytes at offset %d.",
294         OffsetPtr - PreReadOffset, R.Size, PreReadOffset);
295
296   R.Data.assign(Buffer.begin(), Buffer.end());
297   return Error::success();
298 }
299
300 Error RecordInitializer::visit(CallArgRecord &R) {
301   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
302                                     MetadataRecord::kMetadataBodySize))
303     return createStringError(std::make_error_code(std::errc::bad_address),
304                              "Invalid offset for a call argument record (%d).",
305                              OffsetPtr);
306
307   auto PreReadOffset = OffsetPtr;
308   R.Arg = E.getU64(&OffsetPtr);
309   if (PreReadOffset == OffsetPtr)
310     return createStringError(std::make_error_code(std::errc::invalid_argument),
311                              "Cannot read a call arg record at offset %d.",
312                              OffsetPtr);
313
314   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
315   return Error::success();
316 }
317
318 Error RecordInitializer::visit(PIDRecord &R) {
319   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
320                                     MetadataRecord::kMetadataBodySize))
321     return createStringError(std::make_error_code(std::errc::bad_address),
322                              "Invalid offset for a process ID record (%d).",
323                              OffsetPtr);
324
325   auto PreReadOffset = OffsetPtr;
326   R.PID = E.getSigned(&OffsetPtr, 4);
327   if (PreReadOffset == OffsetPtr)
328     return createStringError(std::make_error_code(std::errc::invalid_argument),
329                              "Cannot read a process ID record at offset %d.",
330                              OffsetPtr);
331
332   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
333   return Error::success();
334 }
335
336 Error RecordInitializer::visit(NewBufferRecord &R) {
337   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
338                                     MetadataRecord::kMetadataBodySize))
339     return createStringError(std::make_error_code(std::errc::bad_address),
340                              "Invalid offset for a new buffer record (%d).",
341                              OffsetPtr);
342
343   auto PreReadOffset = OffsetPtr;
344   R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t));
345   if (PreReadOffset == OffsetPtr)
346     return createStringError(std::make_error_code(std::errc::invalid_argument),
347                              "Cannot read a new buffer record at offset %d.",
348                              OffsetPtr);
349
350   OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset);
351   return Error::success();
352 }
353
354 Error RecordInitializer::visit(EndBufferRecord &R) {
355   if (!E.isValidOffsetForDataOfSize(OffsetPtr,
356                                     MetadataRecord::kMetadataBodySize))
357     return createStringError(std::make_error_code(std::errc::bad_address),
358                              "Invalid offset for an end-of-buffer record (%d).",
359                              OffsetPtr);
360
361   OffsetPtr += MetadataRecord::kMetadataBodySize;
362   return Error::success();
363 }
364
365 Error RecordInitializer::visit(FunctionRecord &R) {
366   // For function records, we need to retreat one byte back to read a full
367   // unsigned 32-bit value. The first four bytes will have the following
368   // layout:
369   //
370   //   bit  0     : function record indicator (must be 0)
371   //   bits 1..3  : function record type
372   //   bits 4..32 : function id
373   //
374   if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize(
375                             --OffsetPtr, FunctionRecord::kFunctionRecordSize))
376     return createStringError(std::make_error_code(std::errc::bad_address),
377                              "Invalid offset for a function record (%d).",
378                              OffsetPtr);
379
380   auto BeginOffset = OffsetPtr;
381   auto PreReadOffset = BeginOffset;
382   uint32_t Buffer = E.getU32(&OffsetPtr);
383   if (PreReadOffset == OffsetPtr)
384     return createStringError(std::make_error_code(std::errc::bad_address),
385                              "Cannot read function id field from offset %d.",
386                              OffsetPtr);
387
388   // To get the function record type, we shift the buffer one to the right
389   // (truncating the function record indicator) then take the three bits
390   // (0b0111) to get the record type as an unsigned value.
391   unsigned FunctionType = (Buffer >> 1) & 0x07u;
392   switch (FunctionType) {
393   case static_cast<unsigned>(RecordTypes::ENTER):
394   case static_cast<unsigned>(RecordTypes::ENTER_ARG):
395   case static_cast<unsigned>(RecordTypes::EXIT):
396   case static_cast<unsigned>(RecordTypes::TAIL_EXIT):
397     R.Kind = static_cast<RecordTypes>(FunctionType);
398     break;
399   default:
400     return createStringError(std::make_error_code(std::errc::invalid_argument),
401                              "Unknown function record type '%d' at offset %d.",
402                              FunctionType, BeginOffset);
403   }
404
405   R.FuncId = Buffer >> 4;
406   PreReadOffset = OffsetPtr;
407   R.Delta = E.getU32(&OffsetPtr);
408   if (OffsetPtr == PreReadOffset)
409     return createStringError(std::make_error_code(std::errc::invalid_argument),
410                              "Failed reading TSC delta from offset %d.",
411                              OffsetPtr);
412   assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset));
413   return Error::success();
414 }
415
416 } // namespace xray
417 } // namespace llvm