blob: 389825605b621280037412f470ae0167e9367c47 [file] [log] [blame]
Dean Michael Berrisdd24af12018-09-11 00:22:53 +00001//===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===//
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//
10// Implements the FDR trace dumping tool, using the libraries for handling FDR
11// mode traces specifically.
12//
13//===----------------------------------------------------------------------===//
14#include "xray-registry.h"
15#include "llvm/Support/CommandLine.h"
16#include "llvm/Support/FileSystem.h"
17#include "llvm/XRay/BlockIndexer.h"
18#include "llvm/XRay/BlockPrinter.h"
19#include "llvm/XRay/BlockVerifier.h"
20#include "llvm/XRay/FDRRecordConsumer.h"
21#include "llvm/XRay/FDRRecordProducer.h"
22#include "llvm/XRay/FDRRecords.h"
23#include "llvm/XRay/FileHeaderReader.h"
24#include "llvm/XRay/RecordPrinter.h"
25
26using namespace llvm;
27using namespace xray;
28
29static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump");
30static cl::opt<std::string> DumpInput(cl::Positional,
31 cl::desc("<xray fdr mode log>"),
32 cl::Required, cl::sub(Dump));
33static cl::opt<bool> DumpVerify("verify",
34 cl::desc("verify structure of the log"),
35 cl::init(false), cl::sub(Dump));
36
37static CommandRegistration Unused(&Dump, []() -> Error {
38 // Open the file provided.
39 int Fd;
40 if (auto EC = sys::fs::openFileForRead(DumpInput, Fd))
41 return createStringError(EC, "Cannot open file '%s' for read.",
42 DumpInput.c_str());
43
44 uint64_t FileSize;
45 if (auto EC = sys::fs::file_size(DumpInput, FileSize))
46 return createStringError(EC, "Failed to get file size for '%s'.",
47 DumpInput.c_str());
48
49 std::error_code EC;
50 sys::fs::mapped_file_region MappedFile(
51 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
52
53 DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8);
54 uint32_t OffsetPtr = 0;
55
56 auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr);
57 if (!FileHeaderOrError)
58 return FileHeaderOrError.takeError();
59 auto &H = FileHeaderOrError.get();
60
61 FileBasedRecordProducer P(H, DE, OffsetPtr);
62
63 RecordPrinter RP(outs(), "\n");
64 if (!DumpVerify) {
65 PipelineConsumer C({&RP});
66 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
67 auto R = P.produce();
68 if (!R)
69 return R.takeError();
70 if (auto E = C.consume(std::move(R.get())))
71 return E;
72 }
73 return Error::success();
74 }
75
76 BlockPrinter BP(outs(), RP);
77 std::vector<std::unique_ptr<Record>> Records;
78 LogBuilderConsumer C(Records);
79 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
80 auto R = P.produce();
81 if (!R) {
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());
86 return R.takeError();
87 }
88 if (auto E = C.consume(std::move(R.get())))
89 return E;
90 }
91
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))
97 return E;
98
99 if (auto E = BI.flush())
100 return E;
101
102 // Then we validate while printing each block.
103 BlockVerifier BV;
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))
109 return E;
110 if (auto E = R->apply(BP))
111 return E;
112 }
113 BV.reset();
114 BP.reset();
115 }
116 }
117 outs().flush();
118 return Error::success();
119});