forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			120 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // Implements the FDR trace dumping tool, using the libraries for handling FDR
 | |
| // mode traces specifically.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| #include "xray-registry.h"
 | |
| #include "llvm/Support/CommandLine.h"
 | |
| #include "llvm/Support/FileSystem.h"
 | |
| #include "llvm/XRay/BlockIndexer.h"
 | |
| #include "llvm/XRay/BlockPrinter.h"
 | |
| #include "llvm/XRay/BlockVerifier.h"
 | |
| #include "llvm/XRay/FDRRecordConsumer.h"
 | |
| #include "llvm/XRay/FDRRecordProducer.h"
 | |
| #include "llvm/XRay/FDRRecords.h"
 | |
| #include "llvm/XRay/FileHeaderReader.h"
 | |
| #include "llvm/XRay/RecordPrinter.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace xray;
 | |
| 
 | |
| static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump");
 | |
| static cl::opt<std::string> DumpInput(cl::Positional,
 | |
|                                       cl::desc("<xray fdr mode log>"),
 | |
|                                       cl::Required, cl::sub(Dump));
 | |
| static cl::opt<bool> DumpVerify("verify",
 | |
|                                 cl::desc("verify structure of the log"),
 | |
|                                 cl::init(false), cl::sub(Dump));
 | |
| 
 | |
| static CommandRegistration Unused(&Dump, []() -> Error {
 | |
|   // Open the file provided.
 | |
|   auto FDOrErr = sys::fs::openNativeFileForRead(DumpInput);
 | |
|   if (!FDOrErr)
 | |
|     return FDOrErr.takeError();
 | |
| 
 | |
|   uint64_t FileSize;
 | |
|   if (auto EC = sys::fs::file_size(DumpInput, FileSize))
 | |
|     return createStringError(EC, "Failed to get file size for '%s'.",
 | |
|                              DumpInput.c_str());
 | |
| 
 | |
|   std::error_code EC;
 | |
|   sys::fs::mapped_file_region MappedFile(
 | |
|       *FDOrErr, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0,
 | |
|       EC);
 | |
|   sys::fs::closeFile(*FDOrErr);
 | |
| 
 | |
|   DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8);
 | |
|   uint64_t OffsetPtr = 0;
 | |
| 
 | |
|   auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr);
 | |
|   if (!FileHeaderOrError)
 | |
|     return FileHeaderOrError.takeError();
 | |
|   auto &H = FileHeaderOrError.get();
 | |
| 
 | |
|   FileBasedRecordProducer P(H, DE, OffsetPtr);
 | |
| 
 | |
|   RecordPrinter RP(outs(), "\n");
 | |
|   if (!DumpVerify) {
 | |
|     PipelineConsumer C({&RP});
 | |
|     while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
 | |
|       auto R = P.produce();
 | |
|       if (!R)
 | |
|         return R.takeError();
 | |
|       if (auto E = C.consume(std::move(R.get())))
 | |
|         return E;
 | |
|     }
 | |
|     return Error::success();
 | |
|   }
 | |
| 
 | |
|   BlockPrinter BP(outs(), RP);
 | |
|   std::vector<std::unique_ptr<Record>> Records;
 | |
|   LogBuilderConsumer C(Records);
 | |
|   while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
 | |
|     auto R = P.produce();
 | |
|     if (!R) {
 | |
|       // Print records we've found so far.
 | |
|       for (auto &Ptr : Records)
 | |
|         if (auto E = Ptr->apply(RP))
 | |
|           return joinErrors(std::move(E), R.takeError());
 | |
|       return R.takeError();
 | |
|     }
 | |
|     if (auto E = C.consume(std::move(R.get())))
 | |
|       return E;
 | |
|   }
 | |
| 
 | |
|   // Once we have a trace, we then index the blocks.
 | |
|   BlockIndexer::Index Index;
 | |
|   BlockIndexer BI(Index);
 | |
|   for (auto &Ptr : Records)
 | |
|     if (auto E = Ptr->apply(BI))
 | |
|       return E;
 | |
| 
 | |
|   if (auto E = BI.flush())
 | |
|     return E;
 | |
| 
 | |
|   // Then we validate while printing each block.
 | |
|   BlockVerifier BV;
 | |
|   for (auto ProcessThreadBlocks : Index) {
 | |
|     auto &Blocks = ProcessThreadBlocks.second;
 | |
|     for (auto &B : Blocks) {
 | |
|       for (auto *R : B.Records) {
 | |
|         if (auto E = R->apply(BV))
 | |
|           return E;
 | |
|         if (auto E = R->apply(BP))
 | |
|           return E;
 | |
|       }
 | |
|       BV.reset();
 | |
|       BP.reset();
 | |
|     }
 | |
|   }
 | |
|   outs().flush();
 | |
|   return Error::success();
 | |
| });
 |