LLVM: lib/XRay/Trace.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
25#include
26#include
27
28using namespace llvm;
31
34 std::vector &Records) {
35 if (Data.size() < 32)
37 "Not enough bytes for an XRay log.",
38 std::make_error_code(std::errc::invalid_argument));
39
40 if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
42 "Invalid-sized XRay data.",
43 std::make_error_code(std::errc::invalid_argument));
44
48 if (!FileHeaderOrError)
49 return FileHeaderOrError.takeError();
50 FileHeader = std::move(FileHeaderOrError.get());
51
53 Records.reserve(NumReservations);
54
55
56
57
58
59
60
61
62
63
64
68 std::make_error_code(std::errc::executable_format_error),
69 "Not enough bytes to read a full record at offset %" PRId64 ".",
70 OffsetPtr);
71 auto PreReadOffset = OffsetPtr;
73 if (OffsetPtr == PreReadOffset)
75 std::make_error_code(std::errc::executable_format_error),
76 "Failed reading record type at offset %" PRId64 ".", OffsetPtr);
77
79 case 0: {
83
84 PreReadOffset = OffsetPtr;
86 if (OffsetPtr == PreReadOffset)
88 std::make_error_code(std::errc::executable_format_error),
89 "Failed reading CPU field at offset %" PRId64 ".", OffsetPtr);
90
91 PreReadOffset = OffsetPtr;
92 auto Type = Reader.getU8(&OffsetPtr);
93 if (OffsetPtr == PreReadOffset)
95 std::make_error_code(std::errc::executable_format_error),
96 "Failed reading record type field at offset %" PRId64 ".",
97 OffsetPtr);
98
99 switch (Type) {
100 case 0:
102 break;
103 case 1:
105 break;
106 case 2:
108 break;
109 case 3:
111 break;
112 default:
114 std::make_error_code(std::errc::executable_format_error),
115 "Unknown record type '%d' at offset %" PRId64 ".", Type, OffsetPtr);
116 }
117
118 PreReadOffset = OffsetPtr;
119 Record.FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));
120 if (OffsetPtr == PreReadOffset)
122 std::make_error_code(std::errc::executable_format_error),
123 "Failed reading function id field at offset %" PRId64 ".",
124 OffsetPtr);
125
126 PreReadOffset = OffsetPtr;
128 if (OffsetPtr == PreReadOffset)
130 std::make_error_code(std::errc::executable_format_error),
131 "Failed reading TSC field at offset %" PRId64 ".", OffsetPtr);
132
133 PreReadOffset = OffsetPtr;
135 if (OffsetPtr == PreReadOffset)
137 std::make_error_code(std::errc::executable_format_error),
138 "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);
139
140 PreReadOffset = OffsetPtr;
142 if (OffsetPtr == PreReadOffset)
144 std::make_error_code(std::errc::executable_format_error),
145 "Failed reading process id at offset %" PRId64 ".", OffsetPtr);
146
147 break;
148 }
149 case 1: {
151
152
153
154 OffsetPtr += 2;
155 PreReadOffset = OffsetPtr;
156 int32_t FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));
157 if (OffsetPtr == PreReadOffset)
159 std::make_error_code(std::errc::executable_format_error),
160 "Failed reading function id field at offset %" PRId64 ".",
161 OffsetPtr);
162
163 PreReadOffset = OffsetPtr;
164 auto TId = Reader.getU32(&OffsetPtr);
165 if (OffsetPtr == PreReadOffset)
167 std::make_error_code(std::errc::executable_format_error),
168 "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);
169
170 PreReadOffset = OffsetPtr;
171 auto PId = Reader.getU32(&OffsetPtr);
172 if (OffsetPtr == PreReadOffset)
174 std::make_error_code(std::errc::executable_format_error),
175 "Failed reading process id field at offset %" PRId64 ".",
176 OffsetPtr);
177
178
179 if (Record.FuncId != FuncId || Record.TId != TId ||
180 (FileHeader.Version >= 3 ? Record.PId != PId : false))
182 std::make_error_code(std::errc::executable_format_error),
183 "Corrupted log, found arg payload following non-matching "
184 "function+thread record. Record for function %d != %d at offset "
185 "%" PRId64 ".",
186 Record.FuncId, FuncId, OffsetPtr);
187
188 PreReadOffset = OffsetPtr;
189 auto Arg = Reader.getU64(&OffsetPtr);
190 if (OffsetPtr == PreReadOffset)
192 std::make_error_code(std::errc::executable_format_error),
193 "Failed reading argument payload at offset %" PRId64 ".",
194 OffsetPtr);
195
196 Record.CallArgs.push_back(Arg);
197 break;
198 }
199 default:
201 std::make_error_code(std::errc::executable_format_error),
202 "Unknown record type '%d' at offset %" PRId64 ".", RecordType,
203 OffsetPtr);
204 }
205
206
207 OffsetPtr += 8;
208 }
210}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
268 std::vector &Records) {
269
270 if (Data.size() < 32)
271 return createStringError(std::make_error_code(std::errc::invalid_argument),
272 "Not enough bytes for an XRay FDR log.");
274
277 if (!FileHeaderOrError)
278 return FileHeaderOrError.takeError();
279 FileHeader = std::move(FileHeaderOrError.get());
280
281
282 std::vector<std::unique_ptr> FDRRecords;
283
284 {
288 auto R = P.produce();
289 if (!R)
290 return R.takeError();
291 if (auto E = C.consume(std::move(R.get())))
292 return E;
293 }
294 }
295
296
298 {
300 for (auto &R : FDRRecords)
301 if (auto E = R->apply(Indexer))
302 return E;
303 if (auto E = Indexer.flush())
304 return E;
305 }
306
307
308 {
309 for (auto &PTB : Index) {
310 auto &Blocks = PTB.second;
311 for (auto &B : Blocks) {
313 for (auto *R : B.Records)
314 if (auto E = R->apply(Verifier))
315 return E;
316 if (auto E = Verifier.verify())
317 return E;
318 }
319 }
320 }
321
322
323
324
325
326
327 {
328 for (auto &PTB : Index) {
329 auto &Blocks = PTB.second;
332 return (L.WallclockTime->seconds() < R.WallclockTime->seconds() &&
333 L.WallclockTime->nanos() < R.WallclockTime->nanos());
334 });
337 for (auto &B : Blocks) {
338 for (auto *R : B.Records)
339 if (auto E = R->apply(Expander))
340 return E;
341 }
342 if (auto E = Expander.flush())
343 return E;
344 }
345 }
346
348}
349
351 std::vector &Records) {
355 if (In.error())
357
359 FileHeader.Type = Trace.Header.Type;
363
364 if (FileHeader.Version != 1)
366 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
367 std::make_error_code(std::errc::invalid_argument));
368
371 std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
372 return XRayRecord{R.RecordType, R.CPU, R.Type,
373 R.FuncId, R.TSC, R.TId,
374 R.PId, R.CallArgs, R.Data};
375 });
377}
378
381 if (!FdOrErr)
383
387 Twine("Cannot read log from '") + Filename + "'", EC);
388 }
389 if (FileSize < 4) {
391 Twine("File '") + Filename + "' too small for XRay.",
392 std::make_error_code(std::errc::executable_format_error));
393 }
394
395
396 std::error_code EC;
399 EC);
401 if (EC) {
403 Twine("Cannot read log from '") + Filename + "'", EC);
404 }
406
407
409 auto TraceOrError = loadTrace(LittleEndianDE, Sort);
410 if (!TraceOrError) {
413 TraceOrError = loadTrace(BigEndianDE, Sort);
414 }
415 return TraceOrError;
416}
417
419
420
421
422
423
424
425
426
427
428
429
430
431
432
437
438 enum BinaryFormatType { NAIVE_FORMAT = 0, FLIGHT_DATA_RECORDER_FORMAT = 1 };
439
441 switch (Type) {
442 case NAIVE_FORMAT:
446 return std::move(E);
447 } else {
449 Twine("Unsupported version for Basic/Naive Mode logging: ") +
451 std::make_error_code(std::errc::executable_format_error));
452 }
453 break;
454 case FLIGHT_DATA_RECORDER_FORMAT:
457 T.Records))
458 return std::move(E);
459 } else {
461 Twine("Unsupported version for FDR Mode logging: ") + Twine(Version),
462 std::make_error_code(std::errc::executable_format_error));
463 }
464 break;
465 default:
467 return std::move(E);
468 }
469
470 if (Sort)
472 return L.TSC < R.TSC;
473 });
474
475 return std::move(T);
476}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
FunctionLoweringInfo::StatepointRelocationRecord RecordType
static Error loadFDRLog(StringRef Data, bool IsLittleEndian, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)
Reads a log in FDR mode for version 1 of this binary format.
Definition Trace.cpp:266
static Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)
Definition Trace.cpp:32
static Error loadYAMLLog(StringRef Data, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)
Definition Trace.cpp:350
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
This class represents a memory mapped file.
LLVM_ABI size_t size() const
@ readonly
May only access map via const_data as read only.
LLVM_ABI char * data() const
DenseMap< std::pair< uint64_t, int32_t >, std::vector< Block > > Index
Error flush()
The flush() function will clear out the current state of the visitor, to allow for explicitly flushin...
A Trace object represents the records that have been loaded from XRay log files generated by instrume...
The Input class is used to parse a yaml document into in-memory structs and vectors.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
std::error_code file_size(const Twine &Path, uint64_t &Result)
Get file size.
LLVM_ABI Expected< Trace > loadTrace(const DataExtractor &Extractor, bool Sort=false)
This function will attempt to load XRay trace records from the provided DataExtractor.
Definition Trace.cpp:418
LLVM_ABI Expected< XRayFileHeader > readBinaryFormatHeader(DataExtractor &HeaderExtractor, uint64_t &OffsetPtr)
Convenience function for loading the file header given a data extractor at a specified offset.
LLVM_ABI Expected< Trace > loadTraceFile(StringRef Filename, bool Sort=false)
This function will attempt to load XRay trace records from the provided |Filename|.
Definition Trace.cpp:379
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
FunctionAddr VTableAddr uintptr_t uintptr_t Version
void sort(IteratorTy Start, IteratorTy End)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
FunctionAddr VTableAddr uintptr_t uintptr_t Data
void consumeError(Error Err)
Consume a Error without doing anything.
An XRayRecord is the denormalized view of data associated in a trace.