2018-09-11 08:22:53 +08:00
|
|
|
//===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2018-09-11 08:22:53 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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.
|
[Support] Move llvm::MemoryBuffer to sys::fs::file_t
Summary:
On Windows, Posix integer file descriptors are a compatibility layer
over native file handles provided by the C runtime. There is a hard
limit on the maximum number of file descriptors that a process can open,
and the limit is 8192. LLD typically doesn't run into this limit because
it opens input files, maps them into memory, and then immediately closes
the file descriptor. This prevents it from running out of FDs.
For various reasons, I'd like to open handles to every input file and
keep them open during linking. That requires migrating MemoryBuffer over
to taking open native file handles instead of integer FDs.
Reviewers: aganea, Bigcheese
Reviewed By: aganea
Subscribers: smeenai, silvas, mehdi_amini, hiraditya, steven_wu, dexonsmith, dang, llvm-commits, zturner
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D63453
llvm-svn: 365588
2019-07-10 08:34:13 +08:00
|
|
|
auto FDOrErr = sys::fs::openNativeFileForRead(DumpInput);
|
|
|
|
if (!FDOrErr)
|
|
|
|
return FDOrErr.takeError();
|
2018-09-11 08:22:53 +08:00
|
|
|
|
|
|
|
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(
|
[Support] Move llvm::MemoryBuffer to sys::fs::file_t
Summary:
On Windows, Posix integer file descriptors are a compatibility layer
over native file handles provided by the C runtime. There is a hard
limit on the maximum number of file descriptors that a process can open,
and the limit is 8192. LLD typically doesn't run into this limit because
it opens input files, maps them into memory, and then immediately closes
the file descriptor. This prevents it from running out of FDs.
For various reasons, I'd like to open handles to every input file and
keep them open during linking. That requires migrating MemoryBuffer over
to taking open native file handles instead of integer FDs.
Reviewers: aganea, Bigcheese
Reviewed By: aganea
Subscribers: smeenai, silvas, mehdi_amini, hiraditya, steven_wu, dexonsmith, dang, llvm-commits, zturner
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D63453
llvm-svn: 365588
2019-07-10 08:34:13 +08:00
|
|
|
*FDOrErr, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0,
|
|
|
|
EC);
|
|
|
|
sys::fs::closeFile(*FDOrErr);
|
2018-09-11 08:22:53 +08:00
|
|
|
|
|
|
|
DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8);
|
2019-08-06 18:49:40 +08:00
|
|
|
uint64_t OffsetPtr = 0;
|
2018-09-11 08:22:53 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
});
|