]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-xray/xray-fdr-dump.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-xray / xray-fdr-dump.cpp
1 //===- 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
26 using namespace llvm;
27 using namespace xray;
28
29 static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump");
30 static cl::opt<std::string> DumpInput(cl::Positional,
31                                       cl::desc("<xray fdr mode log>"),
32                                       cl::Required, cl::sub(Dump));
33 static cl::opt<bool> DumpVerify("verify",
34                                 cl::desc("verify structure of the log"),
35                                 cl::init(false), cl::sub(Dump));
36
37 static 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 });