You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
148
external/llvm/tools/llvm-pdbutil/Analyze.cpp
vendored
148
external/llvm/tools/llvm-pdbutil/Analyze.cpp
vendored
@ -1,148 +0,0 @@
|
||||
//===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Analyze.h"
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
static StringRef getLeafTypeName(TypeLeafKind LT) {
|
||||
switch (LT) {
|
||||
#define TYPE_RECORD(ename, value, name) \
|
||||
case ename: \
|
||||
return #name;
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "UnknownLeaf";
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct HashLookupVisitor : public TypeVisitorCallbacks {
|
||||
struct Entry {
|
||||
TypeIndex TI;
|
||||
CVType Record;
|
||||
};
|
||||
|
||||
explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {}
|
||||
|
||||
Error visitTypeBegin(CVType &Record) override {
|
||||
uint32_t H = Tpi.getHashValues()[I];
|
||||
Record.Hash = H;
|
||||
TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex);
|
||||
Lookup[H].push_back(Entry{TI, Record});
|
||||
++I;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t I = 0;
|
||||
DenseMap<uint32_t, std::list<Entry>> Lookup;
|
||||
TpiStream &Tpi;
|
||||
};
|
||||
}
|
||||
|
||||
AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {}
|
||||
|
||||
Error AnalysisStyle::dump() {
|
||||
auto Tpi = File.getPDBTpiStream();
|
||||
if (!Tpi)
|
||||
return Tpi.takeError();
|
||||
|
||||
HashLookupVisitor Hasher(*Tpi);
|
||||
|
||||
uint32_t RecordCount = Tpi->getNumTypeRecords();
|
||||
auto Offsets = Tpi->getTypeIndexOffsets();
|
||||
auto Types = llvm::make_unique<LazyRandomTypeCollection>(
|
||||
Tpi->typeArray(), RecordCount, Offsets);
|
||||
|
||||
if (auto EC = codeview::visitTypeStream(*Types, Hasher))
|
||||
return EC;
|
||||
|
||||
auto &Adjusters = Tpi->getHashAdjusters();
|
||||
DenseSet<uint32_t> AdjusterSet;
|
||||
for (const auto &Adj : Adjusters) {
|
||||
assert(AdjusterSet.find(Adj.second) == AdjusterSet.end());
|
||||
AdjusterSet.insert(Adj.second);
|
||||
}
|
||||
|
||||
uint32_t Count = 0;
|
||||
outs() << "Searching for hash collisions\n";
|
||||
for (const auto &H : Hasher.Lookup) {
|
||||
if (H.second.size() <= 1)
|
||||
continue;
|
||||
++Count;
|
||||
outs() << formatv("Hash: {0}, Count: {1} records\n", H.first,
|
||||
H.second.size());
|
||||
for (const auto &R : H.second) {
|
||||
auto Iter = AdjusterSet.find(R.TI.getIndex());
|
||||
StringRef Prefix;
|
||||
if (Iter != AdjusterSet.end()) {
|
||||
Prefix = "[HEAD]";
|
||||
AdjusterSet.erase(Iter);
|
||||
}
|
||||
StringRef LeafName = getLeafTypeName(R.Record.Type);
|
||||
uint32_t TI = R.TI.getIndex();
|
||||
StringRef TypeName = Types->getTypeName(R.TI);
|
||||
outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI,
|
||||
TypeName);
|
||||
}
|
||||
}
|
||||
|
||||
outs() << "\n";
|
||||
outs() << "Dumping hash adjustment chains\n";
|
||||
for (const auto &A : Tpi->getHashAdjusters()) {
|
||||
TypeIndex TI(A.second);
|
||||
StringRef TypeName = Types->getTypeName(TI);
|
||||
const CVType &HeadRecord = Types->getType(TI);
|
||||
assert(HeadRecord.Hash.hasValue());
|
||||
|
||||
auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash);
|
||||
if (CollisionsIter == Hasher.Lookup.end())
|
||||
continue;
|
||||
|
||||
const auto &Collisions = CollisionsIter->second;
|
||||
outs() << TypeName << "\n";
|
||||
outs() << formatv(" [HEAD] {0:x} {1} {2}\n", A.second,
|
||||
getLeafTypeName(HeadRecord.Type), TypeName);
|
||||
for (const auto &Chain : Collisions) {
|
||||
if (Chain.TI == TI)
|
||||
continue;
|
||||
const CVType &TailRecord = Types->getType(Chain.TI);
|
||||
outs() << formatv(" {0:x} {1} {2}\n", Chain.TI.getIndex(),
|
||||
getLeafTypeName(TailRecord.Type),
|
||||
Types->getTypeName(Chain.TI));
|
||||
}
|
||||
}
|
||||
outs() << formatv("There are {0} orphaned hash adjusters\n",
|
||||
AdjusterSet.size());
|
||||
for (const auto &Adj : AdjusterSet) {
|
||||
outs() << formatv(" {0}\n", Adj);
|
||||
}
|
||||
|
||||
uint32_t DistinctHashValues = Hasher.Lookup.size();
|
||||
outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues);
|
||||
return Error::success();
|
||||
}
|
30
external/llvm/tools/llvm-pdbutil/Analyze.h
vendored
30
external/llvm/tools/llvm-pdbutil/Analyze.h
vendored
@ -1,30 +0,0 @@
|
||||
//===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
|
||||
|
||||
#include "OutputStyle.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
class PDBFile;
|
||||
class AnalysisStyle : public OutputStyle {
|
||||
public:
|
||||
explicit AnalysisStyle(PDBFile &File);
|
||||
|
||||
Error dump() override;
|
||||
|
||||
private:
|
||||
PDBFile &File;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,494 +0,0 @@
|
||||
//===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BytesOutputStyle.h"
|
||||
|
||||
#include "FormatUtil.h"
|
||||
#include "StreamUtil.h"
|
||||
#include "llvm-pdbutil.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/Formatters.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::msf;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
namespace {
|
||||
struct StreamSpec {
|
||||
uint32_t SI = 0;
|
||||
uint32_t Begin = 0;
|
||||
uint32_t Size = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static Expected<StreamSpec> parseStreamSpec(StringRef Str) {
|
||||
StreamSpec Result;
|
||||
if (Str.consumeInteger(0, Result.SI))
|
||||
return make_error<RawError>(raw_error_code::invalid_format,
|
||||
"Invalid Stream Specification");
|
||||
if (Str.consume_front(":")) {
|
||||
if (Str.consumeInteger(0, Result.Begin))
|
||||
return make_error<RawError>(raw_error_code::invalid_format,
|
||||
"Invalid Stream Specification");
|
||||
}
|
||||
if (Str.consume_front("@")) {
|
||||
if (Str.consumeInteger(0, Result.Size))
|
||||
return make_error<RawError>(raw_error_code::invalid_format,
|
||||
"Invalid Stream Specification");
|
||||
}
|
||||
|
||||
if (!Str.empty())
|
||||
return make_error<RawError>(raw_error_code::invalid_format,
|
||||
"Invalid Stream Specification");
|
||||
return Result;
|
||||
}
|
||||
|
||||
static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {
|
||||
SmallVector<StreamSpec, 2> Result;
|
||||
|
||||
for (auto &Str : opts::bytes::DumpStreamData) {
|
||||
auto ESS = parseStreamSpec(Str);
|
||||
if (!ESS) {
|
||||
P.formatLine("Error parsing stream spec {0}: {1}", Str,
|
||||
toString(ESS.takeError()));
|
||||
continue;
|
||||
}
|
||||
Result.push_back(*ESS);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void printHeader(LinePrinter &P, const Twine &S) {
|
||||
P.NewLine();
|
||||
P.formatLine("{0,=60}", S);
|
||||
P.formatLine("{0}", fmt_repeat('=', 60));
|
||||
}
|
||||
|
||||
BytesOutputStyle::BytesOutputStyle(PDBFile &File)
|
||||
: File(File), P(2, false, outs()) {}
|
||||
|
||||
Error BytesOutputStyle::dump() {
|
||||
|
||||
if (opts::bytes::DumpBlockRange.hasValue()) {
|
||||
auto &R = *opts::bytes::DumpBlockRange;
|
||||
uint32_t Max = R.Max.getValueOr(R.Min);
|
||||
|
||||
if (Max < R.Min)
|
||||
return make_error<StringError>(
|
||||
"Invalid block range specified. Max < Min",
|
||||
inconvertibleErrorCode());
|
||||
if (Max >= File.getBlockCount())
|
||||
return make_error<StringError>(
|
||||
"Invalid block range specified. Requested block out of bounds",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
dumpBlockRanges(R.Min, Max);
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::DumpByteRange.hasValue()) {
|
||||
auto &R = *opts::bytes::DumpByteRange;
|
||||
uint32_t Max = R.Max.getValueOr(File.getFileSize());
|
||||
|
||||
if (Max < R.Min)
|
||||
return make_error<StringError>("Invalid byte range specified. Max < Min",
|
||||
inconvertibleErrorCode());
|
||||
if (Max >= File.getFileSize())
|
||||
return make_error<StringError>(
|
||||
"Invalid byte range specified. Requested byte larger than file size",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
dumpByteRanges(R.Min, Max);
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::Fpm) {
|
||||
dumpFpm();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (!opts::bytes::DumpStreamData.empty()) {
|
||||
dumpStreamBytes();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::NameMap) {
|
||||
dumpNameMap();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::SectionContributions) {
|
||||
dumpSectionContributions();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::SectionMap) {
|
||||
dumpSectionMap();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::ModuleInfos) {
|
||||
dumpModuleInfos();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::FileInfo) {
|
||||
dumpFileInfo();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::TypeServerMap) {
|
||||
dumpTypeServerMap();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::ECData) {
|
||||
dumpECData();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (!opts::bytes::TypeIndex.empty()) {
|
||||
dumpTypeIndex(StreamTPI, opts::bytes::TypeIndex);
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (!opts::bytes::IdIndex.empty()) {
|
||||
dumpTypeIndex(StreamIPI, opts::bytes::IdIndex);
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::ModuleSyms) {
|
||||
dumpModuleSyms();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::ModuleC11) {
|
||||
dumpModuleC11();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
if (opts::bytes::ModuleC13) {
|
||||
dumpModuleC13();
|
||||
P.NewLine();
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpNameMap() {
|
||||
printHeader(P, "Named Stream Map");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &InfoS = Err(File.getPDBInfoStream());
|
||||
BinarySubstreamRef NS = InfoS.getNamedStreamsBuffer();
|
||||
auto Layout = File.getStreamLayout(StreamPDB);
|
||||
P.formatMsfStreamData("Named Stream Map", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
|
||||
printHeader(P, "MSF Blocks");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
for (uint32_t I = Min; I <= Max; ++I) {
|
||||
uint64_t Base = I;
|
||||
Base *= File.getBlockSize();
|
||||
|
||||
auto ExpectedData = File.getBlockData(I, File.getBlockSize());
|
||||
if (!ExpectedData) {
|
||||
P.formatLine("Could not get block {0}. Reason = {1}", I,
|
||||
toString(ExpectedData.takeError()));
|
||||
continue;
|
||||
}
|
||||
std::string Label = formatv("Block {0}", I).str();
|
||||
P.formatBinary(Label, *ExpectedData, Base, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpSectionContributions() {
|
||||
printHeader(P, "Section Contributions");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getSectionContributionData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("Section Contributions", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpSectionMap() {
|
||||
printHeader(P, "Section Map");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getSecMapSubstreamData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("Section Map", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpModuleInfos() {
|
||||
printHeader(P, "Module Infos");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getModiSubstreamData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("Module Infos", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpFileInfo() {
|
||||
printHeader(P, "File Info");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getFileInfoSubstreamData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("File Info", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpTypeServerMap() {
|
||||
printHeader(P, "Type Server Map");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getTypeServerMapSubstreamData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("Type Server Map", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpECData() {
|
||||
printHeader(P, "Edit and Continue Data");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto &DbiS = Err(File.getPDBDbiStream());
|
||||
BinarySubstreamRef NS = DbiS.getECSubstreamData();
|
||||
auto Layout = File.getStreamLayout(StreamDBI);
|
||||
P.formatMsfStreamData("Edit and Continue Data", File, Layout, NS);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpTypeIndex(uint32_t StreamIdx,
|
||||
ArrayRef<uint32_t> Indices) {
|
||||
assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
|
||||
assert(!Indices.empty());
|
||||
|
||||
bool IsTpi = (StreamIdx == StreamTPI);
|
||||
|
||||
StringRef Label = IsTpi ? "Type (TPI) Records" : "Index (IPI) Records";
|
||||
printHeader(P, Label);
|
||||
auto &Stream = Err(IsTpi ? File.getPDBTpiStream() : File.getPDBIpiStream());
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
auto Substream = Stream.getTypeRecordsSubstream();
|
||||
auto &Types = Err(initializeTypes(StreamIdx));
|
||||
auto Layout = File.getStreamLayout(StreamIdx);
|
||||
for (const auto &Id : Indices) {
|
||||
TypeIndex TI(Id);
|
||||
if (TI.toArrayIndex() >= Types.capacity()) {
|
||||
P.formatLine("Error: TypeIndex {0} does not exist", TI);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto Type = Types.getType(TI);
|
||||
uint32_t Offset = Types.getOffsetOfType(TI);
|
||||
auto OneType = Substream.slice(Offset, Type.length());
|
||||
P.formatMsfStreamData(formatv("Type {0}", TI).str(), File, Layout, OneType);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CallbackT>
|
||||
static void iterateOneModule(PDBFile &File, LinePrinter &P,
|
||||
const DbiModuleList &Modules, uint32_t I,
|
||||
uint32_t Digits, uint32_t IndentLevel,
|
||||
CallbackT Callback) {
|
||||
if (I >= Modules.getModuleCount()) {
|
||||
P.formatLine("Mod {0:4} | Invalid module index ",
|
||||
fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)));
|
||||
return;
|
||||
}
|
||||
|
||||
auto Modi = Modules.getModuleDescriptor(I);
|
||||
P.formatLine("Mod {0:4} | `{1}`: ",
|
||||
fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)),
|
||||
Modi.getModuleName());
|
||||
|
||||
uint16_t ModiStream = Modi.getModuleStreamIndex();
|
||||
AutoIndent Indent2(P, IndentLevel);
|
||||
if (ModiStream == kInvalidStreamIndex)
|
||||
return;
|
||||
|
||||
auto ModStreamData = MappedBlockStream::createIndexedStream(
|
||||
File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
|
||||
File.getAllocator());
|
||||
ModuleDebugStreamRef ModStream(Modi, std::move(ModStreamData));
|
||||
if (auto EC = ModStream.reload()) {
|
||||
P.formatLine("Could not parse debug information.");
|
||||
return;
|
||||
}
|
||||
auto Layout = File.getStreamLayout(ModiStream);
|
||||
Callback(I, ModStream, Layout);
|
||||
}
|
||||
|
||||
template <typename CallbackT>
|
||||
static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
|
||||
CallbackT Callback) {
|
||||
AutoIndent Indent(P);
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.formatLine("DBI Stream not present");
|
||||
return;
|
||||
}
|
||||
|
||||
ExitOnError Err("Unexpected error processing modules");
|
||||
|
||||
auto &Stream = Err(File.getPDBDbiStream());
|
||||
|
||||
const DbiModuleList &Modules = Stream.modules();
|
||||
|
||||
if (opts::bytes::ModuleIndex.getNumOccurrences() > 0) {
|
||||
iterateOneModule(File, P, Modules, opts::bytes::ModuleIndex, 1, IndentLevel,
|
||||
Callback);
|
||||
} else {
|
||||
uint32_t Count = Modules.getModuleCount();
|
||||
uint32_t Digits = NumDigits(Count);
|
||||
for (uint32_t I = 0; I < Count; ++I) {
|
||||
iterateOneModule(File, P, Modules, I, Digits, IndentLevel, Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpModuleSyms() {
|
||||
printHeader(P, "Module Symbols");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
iterateModules(File, P, 2,
|
||||
[this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
|
||||
const MSFStreamLayout &Layout) {
|
||||
auto Symbols = Stream.getSymbolsSubstream();
|
||||
P.formatMsfStreamData("Symbols", File, Layout, Symbols);
|
||||
});
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpModuleC11() {
|
||||
printHeader(P, "C11 Debug Chunks");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
iterateModules(File, P, 2,
|
||||
[this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
|
||||
const MSFStreamLayout &Layout) {
|
||||
auto Chunks = Stream.getC11LinesSubstream();
|
||||
P.formatMsfStreamData("C11 Debug Chunks", File, Layout,
|
||||
Chunks);
|
||||
});
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpModuleC13() {
|
||||
printHeader(P, "Debug Chunks");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
iterateModules(
|
||||
File, P, 2,
|
||||
[this](uint32_t Modi, const ModuleDebugStreamRef &Stream,
|
||||
const MSFStreamLayout &Layout) {
|
||||
auto Chunks = Stream.getC13LinesSubstream();
|
||||
if (opts::bytes::SplitChunks) {
|
||||
for (const auto &SS : Stream.subsections()) {
|
||||
BinarySubstreamRef ThisChunk;
|
||||
std::tie(ThisChunk, Chunks) = Chunks.split(SS.getRecordLength());
|
||||
P.formatMsfStreamData(formatChunkKind(SS.kind()), File, Layout,
|
||||
ThisChunk);
|
||||
}
|
||||
} else {
|
||||
P.formatMsfStreamData("Debug Chunks", File, Layout, Chunks);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
|
||||
printHeader(P, "MSF Bytes");
|
||||
|
||||
AutoIndent Indent(P);
|
||||
|
||||
BinaryStreamReader Reader(File.getMsfBuffer());
|
||||
ArrayRef<uint8_t> Data;
|
||||
consumeError(Reader.skip(Min));
|
||||
uint32_t Size = Max - Min + 1;
|
||||
auto EC = Reader.readBytes(Data, Size);
|
||||
assert(!EC);
|
||||
consumeError(std::move(EC));
|
||||
P.formatBinary("Bytes", Data, Min);
|
||||
}
|
||||
|
||||
Expected<codeview::LazyRandomTypeCollection &>
|
||||
BytesOutputStyle::initializeTypes(uint32_t StreamIdx) {
|
||||
auto &TypeCollection = (StreamIdx == StreamTPI) ? TpiTypes : IpiTypes;
|
||||
if (TypeCollection)
|
||||
return *TypeCollection;
|
||||
|
||||
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
|
||||
: File.getPDBIpiStream();
|
||||
if (!Tpi)
|
||||
return Tpi.takeError();
|
||||
|
||||
auto &Types = Tpi->typeArray();
|
||||
uint32_t Count = Tpi->getNumTypeRecords();
|
||||
auto Offsets = Tpi->getTypeIndexOffsets();
|
||||
TypeCollection =
|
||||
llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
|
||||
|
||||
return *TypeCollection;
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpFpm() {
|
||||
printHeader(P, "Free Page Map");
|
||||
|
||||
msf::MSFStreamLayout FpmLayout = File.getFpmStreamLayout();
|
||||
P.formatMsfStreamBlocks(File, FpmLayout);
|
||||
}
|
||||
|
||||
void BytesOutputStyle::dumpStreamBytes() {
|
||||
if (StreamPurposes.empty())
|
||||
discoverStreamPurposes(File, StreamPurposes);
|
||||
|
||||
printHeader(P, "Stream Data");
|
||||
ExitOnError Err("Unexpected error reading stream data");
|
||||
|
||||
auto Specs = parseStreamSpecs(P);
|
||||
|
||||
for (const auto &Spec : Specs) {
|
||||
AutoIndent Indent(P);
|
||||
if (Spec.SI >= StreamPurposes.size()) {
|
||||
P.formatLine("Stream {0}: Not present", Spec.SI);
|
||||
continue;
|
||||
}
|
||||
P.formatMsfStreamData("Data", File, Spec.SI,
|
||||
StreamPurposes[Spec.SI].getShortName(), Spec.Begin,
|
||||
Spec.Size);
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
//===- BytesOutputStyle.h ------------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_BYTESOUTPUTSTYLE_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_BYTESOUTPUTSTYLE_H
|
||||
|
||||
#include "LinePrinter.h"
|
||||
#include "OutputStyle.h"
|
||||
#include "StreamUtil.h"
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace codeview {
|
||||
class LazyRandomTypeCollection;
|
||||
}
|
||||
|
||||
namespace pdb {
|
||||
|
||||
class PDBFile;
|
||||
|
||||
class BytesOutputStyle : public OutputStyle {
|
||||
public:
|
||||
BytesOutputStyle(PDBFile &File);
|
||||
|
||||
Error dump() override;
|
||||
|
||||
private:
|
||||
void dumpNameMap();
|
||||
void dumpBlockRanges(uint32_t Min, uint32_t Max);
|
||||
void dumpByteRanges(uint32_t Min, uint32_t Max);
|
||||
void dumpFpm();
|
||||
void dumpStreamBytes();
|
||||
|
||||
void dumpSectionContributions();
|
||||
void dumpSectionMap();
|
||||
void dumpModuleInfos();
|
||||
void dumpFileInfo();
|
||||
void dumpTypeServerMap();
|
||||
void dumpECData();
|
||||
|
||||
void dumpModuleSyms();
|
||||
void dumpModuleC11();
|
||||
void dumpModuleC13();
|
||||
|
||||
void dumpTypeIndex(uint32_t StreamIdx, ArrayRef<uint32_t> Indices);
|
||||
|
||||
Expected<codeview::LazyRandomTypeCollection &>
|
||||
initializeTypes(uint32_t StreamIdx);
|
||||
|
||||
std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
|
||||
std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
|
||||
|
||||
PDBFile &File;
|
||||
LinePrinter P;
|
||||
ExitOnError Err;
|
||||
SmallVector<StreamInfo, 8> StreamPurposes;
|
||||
};
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
36
external/llvm/tools/llvm-pdbutil/CMakeLists.txt
vendored
36
external/llvm/tools/llvm-pdbutil/CMakeLists.txt
vendored
@ -1,36 +0,0 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
BinaryFormat
|
||||
DebugInfoCodeView
|
||||
DebugInfoMSF
|
||||
DebugInfoPDB
|
||||
Object
|
||||
ObjectYAML
|
||||
Support
|
||||
)
|
||||
|
||||
add_llvm_tool(llvm-pdbutil
|
||||
Analyze.cpp
|
||||
BytesOutputStyle.cpp
|
||||
Diff.cpp
|
||||
DiffPrinter.cpp
|
||||
DumpOutputStyle.cpp
|
||||
InputFile.cpp
|
||||
llvm-pdbutil.cpp
|
||||
FormatUtil.cpp
|
||||
LinePrinter.cpp
|
||||
MinimalSymbolDumper.cpp
|
||||
MinimalTypeDumper.cpp
|
||||
PdbYaml.cpp
|
||||
PrettyBuiltinDumper.cpp
|
||||
PrettyClassDefinitionDumper.cpp
|
||||
PrettyClassLayoutGraphicalDumper.cpp
|
||||
PrettyCompilandDumper.cpp
|
||||
PrettyEnumDumper.cpp
|
||||
PrettyExternalSymbolDumper.cpp
|
||||
PrettyFunctionDumper.cpp
|
||||
PrettyTypeDumper.cpp
|
||||
PrettyTypedefDumper.cpp
|
||||
PrettyVariableDumper.cpp
|
||||
StreamUtil.cpp
|
||||
YAMLOutputStyle.cpp
|
||||
)
|
644
external/llvm/tools/llvm-pdbutil/Diff.cpp
vendored
644
external/llvm/tools/llvm-pdbutil/Diff.cpp
vendored
File diff suppressed because it is too large
Load Diff
45
external/llvm/tools/llvm-pdbutil/Diff.h
vendored
45
external/llvm/tools/llvm-pdbutil/Diff.h
vendored
@ -1,45 +0,0 @@
|
||||
//===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
|
||||
|
||||
#include "OutputStyle.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
class PDBFile;
|
||||
class DiffStyle : public OutputStyle {
|
||||
public:
|
||||
explicit DiffStyle(PDBFile &File1, PDBFile &File2);
|
||||
|
||||
Error dump() override;
|
||||
|
||||
private:
|
||||
Error diffSuperBlock();
|
||||
Error diffStreamDirectory();
|
||||
Error diffStringTable();
|
||||
Error diffFreePageMap();
|
||||
Error diffInfoStream();
|
||||
Error diffDbiStream();
|
||||
Error diffSectionContribs();
|
||||
Error diffSectionMap();
|
||||
Error diffFpoStream();
|
||||
Error diffTpiStream(int Index);
|
||||
Error diffModuleInfoStream(int Index);
|
||||
Error diffPublics();
|
||||
Error diffGlobals();
|
||||
|
||||
PDBFile &File1;
|
||||
PDBFile &File2;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
147
external/llvm/tools/llvm-pdbutil/DiffPrinter.cpp
vendored
147
external/llvm/tools/llvm-pdbutil/DiffPrinter.cpp
vendored
@ -1,147 +0,0 @@
|
||||
|
||||
#include "DiffPrinter.h"
|
||||
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
namespace {
|
||||
struct Colorize {
|
||||
Colorize(raw_ostream &OS, DiffResult Result) : OS(OS) {
|
||||
if (!OS.has_colors())
|
||||
return;
|
||||
switch (Result) {
|
||||
case DiffResult::IDENTICAL:
|
||||
OS.changeColor(raw_ostream::Colors::GREEN, false);
|
||||
break;
|
||||
case DiffResult::EQUIVALENT:
|
||||
OS.changeColor(raw_ostream::Colors::YELLOW, true);
|
||||
break;
|
||||
default:
|
||||
OS.changeColor(raw_ostream::Colors::RED, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~Colorize() {
|
||||
if (OS.has_colors())
|
||||
OS.resetColor();
|
||||
}
|
||||
|
||||
raw_ostream &OS;
|
||||
};
|
||||
}
|
||||
|
||||
DiffPrinter::DiffPrinter(uint32_t Indent, StringRef Header,
|
||||
uint32_t PropertyWidth, uint32_t FieldWidth,
|
||||
bool Result, bool Fields, raw_ostream &Stream)
|
||||
: PrintResult(Result), PrintValues(Fields), Indent(Indent),
|
||||
PropertyWidth(PropertyWidth), FieldWidth(FieldWidth), OS(Stream) {
|
||||
printHeaderRow();
|
||||
printFullRow(Header);
|
||||
}
|
||||
|
||||
DiffPrinter::~DiffPrinter() {}
|
||||
|
||||
uint32_t DiffPrinter::tableWidth() const {
|
||||
// `|`
|
||||
uint32_t W = 1;
|
||||
|
||||
// `<width>|`
|
||||
W += PropertyWidth + 1;
|
||||
|
||||
if (PrintResult) {
|
||||
// ` I |`
|
||||
W += 4;
|
||||
}
|
||||
|
||||
if (PrintValues) {
|
||||
// `<width>|<width>|`
|
||||
W += 2 * (FieldWidth + 1);
|
||||
}
|
||||
return W;
|
||||
}
|
||||
|
||||
void DiffPrinter::printFullRow(StringRef Text) {
|
||||
newLine();
|
||||
printValue(Text, DiffResult::UNSPECIFIED, AlignStyle::Center,
|
||||
tableWidth() - 2, true);
|
||||
printSeparatorRow();
|
||||
}
|
||||
|
||||
void DiffPrinter::printSeparatorRow() {
|
||||
newLine();
|
||||
OS << formatv("{0}", fmt_repeat('-', PropertyWidth));
|
||||
if (PrintResult) {
|
||||
OS << '+';
|
||||
OS << formatv("{0}", fmt_repeat('-', 3));
|
||||
}
|
||||
if (PrintValues) {
|
||||
OS << '+';
|
||||
OS << formatv("{0}", fmt_repeat('-', FieldWidth));
|
||||
OS << '+';
|
||||
OS << formatv("{0}", fmt_repeat('-', FieldWidth));
|
||||
}
|
||||
OS << '|';
|
||||
}
|
||||
|
||||
void DiffPrinter::printHeaderRow() {
|
||||
newLine('-');
|
||||
OS << formatv("{0}", fmt_repeat('-', tableWidth() - 1));
|
||||
}
|
||||
|
||||
void DiffPrinter::newLine(char InitialChar) {
|
||||
OS << "\n";
|
||||
OS.indent(Indent) << InitialChar;
|
||||
}
|
||||
|
||||
void DiffPrinter::printExplicit(StringRef Property, DiffResult C,
|
||||
StringRef Left, StringRef Right) {
|
||||
newLine();
|
||||
printValue(Property, DiffResult::UNSPECIFIED, AlignStyle::Right,
|
||||
PropertyWidth, true);
|
||||
printResult(C);
|
||||
printValue(Left, C, AlignStyle::Center, FieldWidth, false);
|
||||
printValue(Right, C, AlignStyle::Center, FieldWidth, false);
|
||||
printSeparatorRow();
|
||||
}
|
||||
|
||||
void DiffPrinter::printResult(DiffResult Result) {
|
||||
if (!PrintResult)
|
||||
return;
|
||||
switch (Result) {
|
||||
case DiffResult::DIFFERENT:
|
||||
printValue("D", Result, AlignStyle::Center, 3, true);
|
||||
break;
|
||||
case DiffResult::EQUIVALENT:
|
||||
printValue("E", Result, AlignStyle::Center, 3, true);
|
||||
break;
|
||||
case DiffResult::IDENTICAL:
|
||||
printValue("I", Result, AlignStyle::Center, 3, true);
|
||||
break;
|
||||
case DiffResult::UNSPECIFIED:
|
||||
printValue(" ", Result, AlignStyle::Center, 3, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiffPrinter::printValue(StringRef Value, DiffResult C, AlignStyle Style,
|
||||
uint32_t Width, bool Force) {
|
||||
if (!Force && !PrintValues)
|
||||
return;
|
||||
|
||||
if (Style == AlignStyle::Right)
|
||||
--Width;
|
||||
|
||||
std::string FormattedItem =
|
||||
formatv("{0}", fmt_align(Value, Style, Width)).str();
|
||||
if (C != DiffResult::UNSPECIFIED) {
|
||||
Colorize Color(OS, C);
|
||||
OS << FormattedItem;
|
||||
} else
|
||||
OS << FormattedItem;
|
||||
if (Style == AlignStyle::Right)
|
||||
OS << ' ';
|
||||
OS << '|';
|
||||
}
|
172
external/llvm/tools/llvm-pdbutil/DiffPrinter.h
vendored
172
external/llvm/tools/llvm-pdbutil/DiffPrinter.h
vendored
@ -1,172 +0,0 @@
|
||||
//===- DiffPrinter.h ------------------------------------------ *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <list>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace std {
|
||||
template <> struct hash<llvm::pdb::PdbRaw_FeatureSig> {
|
||||
typedef llvm::pdb::PdbRaw_FeatureSig argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type Item) const {
|
||||
return std::hash<uint32_t>{}(uint32_t(Item));
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class PDBFile;
|
||||
|
||||
enum class DiffResult { UNSPECIFIED, IDENTICAL, EQUIVALENT, DIFFERENT };
|
||||
|
||||
struct IdenticalDiffProvider {
|
||||
template <typename T, typename U>
|
||||
DiffResult compare(const T &Left, const U &Right) {
|
||||
return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::DIFFERENT;
|
||||
}
|
||||
|
||||
template <typename T> std::string format(const T &Item, bool Right) {
|
||||
return formatv("{0}", Item).str();
|
||||
}
|
||||
};
|
||||
|
||||
struct EquivalentDiffProvider {
|
||||
template <typename T, typename U>
|
||||
DiffResult compare(const T &Left, const U &Right) {
|
||||
return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::EQUIVALENT;
|
||||
}
|
||||
|
||||
template <typename T> std::string format(const T &Item, bool Right) {
|
||||
return formatv("{0}", Item).str();
|
||||
}
|
||||
};
|
||||
|
||||
class DiffPrinter {
|
||||
public:
|
||||
DiffPrinter(uint32_t Indent, StringRef Header, uint32_t PropertyWidth,
|
||||
uint32_t FieldWidth, bool Result, bool Values,
|
||||
raw_ostream &Stream);
|
||||
~DiffPrinter();
|
||||
|
||||
template <typename T, typename U> struct Identical {};
|
||||
|
||||
template <typename Provider = IdenticalDiffProvider, typename T, typename U>
|
||||
void print(StringRef Property, const T &Left, const U &Right,
|
||||
Provider P = Provider()) {
|
||||
std::string L = P.format(Left, false);
|
||||
std::string R = P.format(Right, true);
|
||||
|
||||
DiffResult Result = P.compare(Left, Right);
|
||||
printExplicit(Property, Result, L, R);
|
||||
}
|
||||
|
||||
void printExplicit(StringRef Property, DiffResult C, StringRef Left,
|
||||
StringRef Right);
|
||||
|
||||
template <typename T, typename U>
|
||||
void printExplicit(StringRef Property, DiffResult C, const T &Left,
|
||||
const U &Right) {
|
||||
std::string L = formatv("{0}", Left).str();
|
||||
std::string R = formatv("{0}", Right).str();
|
||||
printExplicit(Property, C, StringRef(L), StringRef(R));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void diffUnorderedArray(StringRef Property, ArrayRef<T> Left,
|
||||
ArrayRef<U> Right) {
|
||||
std::unordered_set<T> LS(Left.begin(), Left.end());
|
||||
std::unordered_set<U> RS(Right.begin(), Right.end());
|
||||
std::string Count1 = formatv("{0} element(s)", Left.size());
|
||||
std::string Count2 = formatv("{0} element(s)", Right.size());
|
||||
print(std::string(Property) + "s (set)", Count1, Count2);
|
||||
for (const auto &L : LS) {
|
||||
auto Iter = RS.find(L);
|
||||
std::string Text = formatv("{0}", L).str();
|
||||
if (Iter == RS.end()) {
|
||||
print(Property, Text, "(not present)");
|
||||
continue;
|
||||
}
|
||||
print(Property, Text, Text);
|
||||
RS.erase(Iter);
|
||||
}
|
||||
for (const auto &R : RS) {
|
||||
auto Iter = LS.find(R);
|
||||
std::string Text = formatv("{0}", R).str();
|
||||
if (Iter == LS.end()) {
|
||||
print(Property, "(not present)", Text);
|
||||
continue;
|
||||
}
|
||||
print(Property, Text, Text);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ValueProvider = IdenticalDiffProvider, typename T,
|
||||
typename U>
|
||||
void diffUnorderedMap(StringRef Property, const StringMap<T> &Left,
|
||||
const StringMap<U> &Right,
|
||||
ValueProvider P = ValueProvider()) {
|
||||
StringMap<U> RightCopy(Right);
|
||||
|
||||
std::string Count1 = formatv("{0} element(s)", Left.size());
|
||||
std::string Count2 = formatv("{0} element(s)", Right.size());
|
||||
print(std::string(Property) + "s (map)", Count1, Count2);
|
||||
|
||||
for (const auto &L : Left) {
|
||||
auto Iter = RightCopy.find(L.getKey());
|
||||
if (Iter == RightCopy.end()) {
|
||||
printExplicit(L.getKey(), DiffResult::DIFFERENT, L.getValue(),
|
||||
"(not present)");
|
||||
continue;
|
||||
}
|
||||
|
||||
print(L.getKey(), L.getValue(), Iter->getValue(), P);
|
||||
RightCopy.erase(Iter);
|
||||
}
|
||||
|
||||
for (const auto &R : RightCopy) {
|
||||
printExplicit(R.getKey(), DiffResult::DIFFERENT, "(not present)",
|
||||
R.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void printFullRow(StringRef Text);
|
||||
|
||||
private:
|
||||
uint32_t tableWidth() const;
|
||||
|
||||
void printHeaderRow();
|
||||
void printSeparatorRow();
|
||||
void newLine(char InitialChar = '|');
|
||||
void printValue(StringRef Value, DiffResult C, AlignStyle Style,
|
||||
uint32_t Width, bool Force);
|
||||
void printResult(DiffResult Result);
|
||||
|
||||
bool PrintResult;
|
||||
bool PrintValues;
|
||||
uint32_t Indent;
|
||||
uint32_t PropertyWidth;
|
||||
uint32_t FieldWidth;
|
||||
raw_ostream &OS;
|
||||
};
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
1542
external/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
vendored
1542
external/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
vendored
File diff suppressed because it is too large
Load Diff
104
external/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
vendored
104
external/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
vendored
@ -1,104 +0,0 @@
|
||||
//===- DumpOutputStyle.h -------------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_DUMPOUTPUTSTYLE_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_DUMPOUTPUTSTYLE_H
|
||||
|
||||
#include "LinePrinter.h"
|
||||
#include "OutputStyle.h"
|
||||
#include "StreamUtil.h"
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class BitVector;
|
||||
|
||||
namespace codeview {
|
||||
class LazyRandomTypeCollection;
|
||||
}
|
||||
|
||||
namespace object {
|
||||
class COFFObjectFile;
|
||||
}
|
||||
|
||||
namespace pdb {
|
||||
class GSIHashTable;
|
||||
class InputFile;
|
||||
|
||||
struct StatCollection {
|
||||
struct Stat {
|
||||
Stat() {}
|
||||
Stat(uint32_t Count, uint32_t Size) : Count(Count), Size(Size) {}
|
||||
uint32_t Count = 0;
|
||||
uint32_t Size = 0;
|
||||
|
||||
void update(uint32_t RecordSize) {
|
||||
++Count;
|
||||
Size += RecordSize;
|
||||
}
|
||||
};
|
||||
|
||||
void update(uint32_t Kind, uint32_t RecordSize) {
|
||||
Totals.update(RecordSize);
|
||||
auto Iter = Individual.try_emplace(Kind, 1, RecordSize);
|
||||
if (!Iter.second)
|
||||
Iter.first->second.update(RecordSize);
|
||||
}
|
||||
Stat Totals;
|
||||
DenseMap<uint32_t, Stat> Individual;
|
||||
};
|
||||
|
||||
class DumpOutputStyle : public OutputStyle {
|
||||
|
||||
public:
|
||||
DumpOutputStyle(InputFile &File);
|
||||
|
||||
Error dump() override;
|
||||
|
||||
private:
|
||||
PDBFile &getPdb();
|
||||
object::COFFObjectFile &getObj();
|
||||
|
||||
Error dumpFileSummary();
|
||||
Error dumpStreamSummary();
|
||||
Error dumpSymbolStats();
|
||||
Error dumpUdtStats();
|
||||
Error dumpStringTable();
|
||||
Error dumpLines();
|
||||
Error dumpInlineeLines();
|
||||
Error dumpXmi();
|
||||
Error dumpXme();
|
||||
Error dumpTpiStream(uint32_t StreamIdx);
|
||||
Error dumpTypesFromObjectFile();
|
||||
Error dumpModules();
|
||||
Error dumpModuleFiles();
|
||||
Error dumpModuleSymsForPdb();
|
||||
Error dumpModuleSymsForObj();
|
||||
Error dumpGlobals();
|
||||
Error dumpPublics();
|
||||
Error dumpSymbolsFromGSI(const GSIHashTable &Table, bool HashExtras);
|
||||
Error dumpSectionHeaders();
|
||||
Error dumpSectionContribs();
|
||||
Error dumpSectionMap();
|
||||
|
||||
void dumpSectionHeaders(StringRef Label, DbgHeaderType Type);
|
||||
|
||||
InputFile &File;
|
||||
LinePrinter P;
|
||||
SmallVector<StreamInfo, 32> StreamPurposes;
|
||||
};
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
258
external/llvm/tools/llvm-pdbutil/FormatUtil.cpp
vendored
258
external/llvm/tools/llvm-pdbutil/FormatUtil.cpp
vendored
@ -1,258 +0,0 @@
|
||||
//===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "FormatUtil.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
std::string llvm::pdb::truncateStringBack(StringRef S, uint32_t MaxLen) {
|
||||
if (MaxLen == 0 || S.size() <= MaxLen || S.size() <= 3)
|
||||
return S;
|
||||
|
||||
assert(MaxLen >= 3);
|
||||
uint32_t FinalLen = std::min<size_t>(S.size(), MaxLen - 3);
|
||||
S = S.take_front(FinalLen);
|
||||
return std::string(S) + std::string("...");
|
||||
}
|
||||
|
||||
std::string llvm::pdb::truncateStringMiddle(StringRef S, uint32_t MaxLen) {
|
||||
if (MaxLen == 0 || S.size() <= MaxLen || S.size() <= 3)
|
||||
return S;
|
||||
|
||||
assert(MaxLen >= 3);
|
||||
uint32_t FinalLen = std::min<size_t>(S.size(), MaxLen - 3);
|
||||
StringRef Front = S.take_front(FinalLen / 2);
|
||||
StringRef Back = S.take_back(Front.size());
|
||||
return std::string(Front) + std::string("...") + std::string(Back);
|
||||
}
|
||||
|
||||
std::string llvm::pdb::truncateStringFront(StringRef S, uint32_t MaxLen) {
|
||||
if (MaxLen == 0 || S.size() <= MaxLen || S.size() <= 3)
|
||||
return S;
|
||||
|
||||
assert(MaxLen >= 3);
|
||||
S = S.take_back(MaxLen - 3);
|
||||
return std::string("...") + std::string(S);
|
||||
}
|
||||
|
||||
std::string llvm::pdb::truncateQuotedNameFront(StringRef Label, StringRef Name,
|
||||
uint32_t MaxLen) {
|
||||
uint32_t RequiredExtraChars = Label.size() + 1 + 2;
|
||||
if (MaxLen == 0 || RequiredExtraChars + Name.size() <= MaxLen)
|
||||
return formatv("{0} \"{1}\"", Label, Name).str();
|
||||
|
||||
assert(MaxLen >= RequiredExtraChars);
|
||||
std::string TN = truncateStringFront(Name, MaxLen - RequiredExtraChars);
|
||||
return formatv("{0} \"{1}\"", Label, TN).str();
|
||||
}
|
||||
|
||||
std::string llvm::pdb::truncateQuotedNameBack(StringRef Label, StringRef Name,
|
||||
uint32_t MaxLen) {
|
||||
uint32_t RequiredExtraChars = Label.size() + 1 + 2;
|
||||
if (MaxLen == 0 || RequiredExtraChars + Name.size() <= MaxLen)
|
||||
return formatv("{0} \"{1}\"", Label, Name).str();
|
||||
|
||||
assert(MaxLen >= RequiredExtraChars);
|
||||
std::string TN = truncateStringBack(Name, MaxLen - RequiredExtraChars);
|
||||
return formatv("{0} \"{1}\"", Label, TN).str();
|
||||
}
|
||||
|
||||
std::string llvm::pdb::typesetItemList(ArrayRef<std::string> Opts,
|
||||
uint32_t IndentLevel, uint32_t GroupSize,
|
||||
StringRef Sep) {
|
||||
std::string Result;
|
||||
while (!Opts.empty()) {
|
||||
ArrayRef<std::string> ThisGroup;
|
||||
ThisGroup = Opts.take_front(GroupSize);
|
||||
Opts = Opts.drop_front(ThisGroup.size());
|
||||
Result += join(ThisGroup, Sep);
|
||||
if (!Opts.empty()) {
|
||||
Result += Sep;
|
||||
Result += "\n";
|
||||
Result += formatv("{0}", fmt_repeat(' ', IndentLevel));
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string llvm::pdb::typesetStringList(uint32_t IndentLevel,
|
||||
ArrayRef<StringRef> Strings) {
|
||||
std::string Result = "[";
|
||||
for (const auto &S : Strings) {
|
||||
Result += formatv("\n{0}{1}", fmt_repeat(' ', IndentLevel), S);
|
||||
}
|
||||
Result += "]";
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string llvm::pdb::formatChunkKind(DebugSubsectionKind Kind,
|
||||
bool Friendly) {
|
||||
if (Friendly) {
|
||||
switch (Kind) {
|
||||
RETURN_CASE(DebugSubsectionKind, None, "none");
|
||||
RETURN_CASE(DebugSubsectionKind, Symbols, "symbols");
|
||||
RETURN_CASE(DebugSubsectionKind, Lines, "lines");
|
||||
RETURN_CASE(DebugSubsectionKind, StringTable, "strings");
|
||||
RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums");
|
||||
RETURN_CASE(DebugSubsectionKind, FrameData, "frames");
|
||||
RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines");
|
||||
RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi");
|
||||
RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme");
|
||||
RETURN_CASE(DebugSubsectionKind, ILLines, "il lines");
|
||||
RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map");
|
||||
RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map");
|
||||
RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
|
||||
"merged assembly input");
|
||||
RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva");
|
||||
}
|
||||
} else {
|
||||
switch (Kind) {
|
||||
RETURN_CASE(DebugSubsectionKind, None, "none");
|
||||
RETURN_CASE(DebugSubsectionKind, Symbols, "DEBUG_S_SYMBOLS");
|
||||
RETURN_CASE(DebugSubsectionKind, Lines, "DEBUG_S_LINES");
|
||||
RETURN_CASE(DebugSubsectionKind, StringTable, "DEBUG_S_STRINGTABLE");
|
||||
RETURN_CASE(DebugSubsectionKind, FileChecksums, "DEBUG_S_FILECHKSMS");
|
||||
RETURN_CASE(DebugSubsectionKind, FrameData, "DEBUG_S_FRAMEDATA");
|
||||
RETURN_CASE(DebugSubsectionKind, InlineeLines, "DEBUG_S_INLINEELINES");
|
||||
RETURN_CASE(DebugSubsectionKind, CrossScopeImports,
|
||||
"DEBUG_S_CROSSSCOPEIMPORTS");
|
||||
RETURN_CASE(DebugSubsectionKind, CrossScopeExports,
|
||||
"DEBUG_S_CROSSSCOPEEXPORTS");
|
||||
RETURN_CASE(DebugSubsectionKind, ILLines, "DEBUG_S_IL_LINES");
|
||||
RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap,
|
||||
"DEBUG_S_FUNC_MDTOKEN_MAP");
|
||||
RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap,
|
||||
"DEBUG_S_TYPE_MDTOKEN_MAP");
|
||||
RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
|
||||
"DEBUG_S_MERGED_ASSEMBLYINPUT");
|
||||
RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA,
|
||||
"DEBUG_S_COFF_SYMBOL_RVA");
|
||||
}
|
||||
}
|
||||
return formatUnknownEnum(Kind);
|
||||
}
|
||||
|
||||
std::string llvm::pdb::formatSymbolKind(SymbolKind K) {
|
||||
switch (uint32_t(K)) {
|
||||
#define SYMBOL_RECORD(EnumName, value, name) \
|
||||
case EnumName: \
|
||||
return #EnumName;
|
||||
#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
||||
}
|
||||
return formatUnknownEnum(K);
|
||||
}
|
||||
|
||||
StringRef llvm::pdb::formatTypeLeafKind(TypeLeafKind K) {
|
||||
switch (K) {
|
||||
#define TYPE_RECORD(EnumName, value, name) \
|
||||
case EnumName: \
|
||||
return #EnumName;
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
default:
|
||||
llvm_unreachable("Unknown type leaf kind!");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) {
|
||||
return formatv("{0:4}:{1:4}", Segment, Offset);
|
||||
}
|
||||
|
||||
#define PUSH_CHARACTERISTIC_FLAG(Enum, TheOpt, Value, Style, Descriptive) \
|
||||
PUSH_FLAG(Enum, TheOpt, Value, \
|
||||
((Style == CharacteristicStyle::HeaderDefinition) ? #TheOpt \
|
||||
: Descriptive))
|
||||
|
||||
#define PUSH_MASKED_CHARACTERISTIC_FLAG(Enum, Mask, TheOpt, Value, Style, \
|
||||
Descriptive) \
|
||||
PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, \
|
||||
((Style == CharacteristicStyle::HeaderDefinition) \
|
||||
? #TheOpt \
|
||||
: Descriptive))
|
||||
|
||||
std::string llvm::pdb::formatSectionCharacteristics(uint32_t IndentLevel,
|
||||
uint32_t C,
|
||||
uint32_t FlagsPerLine,
|
||||
StringRef Separator,
|
||||
CharacteristicStyle Style) {
|
||||
using SC = COFF::SectionCharacteristics;
|
||||
std::vector<std::string> Opts;
|
||||
if (C == COFF::SC_Invalid)
|
||||
return "invalid";
|
||||
if (C == 0)
|
||||
return "none";
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, Style, "noload");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, Style, "no padding");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_CODE, C, Style, "code");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C, Style,
|
||||
"initialized data");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C, Style,
|
||||
"uninitialized data");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, Style, "other");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_INFO, C, Style, "info");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, Style, "remove");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, Style, "comdat");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_GPREL, C, Style, "gp rel");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, Style, "purgeable");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, Style, "16-bit");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, Style, "locked");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, Style, "preload");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
|
||||
Style, "1 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
|
||||
Style, "2 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
|
||||
Style, "4 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
|
||||
Style, "8 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
|
||||
Style, "16 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
|
||||
Style, "32 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
|
||||
Style, "64 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
|
||||
Style, "128 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
|
||||
Style, "256 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
|
||||
Style, "512 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
|
||||
Style, "1024 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
|
||||
Style, "2048 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
|
||||
Style, "4096 byte align");
|
||||
PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
|
||||
Style, "8192 byte align");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, Style,
|
||||
"noreloc overflow");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, Style,
|
||||
"discardable");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, Style,
|
||||
"not cached");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, Style, "not paged");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, Style, "shared");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, Style,
|
||||
"execute permissions");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_READ, C, Style,
|
||||
"read permissions");
|
||||
PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, Style,
|
||||
"write permissions");
|
||||
return typesetItemList(Opts, IndentLevel, FlagsPerLine, Separator);
|
||||
}
|
143
external/llvm/tools/llvm-pdbutil/FormatUtil.h
vendored
143
external/llvm/tools/llvm-pdbutil/FormatUtil.h
vendored
@ -1,143 +0,0 @@
|
||||
//===- FormatUtil.h ------------------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBUTIL_FORMAT_UTIL_H
|
||||
#define LLVM_TOOLS_LLVMPDBUTIL_FORMAT_UTIL_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
std::string truncateStringBack(StringRef S, uint32_t MaxLen);
|
||||
std::string truncateStringMiddle(StringRef S, uint32_t MaxLen);
|
||||
std::string truncateStringFront(StringRef S, uint32_t MaxLen);
|
||||
std::string truncateQuotedNameFront(StringRef Label, StringRef Name,
|
||||
uint32_t MaxLen);
|
||||
std::string truncateQuotedNameBack(StringRef Label, StringRef Name,
|
||||
uint32_t MaxLen);
|
||||
|
||||
#define PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, Text) \
|
||||
if (Enum::TheOpt == (Value & Mask)) \
|
||||
Opts.push_back(Text);
|
||||
|
||||
#define PUSH_FLAG(Enum, TheOpt, Value, Text) \
|
||||
PUSH_MASKED_FLAG(Enum, Enum::TheOpt, TheOpt, Value, Text)
|
||||
|
||||
#define RETURN_CASE(Enum, X, Ret) \
|
||||
case Enum::X: \
|
||||
return Ret;
|
||||
|
||||
template <typename T> std::string formatUnknownEnum(T Value) {
|
||||
return formatv("unknown ({0})",
|
||||
static_cast<typename std::underlying_type<T>::type>(Value))
|
||||
.str();
|
||||
}
|
||||
|
||||
std::string formatSegmentOffset(uint16_t Segment, uint32_t Offset);
|
||||
|
||||
enum class CharacteristicStyle {
|
||||
HeaderDefinition, // format as windows header definition
|
||||
Descriptive, // format as human readable words
|
||||
};
|
||||
std::string formatSectionCharacteristics(
|
||||
uint32_t IndentLevel, uint32_t C, uint32_t FlagsPerLine,
|
||||
StringRef Separator,
|
||||
CharacteristicStyle Style = CharacteristicStyle::HeaderDefinition);
|
||||
|
||||
std::string typesetItemList(ArrayRef<std::string> Opts, uint32_t IndentLevel,
|
||||
uint32_t GroupSize, StringRef Sep);
|
||||
|
||||
std::string typesetStringList(uint32_t IndentLevel,
|
||||
ArrayRef<StringRef> Strings);
|
||||
|
||||
std::string formatChunkKind(codeview::DebugSubsectionKind Kind,
|
||||
bool Friendly = true);
|
||||
std::string formatSymbolKind(codeview::SymbolKind K);
|
||||
StringRef formatTypeLeafKind(codeview::TypeLeafKind K);
|
||||
|
||||
/// Returns the number of digits in the given integer.
|
||||
inline int NumDigits(uint64_t N) {
|
||||
if (N < 10ULL)
|
||||
return 1;
|
||||
if (N < 100ULL)
|
||||
return 2;
|
||||
if (N < 1000ULL)
|
||||
return 3;
|
||||
if (N < 10000ULL)
|
||||
return 4;
|
||||
if (N < 100000ULL)
|
||||
return 5;
|
||||
if (N < 1000000ULL)
|
||||
return 6;
|
||||
if (N < 10000000ULL)
|
||||
return 7;
|
||||
if (N < 100000000ULL)
|
||||
return 8;
|
||||
if (N < 1000000000ULL)
|
||||
return 9;
|
||||
if (N < 10000000000ULL)
|
||||
return 10;
|
||||
if (N < 100000000000ULL)
|
||||
return 11;
|
||||
if (N < 1000000000000ULL)
|
||||
return 12;
|
||||
if (N < 10000000000000ULL)
|
||||
return 13;
|
||||
if (N < 100000000000000ULL)
|
||||
return 14;
|
||||
if (N < 1000000000000000ULL)
|
||||
return 15;
|
||||
if (N < 10000000000000000ULL)
|
||||
return 16;
|
||||
if (N < 100000000000000000ULL)
|
||||
return 17;
|
||||
if (N < 1000000000000000000ULL)
|
||||
return 18;
|
||||
if (N < 10000000000000000000ULL)
|
||||
return 19;
|
||||
return 20;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct EndianAdapter final
|
||||
: public FormatAdapter<support::detail::packed_endian_specific_integral<
|
||||
T, support::little, support::unaligned>> {
|
||||
using EndianType =
|
||||
support::detail::packed_endian_specific_integral<T, support::little,
|
||||
support::unaligned>;
|
||||
|
||||
explicit EndianAdapter(EndianType &&Item)
|
||||
: FormatAdapter<EndianType>(std::move(Item)) {}
|
||||
|
||||
void format(llvm::raw_ostream &Stream, StringRef Style) {
|
||||
format_provider<T>::format(static_cast<T>(this->Item), Stream, Style);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
detail::EndianAdapter<T>
|
||||
fmtle(support::detail::packed_endian_specific_integral<T, support::little,
|
||||
support::unaligned>
|
||||
Value) {
|
||||
return detail::EndianAdapter<T>(std::move(Value));
|
||||
}
|
||||
}
|
||||
} // namespace llvm
|
||||
#endif
|
469
external/llvm/tools/llvm-pdbutil/InputFile.cpp
vendored
469
external/llvm/tools/llvm-pdbutil/InputFile.cpp
vendored
@ -1,469 +0,0 @@
|
||||
//===- InputFile.cpp ------------------------------------------ *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InputFile.h"
|
||||
|
||||
#include "FormatUtil.h"
|
||||
#include "LinePrinter.h"
|
||||
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawError.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/PDB.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
InputFile::InputFile() {}
|
||||
InputFile::~InputFile() {}
|
||||
|
||||
static Expected<ModuleDebugStreamRef>
|
||||
getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index) {
|
||||
ExitOnError Err("Unexpected error: ");
|
||||
|
||||
auto &Dbi = Err(File.getPDBDbiStream());
|
||||
const auto &Modules = Dbi.modules();
|
||||
auto Modi = Modules.getModuleDescriptor(Index);
|
||||
|
||||
ModuleName = Modi.getModuleName();
|
||||
|
||||
uint16_t ModiStream = Modi.getModuleStreamIndex();
|
||||
if (ModiStream == kInvalidStreamIndex)
|
||||
return make_error<RawError>(raw_error_code::no_stream,
|
||||
"Module stream not present");
|
||||
|
||||
auto ModStreamData = File.createIndexedStream(ModiStream);
|
||||
|
||||
ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
|
||||
if (auto EC = ModS.reload())
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
"Invalid module stream");
|
||||
|
||||
return std::move(ModS);
|
||||
}
|
||||
|
||||
static inline bool isCodeViewDebugSubsection(object::SectionRef Section,
|
||||
StringRef Name,
|
||||
BinaryStreamReader &Reader) {
|
||||
StringRef SectionName, Contents;
|
||||
if (Section.getName(SectionName))
|
||||
return false;
|
||||
|
||||
if (SectionName != Name)
|
||||
return false;
|
||||
|
||||
if (Section.getContents(Contents))
|
||||
return false;
|
||||
|
||||
Reader = BinaryStreamReader(Contents, support::little);
|
||||
uint32_t Magic;
|
||||
if (Reader.bytesRemaining() < sizeof(uint32_t))
|
||||
return false;
|
||||
cantFail(Reader.readInteger(Magic));
|
||||
if (Magic != COFF::DEBUG_SECTION_MAGIC)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool isDebugSSection(object::SectionRef Section,
|
||||
DebugSubsectionArray &Subsections) {
|
||||
BinaryStreamReader Reader;
|
||||
if (!isCodeViewDebugSubsection(Section, ".debug$S", Reader))
|
||||
return false;
|
||||
|
||||
cantFail(Reader.readArray(Subsections, Reader.bytesRemaining()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isDebugTSection(SectionRef Section, CVTypeArray &Types) {
|
||||
BinaryStreamReader Reader;
|
||||
if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader))
|
||||
return false;
|
||||
cantFail(Reader.readArray(Types, Reader.bytesRemaining()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string formatChecksumKind(FileChecksumKind Kind) {
|
||||
switch (Kind) {
|
||||
RETURN_CASE(FileChecksumKind, None, "None");
|
||||
RETURN_CASE(FileChecksumKind, MD5, "MD5");
|
||||
RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
|
||||
RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
|
||||
}
|
||||
return formatUnknownEnum(Kind);
|
||||
}
|
||||
|
||||
static const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
|
||||
return cantFail(File.getStringTable()).getStringTable();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static void formatInternal(LinePrinter &Printer, bool Append, Args &&... args) {
|
||||
if (Append)
|
||||
Printer.format(std::forward<Args>(args)...);
|
||||
else
|
||||
Printer.formatLine(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
SymbolGroup::SymbolGroup(InputFile *File, uint32_t GroupIndex) : File(File) {
|
||||
if (!File)
|
||||
return;
|
||||
|
||||
if (File->isPdb())
|
||||
initializeForPdb(GroupIndex);
|
||||
else {
|
||||
Name = ".debug$S";
|
||||
uint32_t I = 0;
|
||||
for (const auto &S : File->obj().sections()) {
|
||||
DebugSubsectionArray SS;
|
||||
if (!isDebugSSection(S, SS))
|
||||
continue;
|
||||
|
||||
if (!SC.hasChecksums() || !SC.hasStrings())
|
||||
SC.initialize(SS);
|
||||
|
||||
if (I == GroupIndex)
|
||||
Subsections = SS;
|
||||
|
||||
if (SC.hasChecksums() && SC.hasStrings())
|
||||
break;
|
||||
}
|
||||
rebuildChecksumMap();
|
||||
}
|
||||
}
|
||||
|
||||
StringRef SymbolGroup::name() const { return Name; }
|
||||
|
||||
void SymbolGroup::updateDebugS(const codeview::DebugSubsectionArray &SS) {
|
||||
Subsections = SS;
|
||||
}
|
||||
|
||||
void SymbolGroup::updatePdbModi(uint32_t Modi) { initializeForPdb(Modi); }
|
||||
|
||||
void SymbolGroup::initializeForPdb(uint32_t Modi) {
|
||||
assert(File && File->isPdb());
|
||||
|
||||
// PDB always uses the same string table, but each module has its own
|
||||
// checksums. So we only set the strings if they're not already set.
|
||||
if (!SC.hasStrings())
|
||||
SC.setStrings(extractStringTable(File->pdb()));
|
||||
|
||||
SC.resetChecksums();
|
||||
auto MDS = getModuleDebugStream(File->pdb(), Name, Modi);
|
||||
if (!MDS) {
|
||||
consumeError(MDS.takeError());
|
||||
return;
|
||||
}
|
||||
|
||||
DebugStream = std::make_shared<ModuleDebugStreamRef>(std::move(*MDS));
|
||||
Subsections = DebugStream->getSubsectionsArray();
|
||||
SC.initialize(Subsections);
|
||||
rebuildChecksumMap();
|
||||
}
|
||||
|
||||
void SymbolGroup::rebuildChecksumMap() {
|
||||
if (!SC.hasChecksums())
|
||||
return;
|
||||
|
||||
for (const auto &Entry : SC.checksums()) {
|
||||
auto S = SC.strings().getString(Entry.FileNameOffset);
|
||||
if (!S)
|
||||
continue;
|
||||
ChecksumsByFile[*S] = Entry;
|
||||
}
|
||||
}
|
||||
|
||||
const ModuleDebugStreamRef &SymbolGroup::getPdbModuleStream() const {
|
||||
assert(File && File->isPdb() && DebugStream);
|
||||
return *DebugStream;
|
||||
}
|
||||
|
||||
Expected<StringRef> SymbolGroup::getNameFromStringTable(uint32_t Offset) const {
|
||||
return SC.strings().getString(Offset);
|
||||
}
|
||||
|
||||
void SymbolGroup::formatFromFileName(LinePrinter &Printer, StringRef File,
|
||||
bool Append) const {
|
||||
auto FC = ChecksumsByFile.find(File);
|
||||
if (FC == ChecksumsByFile.end()) {
|
||||
formatInternal(Printer, Append, "- (no checksum) {0}", File);
|
||||
return;
|
||||
}
|
||||
|
||||
formatInternal(Printer, Append, "- ({0}: {1}) {2}",
|
||||
formatChecksumKind(FC->getValue().Kind),
|
||||
toHex(FC->getValue().Checksum), File);
|
||||
}
|
||||
|
||||
void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer,
|
||||
uint32_t Offset,
|
||||
bool Append) const {
|
||||
if (!SC.hasChecksums()) {
|
||||
formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
|
||||
return;
|
||||
}
|
||||
|
||||
auto Iter = SC.checksums().getArray().at(Offset);
|
||||
if (Iter == SC.checksums().getArray().end()) {
|
||||
formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t FO = Iter->FileNameOffset;
|
||||
auto ExpectedFile = getNameFromStringTable(FO);
|
||||
if (!ExpectedFile) {
|
||||
formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
|
||||
consumeError(ExpectedFile.takeError());
|
||||
return;
|
||||
}
|
||||
if (Iter->Kind == FileChecksumKind::None) {
|
||||
formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
|
||||
} else {
|
||||
formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
|
||||
formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
|
||||
}
|
||||
}
|
||||
|
||||
Expected<InputFile> InputFile::open(StringRef Path) {
|
||||
InputFile IF;
|
||||
if (!llvm::sys::fs::exists(Path))
|
||||
return make_error<StringError>(formatv("File {0} not found", Path),
|
||||
inconvertibleErrorCode());
|
||||
|
||||
file_magic Magic;
|
||||
if (auto EC = identify_magic(Path, Magic))
|
||||
return make_error<StringError>(
|
||||
formatv("Unable to identify file type for file {0}", Path), EC);
|
||||
|
||||
if (Magic == file_magic::coff_object) {
|
||||
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Path);
|
||||
if (!BinaryOrErr)
|
||||
return BinaryOrErr.takeError();
|
||||
|
||||
IF.CoffObject = std::move(*BinaryOrErr);
|
||||
IF.PdbOrObj = llvm::cast<COFFObjectFile>(IF.CoffObject.getBinary());
|
||||
return std::move(IF);
|
||||
}
|
||||
|
||||
if (Magic == file_magic::unknown) {
|
||||
std::unique_ptr<IPDBSession> Session;
|
||||
if (auto Err = loadDataForPDB(PDB_ReaderType::Native, Path, Session))
|
||||
return std::move(Err);
|
||||
|
||||
IF.PdbSession.reset(static_cast<NativeSession *>(Session.release()));
|
||||
IF.PdbOrObj = &IF.PdbSession->getPDBFile();
|
||||
|
||||
return std::move(IF);
|
||||
}
|
||||
|
||||
return make_error<StringError>(
|
||||
formatv("File {0} is not a supported file type", Path),
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
|
||||
PDBFile &InputFile::pdb() {
|
||||
assert(isPdb());
|
||||
return *PdbOrObj.get<PDBFile *>();
|
||||
}
|
||||
|
||||
const PDBFile &InputFile::pdb() const {
|
||||
assert(isPdb());
|
||||
return *PdbOrObj.get<PDBFile *>();
|
||||
}
|
||||
|
||||
object::COFFObjectFile &InputFile::obj() {
|
||||
assert(isObj());
|
||||
return *PdbOrObj.get<object::COFFObjectFile *>();
|
||||
}
|
||||
|
||||
const object::COFFObjectFile &InputFile::obj() const {
|
||||
assert(isObj());
|
||||
return *PdbOrObj.get<object::COFFObjectFile *>();
|
||||
}
|
||||
|
||||
bool InputFile::hasTypes() const {
|
||||
if (isPdb())
|
||||
return pdb().hasPDBTpiStream();
|
||||
|
||||
for (const auto &Section : obj().sections()) {
|
||||
CVTypeArray Types;
|
||||
if (isDebugTSection(Section, Types))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputFile::hasIds() const {
|
||||
if (isObj())
|
||||
return false;
|
||||
return pdb().hasPDBIpiStream();
|
||||
}
|
||||
|
||||
bool InputFile::isPdb() const { return PdbOrObj.is<PDBFile *>(); }
|
||||
|
||||
bool InputFile::isObj() const {
|
||||
return PdbOrObj.is<object::COFFObjectFile *>();
|
||||
}
|
||||
|
||||
codeview::LazyRandomTypeCollection &
|
||||
InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) {
|
||||
if (Types && Kind == kTypes)
|
||||
return *Types;
|
||||
if (Ids && Kind == kIds)
|
||||
return *Ids;
|
||||
|
||||
if (Kind == kIds) {
|
||||
assert(isPdb() && pdb().hasPDBIpiStream());
|
||||
}
|
||||
|
||||
// If the collection was already initialized, we should have just returned it
|
||||
// in step 1.
|
||||
if (isPdb()) {
|
||||
TypeCollectionPtr &Collection = (Kind == kIds) ? Ids : Types;
|
||||
auto &Stream = cantFail((Kind == kIds) ? pdb().getPDBIpiStream()
|
||||
: pdb().getPDBTpiStream());
|
||||
|
||||
auto &Array = Stream.typeArray();
|
||||
uint32_t Count = Stream.getNumTypeRecords();
|
||||
auto Offsets = Stream.getTypeIndexOffsets();
|
||||
Collection =
|
||||
llvm::make_unique<LazyRandomTypeCollection>(Array, Count, Offsets);
|
||||
return *Collection;
|
||||
}
|
||||
|
||||
assert(isObj());
|
||||
assert(Kind == kTypes);
|
||||
assert(!Types);
|
||||
|
||||
for (const auto &Section : obj().sections()) {
|
||||
CVTypeArray Records;
|
||||
if (!isDebugTSection(Section, Records))
|
||||
continue;
|
||||
|
||||
Types = llvm::make_unique<LazyRandomTypeCollection>(Records, 100);
|
||||
return *Types;
|
||||
}
|
||||
|
||||
Types = llvm::make_unique<LazyRandomTypeCollection>(100);
|
||||
return *Types;
|
||||
}
|
||||
|
||||
codeview::LazyRandomTypeCollection &InputFile::types() {
|
||||
return getOrCreateTypeCollection(kTypes);
|
||||
}
|
||||
|
||||
codeview::LazyRandomTypeCollection &InputFile::ids() {
|
||||
// Object files have only one type stream that contains both types and ids.
|
||||
// Similarly, some PDBs don't contain an IPI stream, and for those both types
|
||||
// and IDs are in the same stream.
|
||||
if (isObj() || !pdb().hasPDBIpiStream())
|
||||
return types();
|
||||
|
||||
return getOrCreateTypeCollection(kIds);
|
||||
}
|
||||
|
||||
iterator_range<SymbolGroupIterator> InputFile::symbol_groups() {
|
||||
return make_range<SymbolGroupIterator>(symbol_groups_begin(),
|
||||
symbol_groups_end());
|
||||
}
|
||||
|
||||
SymbolGroupIterator InputFile::symbol_groups_begin() {
|
||||
return SymbolGroupIterator(*this);
|
||||
}
|
||||
|
||||
SymbolGroupIterator InputFile::symbol_groups_end() {
|
||||
return SymbolGroupIterator();
|
||||
}
|
||||
|
||||
SymbolGroupIterator::SymbolGroupIterator() : Value(nullptr) {}
|
||||
|
||||
SymbolGroupIterator::SymbolGroupIterator(InputFile &File) : Value(&File) {
|
||||
if (File.isObj()) {
|
||||
SectionIter = File.obj().section_begin();
|
||||
scanToNextDebugS();
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolGroupIterator::operator==(const SymbolGroupIterator &R) const {
|
||||
bool E = isEnd();
|
||||
bool RE = R.isEnd();
|
||||
if (E || RE)
|
||||
return E == RE;
|
||||
|
||||
if (Value.File != R.Value.File)
|
||||
return false;
|
||||
return Index == R.Index;
|
||||
}
|
||||
|
||||
const SymbolGroup &SymbolGroupIterator::operator*() const {
|
||||
assert(!isEnd());
|
||||
return Value;
|
||||
}
|
||||
SymbolGroup &SymbolGroupIterator::operator*() {
|
||||
assert(!isEnd());
|
||||
return Value;
|
||||
}
|
||||
|
||||
SymbolGroupIterator &SymbolGroupIterator::operator++() {
|
||||
assert(Value.File && !isEnd());
|
||||
++Index;
|
||||
if (isEnd())
|
||||
return *this;
|
||||
|
||||
if (Value.File->isPdb()) {
|
||||
Value.updatePdbModi(Index);
|
||||
return *this;
|
||||
}
|
||||
|
||||
scanToNextDebugS();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SymbolGroupIterator::scanToNextDebugS() {
|
||||
assert(SectionIter.hasValue());
|
||||
auto End = Value.File->obj().section_end();
|
||||
auto &Iter = *SectionIter;
|
||||
assert(!isEnd());
|
||||
|
||||
while (++Iter != End) {
|
||||
DebugSubsectionArray SS;
|
||||
SectionRef SR = *Iter;
|
||||
if (!isDebugSSection(SR, SS))
|
||||
continue;
|
||||
|
||||
Value.updateDebugS(SS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolGroupIterator::isEnd() const {
|
||||
if (!Value.File)
|
||||
return true;
|
||||
if (Value.File->isPdb()) {
|
||||
auto &Dbi = cantFail(Value.File->pdb().getPDBDbiStream());
|
||||
uint32_t Count = Dbi.modules().getModuleCount();
|
||||
assert(Index <= Count);
|
||||
return Index == Count;
|
||||
}
|
||||
|
||||
assert(SectionIter.hasValue());
|
||||
return *SectionIter == Value.File->obj().section_end();
|
||||
}
|
147
external/llvm/tools/llvm-pdbutil/InputFile.h
vendored
147
external/llvm/tools/llvm-pdbutil/InputFile.h
vendored
@ -1,147 +0,0 @@
|
||||
//===- InputFile.h -------------------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_INPUTFILE_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_INPUTFILE_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
class LazyRandomTypeCollection;
|
||||
}
|
||||
namespace object {
|
||||
class COFFObjectFile;
|
||||
class SectionRef;
|
||||
} // namespace object
|
||||
|
||||
namespace pdb {
|
||||
class InputFile;
|
||||
class LinePrinter;
|
||||
class PDBFile;
|
||||
class NativeSession;
|
||||
class SymbolGroupIterator;
|
||||
class SymbolGroup;
|
||||
|
||||
class InputFile {
|
||||
InputFile();
|
||||
|
||||
std::unique_ptr<NativeSession> PdbSession;
|
||||
object::OwningBinary<object::Binary> CoffObject;
|
||||
PointerUnion<PDBFile *, object::COFFObjectFile *> PdbOrObj;
|
||||
|
||||
using TypeCollectionPtr = std::unique_ptr<codeview::LazyRandomTypeCollection>;
|
||||
|
||||
TypeCollectionPtr Types;
|
||||
TypeCollectionPtr Ids;
|
||||
|
||||
enum TypeCollectionKind { kTypes, kIds };
|
||||
codeview::LazyRandomTypeCollection &
|
||||
getOrCreateTypeCollection(TypeCollectionKind Kind);
|
||||
|
||||
public:
|
||||
~InputFile();
|
||||
InputFile(InputFile &&Other) = default;
|
||||
|
||||
static Expected<InputFile> open(StringRef Path);
|
||||
|
||||
PDBFile &pdb();
|
||||
const PDBFile &pdb() const;
|
||||
object::COFFObjectFile &obj();
|
||||
const object::COFFObjectFile &obj() const;
|
||||
|
||||
bool hasTypes() const;
|
||||
bool hasIds() const;
|
||||
|
||||
codeview::LazyRandomTypeCollection &types();
|
||||
codeview::LazyRandomTypeCollection &ids();
|
||||
|
||||
iterator_range<SymbolGroupIterator> symbol_groups();
|
||||
SymbolGroupIterator symbol_groups_begin();
|
||||
SymbolGroupIterator symbol_groups_end();
|
||||
|
||||
bool isPdb() const;
|
||||
bool isObj() const;
|
||||
};
|
||||
|
||||
class SymbolGroup {
|
||||
friend class SymbolGroupIterator;
|
||||
|
||||
public:
|
||||
explicit SymbolGroup(InputFile *File, uint32_t GroupIndex = 0);
|
||||
|
||||
Expected<StringRef> getNameFromStringTable(uint32_t Offset) const;
|
||||
|
||||
void formatFromFileName(LinePrinter &Printer, StringRef File,
|
||||
bool Append = false) const;
|
||||
|
||||
void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
|
||||
bool Append = false) const;
|
||||
|
||||
StringRef name() const;
|
||||
|
||||
codeview::DebugSubsectionArray getDebugSubsections() const {
|
||||
return Subsections;
|
||||
}
|
||||
const ModuleDebugStreamRef &getPdbModuleStream() const;
|
||||
|
||||
const InputFile &getFile() const { return *File; }
|
||||
InputFile &getFile() { return *File; }
|
||||
|
||||
private:
|
||||
void initializeForPdb(uint32_t Modi);
|
||||
void updatePdbModi(uint32_t Modi);
|
||||
void updateDebugS(const codeview::DebugSubsectionArray &SS);
|
||||
|
||||
void rebuildChecksumMap();
|
||||
InputFile *File = nullptr;
|
||||
StringRef Name;
|
||||
codeview::DebugSubsectionArray Subsections;
|
||||
std::shared_ptr<ModuleDebugStreamRef> DebugStream;
|
||||
codeview::StringsAndChecksumsRef SC;
|
||||
StringMap<codeview::FileChecksumEntry> ChecksumsByFile;
|
||||
};
|
||||
|
||||
class SymbolGroupIterator
|
||||
: public iterator_facade_base<SymbolGroupIterator,
|
||||
std::forward_iterator_tag, SymbolGroup> {
|
||||
public:
|
||||
SymbolGroupIterator();
|
||||
explicit SymbolGroupIterator(InputFile &File);
|
||||
SymbolGroupIterator(const SymbolGroupIterator &Other) = default;
|
||||
SymbolGroupIterator &operator=(const SymbolGroupIterator &R) = default;
|
||||
|
||||
const SymbolGroup &operator*() const;
|
||||
SymbolGroup &operator*();
|
||||
|
||||
bool operator==(const SymbolGroupIterator &R) const;
|
||||
SymbolGroupIterator &operator++();
|
||||
|
||||
private:
|
||||
void scanToNextDebugS();
|
||||
bool isEnd() const;
|
||||
|
||||
uint32_t Index = 0;
|
||||
Optional<object::section_iterator> SectionIter;
|
||||
SymbolGroup Value;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
23
external/llvm/tools/llvm-pdbutil/LLVMBuild.txt
vendored
23
external/llvm/tools/llvm-pdbutil/LLVMBuild.txt
vendored
@ -1,23 +0,0 @@
|
||||
;===- ./tools/llvm-pdbutil/LLVMBuild.txt -----------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Tool
|
||||
name = llvm-pdbutil
|
||||
parent = Tools
|
||||
required_libraries = DebugInfoMSF DebugInfoPDB
|
||||
|
335
external/llvm/tools/llvm-pdbutil/LinePrinter.cpp
vendored
335
external/llvm/tools/llvm-pdbutil/LinePrinter.cpp
vendored
@ -1,335 +0,0 @@
|
||||
//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LinePrinter.h"
|
||||
|
||||
#include "llvm-pdbutil.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/UDTLayout.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::msf;
|
||||
using namespace llvm::pdb;
|
||||
|
||||
namespace {
|
||||
bool IsItemExcluded(llvm::StringRef Item,
|
||||
std::list<llvm::Regex> &IncludeFilters,
|
||||
std::list<llvm::Regex> &ExcludeFilters) {
|
||||
if (Item.empty())
|
||||
return false;
|
||||
|
||||
auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
|
||||
|
||||
// Include takes priority over exclude. If the user specified include
|
||||
// filters, and none of them include this item, them item is gone.
|
||||
if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
|
||||
return true;
|
||||
|
||||
if (any_of(ExcludeFilters, match_pred))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream)
|
||||
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) {
|
||||
SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(),
|
||||
opts::pretty::ExcludeTypes.end());
|
||||
SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(),
|
||||
opts::pretty::ExcludeSymbols.end());
|
||||
SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(),
|
||||
opts::pretty::ExcludeCompilands.end());
|
||||
|
||||
SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(),
|
||||
opts::pretty::IncludeTypes.end());
|
||||
SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(),
|
||||
opts::pretty::IncludeSymbols.end());
|
||||
SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(),
|
||||
opts::pretty::IncludeCompilands.end());
|
||||
}
|
||||
|
||||
void LinePrinter::Indent(uint32_t Amount) {
|
||||
if (Amount == 0)
|
||||
Amount = IndentSpaces;
|
||||
CurrentIndent += Amount;
|
||||
}
|
||||
|
||||
void LinePrinter::Unindent(uint32_t Amount) {
|
||||
if (Amount == 0)
|
||||
Amount = IndentSpaces;
|
||||
CurrentIndent = std::max<int>(0, CurrentIndent - Amount);
|
||||
}
|
||||
|
||||
void LinePrinter::NewLine() {
|
||||
OS << "\n";
|
||||
OS.indent(CurrentIndent);
|
||||
}
|
||||
|
||||
void LinePrinter::print(const Twine &T) { OS << T; }
|
||||
|
||||
void LinePrinter::printLine(const Twine &T) {
|
||||
NewLine();
|
||||
OS << T;
|
||||
}
|
||||
|
||||
bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
|
||||
if (IsTypeExcluded(Class.getName(), Class.getSize()))
|
||||
return true;
|
||||
if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
|
||||
uint32_t StartOffset) {
|
||||
NewLine();
|
||||
OS << Label << " (";
|
||||
if (!Data.empty()) {
|
||||
OS << "\n";
|
||||
OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
|
||||
CurrentIndent + IndentSpaces, true);
|
||||
NewLine();
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
|
||||
uint64_t Base, uint32_t StartOffset) {
|
||||
NewLine();
|
||||
OS << Label << " (";
|
||||
if (!Data.empty()) {
|
||||
OS << "\n";
|
||||
Base += StartOffset;
|
||||
OS << format_bytes_with_ascii(Data, Base, 32, 4,
|
||||
CurrentIndent + IndentSpaces, true);
|
||||
NewLine();
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct Run {
|
||||
Run() = default;
|
||||
explicit Run(uint32_t Block) : Block(Block) {}
|
||||
uint32_t Block = 0;
|
||||
uint32_t ByteLen = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static std::vector<Run> computeBlockRuns(uint32_t BlockSize,
|
||||
const msf::MSFStreamLayout &Layout) {
|
||||
std::vector<Run> Runs;
|
||||
if (Layout.Length == 0)
|
||||
return Runs;
|
||||
|
||||
ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks;
|
||||
assert(!Blocks.empty());
|
||||
uint32_t StreamBytesRemaining = Layout.Length;
|
||||
uint32_t CurrentBlock = Blocks[0];
|
||||
Runs.emplace_back(CurrentBlock);
|
||||
while (!Blocks.empty()) {
|
||||
Run *CurrentRun = &Runs.back();
|
||||
uint32_t NextBlock = Blocks.front();
|
||||
if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) {
|
||||
Runs.emplace_back(NextBlock);
|
||||
CurrentRun = &Runs.back();
|
||||
}
|
||||
uint32_t Used = std::min(BlockSize, StreamBytesRemaining);
|
||||
CurrentRun->ByteLen += Used;
|
||||
StreamBytesRemaining -= Used;
|
||||
CurrentBlock = NextBlock;
|
||||
Blocks = Blocks.drop_front();
|
||||
}
|
||||
return Runs;
|
||||
}
|
||||
|
||||
static std::pair<Run, uint32_t> findRun(uint32_t Offset, ArrayRef<Run> Runs) {
|
||||
for (const auto &R : Runs) {
|
||||
if (Offset < R.ByteLen)
|
||||
return std::make_pair(R, Offset);
|
||||
Offset -= R.ByteLen;
|
||||
}
|
||||
llvm_unreachable("Invalid offset!");
|
||||
}
|
||||
|
||||
void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
|
||||
uint32_t StreamIdx,
|
||||
StringRef StreamPurpose, uint32_t Offset,
|
||||
uint32_t Size) {
|
||||
if (StreamIdx >= File.getNumStreams()) {
|
||||
formatLine("Stream {0}: Not present", StreamIdx);
|
||||
return;
|
||||
}
|
||||
if (Size + Offset > File.getStreamByteSize(StreamIdx)) {
|
||||
formatLine(
|
||||
"Stream {0}: Invalid offset and size, range out of stream bounds",
|
||||
StreamIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
auto S = MappedBlockStream::createIndexedStream(
|
||||
File.getMsfLayout(), File.getMsfBuffer(), StreamIdx, File.getAllocator());
|
||||
if (!S) {
|
||||
NewLine();
|
||||
formatLine("Stream {0}: Not present", StreamIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t End =
|
||||
(Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength());
|
||||
Size = End - Offset;
|
||||
|
||||
formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx,
|
||||
StreamPurpose, Size, S->getLength());
|
||||
AutoIndent Indent(*this);
|
||||
BinaryStreamRef Slice(*S);
|
||||
BinarySubstreamRef Substream;
|
||||
Substream.Offset = Offset;
|
||||
Substream.StreamData = Slice.drop_front(Offset).keep_front(Size);
|
||||
|
||||
auto Layout = File.getStreamLayout(StreamIdx);
|
||||
formatMsfStreamData(Label, File, Layout, Substream);
|
||||
}
|
||||
|
||||
void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
|
||||
const msf::MSFStreamLayout &Stream,
|
||||
BinarySubstreamRef Substream) {
|
||||
BinaryStreamReader Reader(Substream.StreamData);
|
||||
|
||||
auto Runs = computeBlockRuns(File.getBlockSize(), Stream);
|
||||
|
||||
NewLine();
|
||||
OS << Label << " (";
|
||||
while (Reader.bytesRemaining() > 0) {
|
||||
OS << "\n";
|
||||
|
||||
Run FoundRun;
|
||||
uint32_t RunOffset;
|
||||
std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs);
|
||||
assert(FoundRun.ByteLen >= RunOffset);
|
||||
uint32_t Len = FoundRun.ByteLen - RunOffset;
|
||||
Len = std::min(Len, Reader.bytesRemaining());
|
||||
uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset;
|
||||
ArrayRef<uint8_t> Data;
|
||||
consumeError(Reader.readBytes(Data, Len));
|
||||
OS << format_bytes_with_ascii(Data, Base, 32, 4,
|
||||
CurrentIndent + IndentSpaces, true);
|
||||
if (Reader.bytesRemaining() > 0) {
|
||||
NewLine();
|
||||
OS << formatv(" {0}",
|
||||
fmt_align("<discontinuity>", AlignStyle::Center, 114, '-'));
|
||||
}
|
||||
Substream.Offset += Len;
|
||||
}
|
||||
NewLine();
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void LinePrinter::formatMsfStreamBlocks(
|
||||
PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {
|
||||
auto Blocks = makeArrayRef(StreamLayout.Blocks);
|
||||
uint32_t L = StreamLayout.Length;
|
||||
|
||||
while (L > 0) {
|
||||
NewLine();
|
||||
assert(!Blocks.empty());
|
||||
OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));
|
||||
uint32_t UsedBytes = std::min(L, File.getBlockSize());
|
||||
ArrayRef<uint8_t> BlockData =
|
||||
cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));
|
||||
uint64_t BaseOffset = Blocks.front();
|
||||
BaseOffset *= File.getBlockSize();
|
||||
OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,
|
||||
CurrentIndent + IndentSpaces, true);
|
||||
NewLine();
|
||||
OS << ")";
|
||||
NewLine();
|
||||
L -= UsedBytes;
|
||||
Blocks = Blocks.drop_front();
|
||||
}
|
||||
}
|
||||
|
||||
bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
|
||||
if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
|
||||
return true;
|
||||
if (Size < opts::pretty::SizeThreshold)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
|
||||
return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
|
||||
}
|
||||
|
||||
bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
|
||||
return IsItemExcluded(CompilandName, IncludeCompilandFilters,
|
||||
ExcludeCompilandFilters);
|
||||
}
|
||||
|
||||
WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)
|
||||
: OS(P.OS), UseColor(P.hasColor()) {
|
||||
if (UseColor)
|
||||
applyColor(C);
|
||||
}
|
||||
|
||||
WithColor::~WithColor() {
|
||||
if (UseColor)
|
||||
OS.resetColor();
|
||||
}
|
||||
|
||||
void WithColor::applyColor(PDB_ColorItem C) {
|
||||
switch (C) {
|
||||
case PDB_ColorItem::None:
|
||||
OS.resetColor();
|
||||
return;
|
||||
case PDB_ColorItem::Comment:
|
||||
OS.changeColor(raw_ostream::GREEN, false);
|
||||
return;
|
||||
case PDB_ColorItem::Address:
|
||||
OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
|
||||
return;
|
||||
case PDB_ColorItem::Keyword:
|
||||
OS.changeColor(raw_ostream::MAGENTA, true);
|
||||
return;
|
||||
case PDB_ColorItem::Register:
|
||||
case PDB_ColorItem::Offset:
|
||||
OS.changeColor(raw_ostream::YELLOW, false);
|
||||
return;
|
||||
case PDB_ColorItem::Type:
|
||||
OS.changeColor(raw_ostream::CYAN, true);
|
||||
return;
|
||||
case PDB_ColorItem::Identifier:
|
||||
OS.changeColor(raw_ostream::CYAN, false);
|
||||
return;
|
||||
case PDB_ColorItem::Path:
|
||||
OS.changeColor(raw_ostream::CYAN, false);
|
||||
return;
|
||||
case PDB_ColorItem::Padding:
|
||||
case PDB_ColorItem::SectionHeader:
|
||||
OS.changeColor(raw_ostream::RED, true);
|
||||
return;
|
||||
case PDB_ColorItem::LiteralValue:
|
||||
OS.changeColor(raw_ostream::GREEN, true);
|
||||
return;
|
||||
}
|
||||
}
|
170
external/llvm/tools/llvm-pdbutil/LinePrinter.h
vendored
170
external/llvm/tools/llvm-pdbutil/LinePrinter.h
vendored
@ -1,170 +0,0 @@
|
||||
//===- LinePrinter.h ------------------------------------------ *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/BinaryStreamRef.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace llvm {
|
||||
class BinaryStreamReader;
|
||||
namespace msf {
|
||||
class MSFStreamLayout;
|
||||
} // namespace msf
|
||||
namespace pdb {
|
||||
|
||||
class ClassLayout;
|
||||
class PDBFile;
|
||||
|
||||
class LinePrinter {
|
||||
friend class WithColor;
|
||||
|
||||
public:
|
||||
LinePrinter(int Indent, bool UseColor, raw_ostream &Stream);
|
||||
|
||||
void Indent(uint32_t Amount = 0);
|
||||
void Unindent(uint32_t Amount = 0);
|
||||
void NewLine();
|
||||
|
||||
void printLine(const Twine &T);
|
||||
void print(const Twine &T);
|
||||
template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) {
|
||||
printLine(formatv(Fmt, std::forward<Ts>(Items)...));
|
||||
}
|
||||
template <typename... Ts> void format(const char *Fmt, Ts &&... Items) {
|
||||
print(formatv(Fmt, std::forward<Ts>(Items)...));
|
||||
}
|
||||
|
||||
void formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
|
||||
uint32_t StartOffset);
|
||||
void formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint64_t BaseAddr,
|
||||
uint32_t StartOffset);
|
||||
|
||||
void formatMsfStreamData(StringRef Label, PDBFile &File, uint32_t StreamIdx,
|
||||
StringRef StreamPurpose, uint32_t Offset,
|
||||
uint32_t Size);
|
||||
void formatMsfStreamData(StringRef Label, PDBFile &File,
|
||||
const msf::MSFStreamLayout &Stream,
|
||||
BinarySubstreamRef Substream);
|
||||
void formatMsfStreamBlocks(PDBFile &File, const msf::MSFStreamLayout &Stream);
|
||||
|
||||
bool hasColor() const { return UseColor; }
|
||||
raw_ostream &getStream() { return OS; }
|
||||
int getIndentLevel() const { return CurrentIndent; }
|
||||
|
||||
bool IsClassExcluded(const ClassLayout &Class);
|
||||
bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size);
|
||||
bool IsSymbolExcluded(llvm::StringRef SymbolName);
|
||||
bool IsCompilandExcluded(llvm::StringRef CompilandName);
|
||||
|
||||
private:
|
||||
template <typename Iter>
|
||||
void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
|
||||
List.clear();
|
||||
for (; Begin != End; ++Begin)
|
||||
List.emplace_back(StringRef(*Begin));
|
||||
}
|
||||
|
||||
raw_ostream &OS;
|
||||
int IndentSpaces;
|
||||
int CurrentIndent;
|
||||
bool UseColor;
|
||||
|
||||
std::list<Regex> ExcludeCompilandFilters;
|
||||
std::list<Regex> ExcludeTypeFilters;
|
||||
std::list<Regex> ExcludeSymbolFilters;
|
||||
|
||||
std::list<Regex> IncludeCompilandFilters;
|
||||
std::list<Regex> IncludeTypeFilters;
|
||||
std::list<Regex> IncludeSymbolFilters;
|
||||
};
|
||||
|
||||
struct PrintScope {
|
||||
explicit PrintScope(LinePrinter &P, uint32_t IndentLevel)
|
||||
: P(P), IndentLevel(IndentLevel) {}
|
||||
explicit PrintScope(const PrintScope &Other, uint32_t LabelWidth)
|
||||
: P(Other.P), IndentLevel(Other.IndentLevel), LabelWidth(LabelWidth) {}
|
||||
|
||||
LinePrinter &P;
|
||||
uint32_t IndentLevel;
|
||||
uint32_t LabelWidth = 0;
|
||||
};
|
||||
|
||||
inline Optional<PrintScope> withLabelWidth(const Optional<PrintScope> &Scope,
|
||||
uint32_t W) {
|
||||
if (!Scope)
|
||||
return None;
|
||||
return PrintScope{*Scope, W};
|
||||
}
|
||||
|
||||
struct AutoIndent {
|
||||
explicit AutoIndent(LinePrinter &L, uint32_t Amount = 0)
|
||||
: L(&L), Amount(Amount) {
|
||||
L.Indent(Amount);
|
||||
}
|
||||
explicit AutoIndent(const Optional<PrintScope> &Scope) {
|
||||
if (Scope.hasValue()) {
|
||||
L = &Scope->P;
|
||||
Amount = Scope->IndentLevel;
|
||||
}
|
||||
}
|
||||
~AutoIndent() {
|
||||
if (L)
|
||||
L->Unindent(Amount);
|
||||
}
|
||||
|
||||
LinePrinter *L = nullptr;
|
||||
uint32_t Amount = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
|
||||
Printer.getStream() << Item;
|
||||
return Printer.getStream();
|
||||
}
|
||||
|
||||
enum class PDB_ColorItem {
|
||||
None,
|
||||
Address,
|
||||
Type,
|
||||
Comment,
|
||||
Padding,
|
||||
Keyword,
|
||||
Offset,
|
||||
Identifier,
|
||||
Path,
|
||||
SectionHeader,
|
||||
LiteralValue,
|
||||
Register,
|
||||
};
|
||||
|
||||
class WithColor {
|
||||
public:
|
||||
WithColor(LinePrinter &P, PDB_ColorItem C);
|
||||
~WithColor();
|
||||
|
||||
raw_ostream &get() { return OS; }
|
||||
|
||||
private:
|
||||
void applyColor(PDB_ColorItem C);
|
||||
raw_ostream &OS;
|
||||
bool UseColor;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
||||
//===- MinimalSymbolDumper.h ---------------------------------- *- C++ --*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_SYMBOL_DUMPER_H
|
||||
#define LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_SYMBOL_DUMPER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
class LazyRandomTypeCollection;
|
||||
}
|
||||
|
||||
namespace pdb {
|
||||
class LinePrinter;
|
||||
|
||||
class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
|
||||
public:
|
||||
MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
|
||||
codeview::LazyRandomTypeCollection &Ids,
|
||||
codeview::LazyRandomTypeCollection &Types)
|
||||
: P(P), RecordBytes(RecordBytes), Ids(Ids), Types(Types) {}
|
||||
|
||||
Error visitSymbolBegin(codeview::CVSymbol &Record) override;
|
||||
Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override;
|
||||
Error visitSymbolEnd(codeview::CVSymbol &Record) override;
|
||||
|
||||
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
|
||||
virtual Error visitKnownRecord(codeview::CVSymbol &CVR, \
|
||||
codeview::Name &Record) override;
|
||||
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
||||
|
||||
private:
|
||||
std::string typeOrIdIndex(codeview::TypeIndex TI, bool IsType) const;
|
||||
|
||||
std::string typeIndex(codeview::TypeIndex TI) const;
|
||||
std::string idIndex(codeview::TypeIndex TI) const;
|
||||
|
||||
LinePrinter &P;
|
||||
bool RecordBytes;
|
||||
codeview::LazyRandomTypeCollection &Ids;
|
||||
codeview::LazyRandomTypeCollection &Types;
|
||||
};
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user