reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
//===- 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();
});