1 //===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implements the FDR trace dumping tool, using the libraries for handling FDR
10 // mode traces specifically.
12 //===----------------------------------------------------------------------===//
13 #include "xray-registry.h"
14 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/XRay/BlockIndexer.h"
17 #include "llvm/XRay/BlockPrinter.h"
18 #include "llvm/XRay/BlockVerifier.h"
19 #include "llvm/XRay/FDRRecordConsumer.h"
20 #include "llvm/XRay/FDRRecordProducer.h"
21 #include "llvm/XRay/FDRRecords.h"
22 #include "llvm/XRay/FileHeaderReader.h"
23 #include "llvm/XRay/RecordPrinter.h"
28 static cl::SubCommand
Dump("fdr-dump", "FDR Trace Dump");
29 static cl::opt
<std::string
> DumpInput(cl::Positional
,
30 cl::desc("<xray fdr mode log>"),
31 cl::Required
, cl::sub(Dump
));
32 static cl::opt
<bool> DumpVerify("verify",
33 cl::desc("verify structure of the log"),
34 cl::init(false), cl::sub(Dump
));
36 static CommandRegistration
Unused(&Dump
, []() -> Error
{
37 // Open the file provided.
38 auto FDOrErr
= sys::fs::openNativeFileForRead(DumpInput
);
40 return FDOrErr
.takeError();
43 if (auto EC
= sys::fs::file_size(DumpInput
, FileSize
))
44 return createStringError(EC
, "Failed to get file size for '%s'.",
48 sys::fs::mapped_file_region
MappedFile(
49 *FDOrErr
, sys::fs::mapped_file_region::mapmode::readonly
, FileSize
, 0,
51 sys::fs::closeFile(*FDOrErr
);
53 DataExtractor
DE(StringRef(MappedFile
.data(), MappedFile
.size()), true, 8);
54 uint64_t OffsetPtr
= 0;
56 auto FileHeaderOrError
= readBinaryFormatHeader(DE
, OffsetPtr
);
57 if (!FileHeaderOrError
)
58 return FileHeaderOrError
.takeError();
59 auto &H
= FileHeaderOrError
.get();
61 FileBasedRecordProducer
P(H
, DE
, OffsetPtr
);
63 RecordPrinter
RP(outs(), "\n");
65 PipelineConsumer
C({&RP
});
66 while (DE
.isValidOffsetForDataOfSize(OffsetPtr
, 1)) {
70 if (auto E
= C
.consume(std::move(R
.get())))
73 return Error::success();
76 BlockPrinter
BP(outs(), RP
);
77 std::vector
<std::unique_ptr
<Record
>> Records
;
78 LogBuilderConsumer
C(Records
);
79 while (DE
.isValidOffsetForDataOfSize(OffsetPtr
, 1)) {
82 // Print records we've found so far.
83 for (auto &Ptr
: Records
)
84 if (auto E
= Ptr
->apply(RP
))
85 return joinErrors(std::move(E
), R
.takeError());
88 if (auto E
= C
.consume(std::move(R
.get())))
92 // Once we have a trace, we then index the blocks.
93 BlockIndexer::Index Index
;
94 BlockIndexer
BI(Index
);
95 for (auto &Ptr
: Records
)
96 if (auto E
= Ptr
->apply(BI
))
99 if (auto E
= BI
.flush())
102 // Then we validate while printing each block.
104 for (auto ProcessThreadBlocks
: Index
) {
105 auto &Blocks
= ProcessThreadBlocks
.second
;
106 for (auto &B
: Blocks
) {
107 for (auto *R
: B
.Records
) {
108 if (auto E
= R
->apply(BV
))
110 if (auto E
= R
->apply(BP
))
118 return Error::success();