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.
39 if (auto EC
= sys::fs::openFileForRead(DumpInput
, Fd
))
40 return createStringError(EC
, "Cannot open file '%s' for read.",
44 if (auto EC
= sys::fs::file_size(DumpInput
, FileSize
))
45 return createStringError(EC
, "Failed to get file size for '%s'.",
49 sys::fs::mapped_file_region
MappedFile(
50 Fd
, sys::fs::mapped_file_region::mapmode::readonly
, FileSize
, 0, EC
);
52 DataExtractor
DE(StringRef(MappedFile
.data(), MappedFile
.size()), true, 8);
53 uint32_t OffsetPtr
= 0;
55 auto FileHeaderOrError
= readBinaryFormatHeader(DE
, OffsetPtr
);
56 if (!FileHeaderOrError
)
57 return FileHeaderOrError
.takeError();
58 auto &H
= FileHeaderOrError
.get();
60 FileBasedRecordProducer
P(H
, DE
, OffsetPtr
);
62 RecordPrinter
RP(outs(), "\n");
64 PipelineConsumer
C({&RP
});
65 while (DE
.isValidOffsetForDataOfSize(OffsetPtr
, 1)) {
69 if (auto E
= C
.consume(std::move(R
.get())))
72 return Error::success();
75 BlockPrinter
BP(outs(), RP
);
76 std::vector
<std::unique_ptr
<Record
>> Records
;
77 LogBuilderConsumer
C(Records
);
78 while (DE
.isValidOffsetForDataOfSize(OffsetPtr
, 1)) {
81 // Print records we've found so far.
82 for (auto &Ptr
: Records
)
83 if (auto E
= Ptr
->apply(RP
))
84 return joinErrors(std::move(E
), R
.takeError());
87 if (auto E
= C
.consume(std::move(R
.get())))
91 // Once we have a trace, we then index the blocks.
92 BlockIndexer::Index Index
;
93 BlockIndexer
BI(Index
);
94 for (auto &Ptr
: Records
)
95 if (auto E
= Ptr
->apply(BI
))
98 if (auto E
= BI
.flush())
101 // Then we validate while printing each block.
103 for (auto ProcessThreadBlocks
: Index
) {
104 auto &Blocks
= ProcessThreadBlocks
.second
;
105 for (auto &B
: Blocks
) {
106 for (auto *R
: B
.Records
) {
107 if (auto E
= R
->apply(BV
))
109 if (auto E
= R
->apply(BP
))
117 return Error::success();