10b57cec5SDimitry Andric //===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implements the FDR trace dumping tool, using the libraries for handling FDR 100b57cec5SDimitry Andric // mode traces specifically. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric #include "xray-registry.h" 140b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 150b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 160b57cec5SDimitry Andric #include "llvm/XRay/BlockIndexer.h" 170b57cec5SDimitry Andric #include "llvm/XRay/BlockPrinter.h" 180b57cec5SDimitry Andric #include "llvm/XRay/BlockVerifier.h" 190b57cec5SDimitry Andric #include "llvm/XRay/FDRRecordConsumer.h" 200b57cec5SDimitry Andric #include "llvm/XRay/FDRRecordProducer.h" 210b57cec5SDimitry Andric #include "llvm/XRay/FDRRecords.h" 220b57cec5SDimitry Andric #include "llvm/XRay/FileHeaderReader.h" 230b57cec5SDimitry Andric #include "llvm/XRay/RecordPrinter.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric using namespace xray; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump"); 290b57cec5SDimitry Andric static cl::opt<std::string> DumpInput(cl::Positional, 300b57cec5SDimitry Andric cl::desc("<xray fdr mode log>"), 310b57cec5SDimitry Andric cl::Required, cl::sub(Dump)); 320b57cec5SDimitry Andric static cl::opt<bool> DumpVerify("verify", 330b57cec5SDimitry Andric cl::desc("verify structure of the log"), 340b57cec5SDimitry Andric cl::init(false), cl::sub(Dump)); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric static CommandRegistration Unused(&Dump, []() -> Error { 370b57cec5SDimitry Andric // Open the file provided. 380b57cec5SDimitry Andric auto FDOrErr = sys::fs::openNativeFileForRead(DumpInput); 390b57cec5SDimitry Andric if (!FDOrErr) 400b57cec5SDimitry Andric return FDOrErr.takeError(); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric uint64_t FileSize; 430b57cec5SDimitry Andric if (auto EC = sys::fs::file_size(DumpInput, FileSize)) 440b57cec5SDimitry Andric return createStringError(EC, "Failed to get file size for '%s'.", 450b57cec5SDimitry Andric DumpInput.c_str()); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric std::error_code EC; 480b57cec5SDimitry Andric sys::fs::mapped_file_region MappedFile( 490b57cec5SDimitry Andric *FDOrErr, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, 500b57cec5SDimitry Andric EC); 510b57cec5SDimitry Andric sys::fs::closeFile(*FDOrErr); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8); 548bcb0991SDimitry Andric uint64_t OffsetPtr = 0; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr); 570b57cec5SDimitry Andric if (!FileHeaderOrError) 580b57cec5SDimitry Andric return FileHeaderOrError.takeError(); 590b57cec5SDimitry Andric auto &H = FileHeaderOrError.get(); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric FileBasedRecordProducer P(H, DE, OffsetPtr); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric RecordPrinter RP(outs(), "\n"); 640b57cec5SDimitry Andric if (!DumpVerify) { 650b57cec5SDimitry Andric PipelineConsumer C({&RP}); 660b57cec5SDimitry Andric while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) { 670b57cec5SDimitry Andric auto R = P.produce(); 680b57cec5SDimitry Andric if (!R) 690b57cec5SDimitry Andric return R.takeError(); 700b57cec5SDimitry Andric if (auto E = C.consume(std::move(R.get()))) 710b57cec5SDimitry Andric return E; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric return Error::success(); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric BlockPrinter BP(outs(), RP); 770b57cec5SDimitry Andric std::vector<std::unique_ptr<Record>> Records; 780b57cec5SDimitry Andric LogBuilderConsumer C(Records); 790b57cec5SDimitry Andric while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) { 800b57cec5SDimitry Andric auto R = P.produce(); 810b57cec5SDimitry Andric if (!R) { 820b57cec5SDimitry Andric // Print records we've found so far. 830b57cec5SDimitry Andric for (auto &Ptr : Records) 840b57cec5SDimitry Andric if (auto E = Ptr->apply(RP)) 850b57cec5SDimitry Andric return joinErrors(std::move(E), R.takeError()); 860b57cec5SDimitry Andric return R.takeError(); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric if (auto E = C.consume(std::move(R.get()))) 890b57cec5SDimitry Andric return E; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Once we have a trace, we then index the blocks. 930b57cec5SDimitry Andric BlockIndexer::Index Index; 940b57cec5SDimitry Andric BlockIndexer BI(Index); 950b57cec5SDimitry Andric for (auto &Ptr : Records) 960b57cec5SDimitry Andric if (auto E = Ptr->apply(BI)) 970b57cec5SDimitry Andric return E; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric if (auto E = BI.flush()) 1000b57cec5SDimitry Andric return E; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Then we validate while printing each block. 1030b57cec5SDimitry Andric BlockVerifier BV; 104*5f757f3fSDimitry Andric for (const auto &ProcessThreadBlocks : Index) { 1050b57cec5SDimitry Andric auto &Blocks = ProcessThreadBlocks.second; 1060b57cec5SDimitry Andric for (auto &B : Blocks) { 1070b57cec5SDimitry Andric for (auto *R : B.Records) { 1080b57cec5SDimitry Andric if (auto E = R->apply(BV)) 1090b57cec5SDimitry Andric return E; 1100b57cec5SDimitry Andric if (auto E = R->apply(BP)) 1110b57cec5SDimitry Andric return E; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric BV.reset(); 1140b57cec5SDimitry Andric BP.reset(); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric outs().flush(); 1180b57cec5SDimitry Andric return Error::success(); 1190b57cec5SDimitry Andric }); 120