Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
)

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 << '|';
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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