1*0b57cec5SDimitry Andric //===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Implements the FDR trace dumping tool, using the libraries for handling FDR 10*0b57cec5SDimitry Andric // mode traces specifically. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric #include "xray-registry.h" 14*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 16*0b57cec5SDimitry Andric #include "llvm/XRay/BlockIndexer.h" 17*0b57cec5SDimitry Andric #include "llvm/XRay/BlockPrinter.h" 18*0b57cec5SDimitry Andric #include "llvm/XRay/BlockVerifier.h" 19*0b57cec5SDimitry Andric #include "llvm/XRay/FDRRecordConsumer.h" 20*0b57cec5SDimitry Andric #include "llvm/XRay/FDRRecordProducer.h" 21*0b57cec5SDimitry Andric #include "llvm/XRay/FDRRecords.h" 22*0b57cec5SDimitry Andric #include "llvm/XRay/FileHeaderReader.h" 23*0b57cec5SDimitry Andric #include "llvm/XRay/RecordPrinter.h" 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric using namespace llvm; 26*0b57cec5SDimitry Andric using namespace xray; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump"); 29*0b57cec5SDimitry Andric static cl::opt<std::string> DumpInput(cl::Positional, 30*0b57cec5SDimitry Andric cl::desc("<xray fdr mode log>"), 31*0b57cec5SDimitry Andric cl::Required, cl::sub(Dump)); 32*0b57cec5SDimitry Andric static cl::opt<bool> DumpVerify("verify", 33*0b57cec5SDimitry Andric cl::desc("verify structure of the log"), 34*0b57cec5SDimitry Andric cl::init(false), cl::sub(Dump)); 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric static CommandRegistration Unused(&Dump, []() -> Error { 37*0b57cec5SDimitry Andric // Open the file provided. 38*0b57cec5SDimitry Andric auto FDOrErr = sys::fs::openNativeFileForRead(DumpInput); 39*0b57cec5SDimitry Andric if (!FDOrErr) 40*0b57cec5SDimitry Andric return FDOrErr.takeError(); 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric uint64_t FileSize; 43*0b57cec5SDimitry Andric if (auto EC = sys::fs::file_size(DumpInput, FileSize)) 44*0b57cec5SDimitry Andric return createStringError(EC, "Failed to get file size for '%s'.", 45*0b57cec5SDimitry Andric DumpInput.c_str()); 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric std::error_code EC; 48*0b57cec5SDimitry Andric sys::fs::mapped_file_region MappedFile( 49*0b57cec5SDimitry Andric *FDOrErr, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, 50*0b57cec5SDimitry Andric EC); 51*0b57cec5SDimitry Andric sys::fs::closeFile(*FDOrErr); 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8); 54*0b57cec5SDimitry Andric uint32_t OffsetPtr = 0; 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr); 57*0b57cec5SDimitry Andric if (!FileHeaderOrError) 58*0b57cec5SDimitry Andric return FileHeaderOrError.takeError(); 59*0b57cec5SDimitry Andric auto &H = FileHeaderOrError.get(); 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric FileBasedRecordProducer P(H, DE, OffsetPtr); 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric RecordPrinter RP(outs(), "\n"); 64*0b57cec5SDimitry Andric if (!DumpVerify) { 65*0b57cec5SDimitry Andric PipelineConsumer C({&RP}); 66*0b57cec5SDimitry Andric while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) { 67*0b57cec5SDimitry Andric auto R = P.produce(); 68*0b57cec5SDimitry Andric if (!R) 69*0b57cec5SDimitry Andric return R.takeError(); 70*0b57cec5SDimitry Andric if (auto E = C.consume(std::move(R.get()))) 71*0b57cec5SDimitry Andric return E; 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric return Error::success(); 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric BlockPrinter BP(outs(), RP); 77*0b57cec5SDimitry Andric std::vector<std::unique_ptr<Record>> Records; 78*0b57cec5SDimitry Andric LogBuilderConsumer C(Records); 79*0b57cec5SDimitry Andric while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) { 80*0b57cec5SDimitry Andric auto R = P.produce(); 81*0b57cec5SDimitry Andric if (!R) { 82*0b57cec5SDimitry Andric // Print records we've found so far. 83*0b57cec5SDimitry Andric for (auto &Ptr : Records) 84*0b57cec5SDimitry Andric if (auto E = Ptr->apply(RP)) 85*0b57cec5SDimitry Andric return joinErrors(std::move(E), R.takeError()); 86*0b57cec5SDimitry Andric return R.takeError(); 87*0b57cec5SDimitry Andric } 88*0b57cec5SDimitry Andric if (auto E = C.consume(std::move(R.get()))) 89*0b57cec5SDimitry Andric return E; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric // Once we have a trace, we then index the blocks. 93*0b57cec5SDimitry Andric BlockIndexer::Index Index; 94*0b57cec5SDimitry Andric BlockIndexer BI(Index); 95*0b57cec5SDimitry Andric for (auto &Ptr : Records) 96*0b57cec5SDimitry Andric if (auto E = Ptr->apply(BI)) 97*0b57cec5SDimitry Andric return E; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric if (auto E = BI.flush()) 100*0b57cec5SDimitry Andric return E; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric // Then we validate while printing each block. 103*0b57cec5SDimitry Andric BlockVerifier BV; 104*0b57cec5SDimitry Andric for (auto ProcessThreadBlocks : Index) { 105*0b57cec5SDimitry Andric auto &Blocks = ProcessThreadBlocks.second; 106*0b57cec5SDimitry Andric for (auto &B : Blocks) { 107*0b57cec5SDimitry Andric for (auto *R : B.Records) { 108*0b57cec5SDimitry Andric if (auto E = R->apply(BV)) 109*0b57cec5SDimitry Andric return E; 110*0b57cec5SDimitry Andric if (auto E = R->apply(BP)) 111*0b57cec5SDimitry Andric return E; 112*0b57cec5SDimitry Andric } 113*0b57cec5SDimitry Andric BV.reset(); 114*0b57cec5SDimitry Andric BP.reset(); 115*0b57cec5SDimitry Andric } 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric outs().flush(); 118*0b57cec5SDimitry Andric return Error::success(); 119*0b57cec5SDimitry Andric }); 120