aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-pdbutil
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-pdbutil
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-pdbutil')
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.cpp491
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.h68
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.cpp1989
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.h122
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.cpp468
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.h67
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.cpp258
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.h141
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.cpp509
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.h155
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.cpp333
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.h168
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.cpp899
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.h68
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.cpp592
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.h70
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/OutputStyle.h27
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.cpp189
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.h130
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp97
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.h34
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp114
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h46
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp212
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h57
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.cpp228
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.h44
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.cpp68
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.h30
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp41
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h33
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.cpp267
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.h42
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.cpp359
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.h41
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.cpp82
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.h38
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.cpp225
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.h49
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.cpp194
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.h63
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.cpp160
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.h69
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.cpp370
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.h49
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.cpp1575
-rw-r--r--contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.h220
47 files changed, 11551 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.cpp
new file mode 100644
index 0000000000..ffc907e09f
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.cpp
@@ -0,0 +1,491 @@
+//===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 = File.createIndexedStream(ModiStream);
+ 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 =
+ std::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);
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.h b/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.h
new file mode 100644
index 0000000000..d3aceb4767
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/BytesOutputStyle.h
@@ -0,0 +1,68 @@
+//===- BytesOutputStyle.h ------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.cpp
new file mode 100644
index 0000000000..babdb56a71
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -0,0 +1,1989 @@
+//===- DumpOutputStyle.cpp ------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DumpOutputStyle.h"
+
+#include "FormatUtil.h"
+#include "InputFile.h"
+#include "MinimalSymbolDumper.h"
+#include "MinimalTypeDumper.h"
+#include "StreamUtil.h"
+#include "TypeReferenceTracker.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.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/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#include <cctype>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+DumpOutputStyle::DumpOutputStyle(InputFile &File)
+ : File(File), P(2, false, outs()) {
+ if (opts::dump::DumpTypeRefStats)
+ RefTracker.reset(new TypeReferenceTracker(File));
+}
+
+DumpOutputStyle::~DumpOutputStyle() {}
+
+PDBFile &DumpOutputStyle::getPdb() { return File.pdb(); }
+object::COFFObjectFile &DumpOutputStyle::getObj() { return File.obj(); }
+
+void DumpOutputStyle::printStreamNotValidForObj() {
+ AutoIndent Indent(P, 4);
+ P.formatLine("Dumping this stream is not valid for object files");
+}
+
+void DumpOutputStyle::printStreamNotPresent(StringRef StreamName) {
+ AutoIndent Indent(P, 4);
+ P.formatLine("{0} stream not present", StreamName);
+}
+
+Error DumpOutputStyle::dump() {
+ // Walk symbols & globals if we are supposed to mark types referenced.
+ if (opts::dump::DumpTypeRefStats)
+ RefTracker->mark();
+
+ if (opts::dump::DumpSummary) {
+ if (auto EC = dumpFileSummary())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpStreams) {
+ if (auto EC = dumpStreamSummary())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpSymbolStats) {
+ if (auto EC = dumpSymbolStats())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpUdtStats) {
+ if (auto EC = dumpUdtStats())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpTypeStats || opts::dump::DumpIDStats) {
+ if (auto EC = dumpTypeStats())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpNamedStreams) {
+ if (auto EC = dumpNamedStreams())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpStringTable || opts::dump::DumpStringTableDetails) {
+ if (auto EC = dumpStringTable())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::dump::DumpModules) {
+ if (auto EC = dumpModules())
+ return EC;
+ }
+
+ if (opts::dump::DumpModuleFiles) {
+ if (auto EC = dumpModuleFiles())
+ return EC;
+ }
+
+ if (opts::dump::DumpLines) {
+ if (auto EC = dumpLines())
+ return EC;
+ }
+
+ if (opts::dump::DumpInlineeLines) {
+ if (auto EC = dumpInlineeLines())
+ return EC;
+ }
+
+ if (opts::dump::DumpXmi) {
+ if (auto EC = dumpXmi())
+ return EC;
+ }
+
+ if (opts::dump::DumpXme) {
+ if (auto EC = dumpXme())
+ return EC;
+ }
+
+ if (opts::dump::DumpFpo) {
+ if (auto EC = dumpFpo())
+ return EC;
+ }
+
+ if (File.isObj()) {
+ if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
+ opts::dump::DumpTypeExtras)
+ if (auto EC = dumpTypesFromObjectFile())
+ return EC;
+ } else {
+ if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
+ opts::dump::DumpTypeExtras) {
+ if (auto EC = dumpTpiStream(StreamTPI))
+ return EC;
+ }
+
+ if (opts::dump::DumpIds || !opts::dump::DumpIdIndex.empty() ||
+ opts::dump::DumpIdExtras) {
+ if (auto EC = dumpTpiStream(StreamIPI))
+ return EC;
+ }
+ }
+
+ if (opts::dump::DumpGSIRecords) {
+ if (auto EC = dumpGSIRecords())
+ return EC;
+ }
+
+ if (opts::dump::DumpGlobals) {
+ if (auto EC = dumpGlobals())
+ return EC;
+ }
+
+ if (opts::dump::DumpPublics) {
+ if (auto EC = dumpPublics())
+ return EC;
+ }
+
+ if (opts::dump::DumpSymbols) {
+ auto EC = File.isPdb() ? dumpModuleSymsForPdb() : dumpModuleSymsForObj();
+ if (EC)
+ return EC;
+ }
+
+ if (opts::dump::DumpTypeRefStats) {
+ if (auto EC = dumpTypeRefStats())
+ return EC;
+ }
+
+ if (opts::dump::DumpSectionHeaders) {
+ if (auto EC = dumpSectionHeaders())
+ return EC;
+ }
+
+ if (opts::dump::DumpSectionContribs) {
+ if (auto EC = dumpSectionContribs())
+ return EC;
+ }
+
+ if (opts::dump::DumpSectionMap) {
+ if (auto EC = dumpSectionMap())
+ return EC;
+ }
+
+ P.NewLine();
+
+ return Error::success();
+}
+
+static void printHeader(LinePrinter &P, const Twine &S) {
+ P.NewLine();
+ P.formatLine("{0,=60}", S);
+ P.formatLine("{0}", fmt_repeat('=', 60));
+}
+
+Error DumpOutputStyle::dumpFileSummary() {
+ printHeader(P, "Summary");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Invalid PDB Format: ");
+
+ P.formatLine("Block Size: {0}", getPdb().getBlockSize());
+ P.formatLine("Number of blocks: {0}", getPdb().getBlockCount());
+ P.formatLine("Number of streams: {0}", getPdb().getNumStreams());
+
+ auto &PS = Err(getPdb().getPDBInfoStream());
+ P.formatLine("Signature: {0}", PS.getSignature());
+ P.formatLine("Age: {0}", PS.getAge());
+ P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
+ P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
+ P.formatLine("Has Debug Info: {0}", getPdb().hasPDBDbiStream());
+ P.formatLine("Has Types: {0}", getPdb().hasPDBTpiStream());
+ P.formatLine("Has IDs: {0}", getPdb().hasPDBIpiStream());
+ P.formatLine("Has Globals: {0}", getPdb().hasPDBGlobalsStream());
+ P.formatLine("Has Publics: {0}", getPdb().hasPDBPublicsStream());
+ if (getPdb().hasPDBDbiStream()) {
+ auto &DBI = Err(getPdb().getPDBDbiStream());
+ P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
+ P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
+ P.formatLine("Is stripped: {0}", DBI.isStripped());
+ }
+
+ return Error::success();
+}
+
+static StatCollection getSymbolStats(const SymbolGroup &SG,
+ StatCollection &CumulativeStats) {
+ StatCollection Stats;
+ if (SG.getFile().isPdb() && SG.hasDebugStream()) {
+ // For PDB files, all symbols are packed into one stream.
+ for (const auto &S : SG.getPdbModuleStream().symbols(nullptr)) {
+ Stats.update(S.kind(), S.length());
+ CumulativeStats.update(S.kind(), S.length());
+ }
+ return Stats;
+ }
+
+ for (const auto &SS : SG.getDebugSubsections()) {
+ // For object files, all symbols are spread across multiple Symbol
+ // subsections of a given .debug$S section.
+ if (SS.kind() != DebugSubsectionKind::Symbols)
+ continue;
+ DebugSymbolsSubsectionRef Symbols;
+ BinaryStreamReader Reader(SS.getRecordData());
+ cantFail(Symbols.initialize(Reader));
+ for (const auto &S : Symbols) {
+ Stats.update(S.kind(), S.length());
+ CumulativeStats.update(S.kind(), S.length());
+ }
+ }
+ return Stats;
+}
+
+static StatCollection getChunkStats(const SymbolGroup &SG,
+ StatCollection &CumulativeStats) {
+ StatCollection Stats;
+ for (const auto &Chunk : SG.getDebugSubsections()) {
+ Stats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+ CumulativeStats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+ }
+ return Stats;
+}
+
+static inline std::string formatModuleDetailKind(DebugSubsectionKind K) {
+ return formatChunkKind(K, false);
+}
+
+static inline std::string formatModuleDetailKind(SymbolKind K) {
+ return formatSymbolKind(K);
+}
+
+// Get the stats sorted by size, descending.
+std::vector<StatCollection::KindAndStat>
+StatCollection::getStatsSortedBySize() const {
+ std::vector<KindAndStat> SortedStats(Individual.begin(), Individual.end());
+ llvm::stable_sort(SortedStats,
+ [](const KindAndStat &LHS, const KindAndStat &RHS) {
+ return LHS.second.Size > RHS.second.Size;
+ });
+ return SortedStats;
+}
+
+template <typename Kind>
+static void printModuleDetailStats(LinePrinter &P, StringRef Label,
+ const StatCollection &Stats) {
+ P.NewLine();
+ P.formatLine(" {0}", Label);
+ AutoIndent Indent(P);
+ P.formatLine("{0,40}: {1,7} entries ({2,12:N} bytes)", "Total",
+ Stats.Totals.Count, Stats.Totals.Size);
+ P.formatLine("{0}", fmt_repeat('-', 74));
+
+ for (const auto &K : Stats.getStatsSortedBySize()) {
+ std::string KindName = formatModuleDetailKind(Kind(K.first));
+ P.formatLine("{0,40}: {1,7} entries ({2,12:N} bytes)", KindName,
+ K.second.Count, K.second.Size);
+ }
+}
+
+static bool isMyCode(const SymbolGroup &Group) {
+ if (Group.getFile().isObj())
+ return true;
+
+ StringRef Name = Group.name();
+ if (Name.startswith("Import:"))
+ return false;
+ if (Name.endswith_lower(".dll"))
+ return false;
+ if (Name.equals_lower("* linker *"))
+ return false;
+ if (Name.startswith_lower("f:\\binaries\\Intermediate\\vctools"))
+ return false;
+ if (Name.startswith_lower("f:\\dd\\vctools\\crt"))
+ return false;
+ return true;
+}
+
+static bool shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group) {
+ if (opts::dump::JustMyCode && !isMyCode(Group))
+ return false;
+
+ // If the arg was not specified on the command line, always dump all modules.
+ if (opts::dump::DumpModi.getNumOccurrences() == 0)
+ return true;
+
+ // Otherwise, only dump if this is the same module specified.
+ return (opts::dump::DumpModi == Idx);
+}
+
+Error DumpOutputStyle::dumpStreamSummary() {
+ printHeader(P, "Streams");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+
+ if (StreamPurposes.empty())
+ discoverStreamPurposes(getPdb(), StreamPurposes);
+
+ uint32_t StreamCount = getPdb().getNumStreams();
+ uint32_t MaxStreamSize = getPdb().getMaxStreamSize();
+
+ for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ P.formatLine(
+ "Stream {0} ({1} bytes): [{2}]",
+ fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
+ fmt_align(getPdb().getStreamByteSize(StreamIdx), AlignStyle::Right,
+ NumDigits(MaxStreamSize)),
+ StreamPurposes[StreamIdx].getLongName());
+
+ if (opts::dump::DumpStreamBlocks) {
+ auto Blocks = getPdb().getStreamBlockList(StreamIdx);
+ std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
+ P.formatLine(" {0} Blocks: [{1}]",
+ fmt_repeat(' ', NumDigits(StreamCount)),
+ make_range(BV.begin(), BV.end()));
+ }
+ }
+
+ return Error::success();
+}
+
+static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
+ uint32_t Index) {
+ ExitOnError Err("Unexpected error: ");
+
+ auto &Dbi = Err(File.getPDBDbiStream());
+ const auto &Modules = Dbi.modules();
+ auto Modi = Modules.getModuleDescriptor(Index);
+
+ 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);
+}
+
+template <typename CallbackT>
+static void
+iterateOneModule(InputFile &File, const Optional<PrintScope> &HeaderScope,
+ const SymbolGroup &SG, uint32_t Modi, CallbackT Callback) {
+ if (HeaderScope) {
+ HeaderScope->P.formatLine(
+ "Mod {0:4} | `{1}`: ",
+ fmt_align(Modi, AlignStyle::Right, HeaderScope->LabelWidth), SG.name());
+ }
+
+ AutoIndent Indent(HeaderScope);
+ Callback(Modi, SG);
+}
+
+template <typename CallbackT>
+static void iterateSymbolGroups(InputFile &Input,
+ const Optional<PrintScope> &HeaderScope,
+ CallbackT Callback) {
+ AutoIndent Indent(HeaderScope);
+
+ ExitOnError Err("Unexpected error processing modules: ");
+
+ if (opts::dump::DumpModi.getNumOccurrences() > 0) {
+ assert(opts::dump::DumpModi.getNumOccurrences() == 1);
+ uint32_t Modi = opts::dump::DumpModi;
+ SymbolGroup SG(&Input, Modi);
+ iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(Modi)), SG,
+ Modi, Callback);
+ return;
+ }
+
+ uint32_t I = 0;
+
+ for (const auto &SG : Input.symbol_groups()) {
+ if (shouldDumpSymbolGroup(I, SG))
+ iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(I)), SG, I,
+ Callback);
+
+ ++I;
+ }
+}
+
+template <typename SubsectionT>
+static void iterateModuleSubsections(
+ InputFile &File, const Optional<PrintScope> &HeaderScope,
+ llvm::function_ref<void(uint32_t, const SymbolGroup &, SubsectionT &)>
+ Callback) {
+
+ iterateSymbolGroups(File, HeaderScope,
+ [&](uint32_t Modi, const SymbolGroup &SG) {
+ for (const auto &SS : SG.getDebugSubsections()) {
+ SubsectionT Subsection;
+
+ if (SS.kind() != Subsection.kind())
+ continue;
+
+ BinaryStreamReader Reader(SS.getRecordData());
+ if (auto EC = Subsection.initialize(Reader))
+ continue;
+ Callback(Modi, SG, Subsection);
+ }
+ });
+}
+
+static Expected<std::pair<std::unique_ptr<MappedBlockStream>,
+ ArrayRef<llvm::object::coff_section>>>
+loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
+ if (!File.hasPDBDbiStream())
+ return make_error<StringError>(
+ "Section headers require a DBI Stream, which could not be loaded",
+ inconvertibleErrorCode());
+
+ auto &Dbi = cantFail(File.getPDBDbiStream());
+ uint32_t SI = Dbi.getDebugStreamIndex(Type);
+
+ if (SI == kInvalidStreamIndex)
+ return make_error<StringError>(
+ "PDB does not contain the requested image section header type",
+ inconvertibleErrorCode());
+
+ auto Stream = File.createIndexedStream(SI);
+ if (!Stream)
+ return make_error<StringError>("Could not load the required stream data",
+ inconvertibleErrorCode());
+
+ ArrayRef<object::coff_section> Headers;
+ if (Stream->getLength() % sizeof(object::coff_section) != 0)
+ return make_error<StringError>(
+ "Section header array size is not a multiple of section header size",
+ inconvertibleErrorCode());
+
+ uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
+ BinaryStreamReader Reader(*Stream);
+ cantFail(Reader.readArray(Headers, NumHeaders));
+ return std::make_pair(std::move(Stream), Headers);
+}
+
+static std::vector<std::string> getSectionNames(PDBFile &File) {
+ auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
+ if (!ExpectedHeaders)
+ return {};
+
+ std::unique_ptr<MappedBlockStream> Stream;
+ ArrayRef<object::coff_section> Headers;
+ std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
+ std::vector<std::string> Names;
+ for (const auto &H : Headers)
+ Names.push_back(H.Name);
+ return Names;
+}
+
+static void dumpSectionContrib(LinePrinter &P, const SectionContrib &SC,
+ ArrayRef<std::string> SectionNames,
+ uint32_t FieldWidth) {
+ std::string NameInsert;
+ if (SC.ISect > 0 && SC.ISect <= SectionNames.size()) {
+ StringRef SectionName = SectionNames[SC.ISect - 1];
+ NameInsert = formatv("[{0}]", SectionName).str();
+ } else
+ NameInsert = "[???]";
+ P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
+ "crc = {4}",
+ formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
+ fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
+ fmt_align(NameInsert, AlignStyle::Left, FieldWidth + 2));
+ AutoIndent Indent(P, FieldWidth + 2);
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Characteristics, 3, " | "));
+}
+
+static void dumpSectionContrib(LinePrinter &P, const SectionContrib2 &SC,
+ ArrayRef<std::string> SectionNames,
+ uint32_t FieldWidth) {
+ P.formatLine("SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
+ "crc = {4}, coff section = {5}",
+ formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
+ fmtle(SC.Base.Size), fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc),
+ fmtle(SC.Base.RelocCrc), fmtle(SC.ISectCoff));
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Base.Characteristics, 3, " | "));
+}
+
+Error DumpOutputStyle::dumpModules() {
+ printHeader(P, "Modules");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Unexpected error processing modules: ");
+
+ auto &Stream = Err(getPdb().getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ iterateSymbolGroups(
+ File, PrintScope{P, 11}, [&](uint32_t Modi, const SymbolGroup &Strings) {
+ auto Desc = Modules.getModuleDescriptor(Modi);
+ if (opts::dump::DumpSectionContribs) {
+ std::vector<std::string> Sections = getSectionNames(getPdb());
+ dumpSectionContrib(P, Desc.getSectionContrib(), Sections, 0);
+ }
+ P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
+ P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
+ Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
+ Desc.hasECInfo());
+ StringRef PdbFilePath =
+ Err(Stream.getECName(Desc.getPdbFilePathNameIndex()));
+ StringRef SrcFilePath =
+ Err(Stream.getECName(Desc.getSourceFileNameIndex()));
+ P.formatLine("pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
+ Desc.getPdbFilePathNameIndex(), PdbFilePath,
+ Desc.getSourceFileNameIndex(), SrcFilePath);
+ });
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpModuleFiles() {
+ printHeader(P, "Files");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ ExitOnError Err("Unexpected error processing modules: ");
+
+ iterateSymbolGroups(File, PrintScope{P, 11},
+ [this, &Err](uint32_t Modi, const SymbolGroup &Strings) {
+ auto &Stream = Err(getPdb().getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ for (const auto &F : Modules.source_files(Modi)) {
+ Strings.formatFromFileName(P, F);
+ }
+ });
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpSymbolStats() {
+ printHeader(P, "Module Stats");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ ExitOnError Err("Unexpected error processing modules: ");
+
+ StatCollection SymStats;
+ StatCollection ChunkStats;
+
+ Optional<PrintScope> Scope;
+ if (File.isPdb())
+ Scope.emplace(P, 2);
+
+ iterateSymbolGroups(File, Scope, [&](uint32_t Modi, const SymbolGroup &SG) {
+ StatCollection SS = getSymbolStats(SG, SymStats);
+ StatCollection CS = getChunkStats(SG, ChunkStats);
+
+ if (SG.getFile().isPdb()) {
+ AutoIndent Indent(P);
+ auto Modules = cantFail(File.pdb().getPDBDbiStream()).modules();
+ uint32_t ModCount = Modules.getModuleCount();
+ DbiModuleDescriptor Desc = Modules.getModuleDescriptor(Modi);
+ uint32_t StreamIdx = Desc.getModuleStreamIndex();
+
+ if (StreamIdx == kInvalidStreamIndex) {
+ P.formatLine("Mod {0} (debug info not present): [{1}]",
+ fmt_align(Modi, AlignStyle::Right, NumDigits(ModCount)),
+ Desc.getModuleName());
+ return;
+ }
+ P.formatLine("Stream {0}, {1} bytes", StreamIdx,
+ getPdb().getStreamByteSize(StreamIdx));
+
+ printModuleDetailStats<SymbolKind>(P, "Symbols", SS);
+ printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", CS);
+ }
+ });
+
+ if (SymStats.Totals.Count > 0) {
+ P.printLine(" Summary |");
+ AutoIndent Indent(P, 4);
+ printModuleDetailStats<SymbolKind>(P, "Symbols", SymStats);
+ printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", ChunkStats);
+ }
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpTypeStats() {
+ printHeader(P, "Type Record Stats");
+
+ // Iterate the types, categorize by kind, accumulate size stats.
+ StatCollection TypeStats;
+ LazyRandomTypeCollection &Types =
+ opts::dump::DumpTypeStats ? File.types() : File.ids();
+ for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
+ CVType Type = Types.getType(*TI);
+ TypeStats.update(uint32_t(Type.kind()), Type.length());
+ }
+
+ P.NewLine();
+ P.formatLine(" Types");
+ AutoIndent Indent(P);
+ P.formatLine("{0,16}: {1,7} entries ({2,12:N} bytes, {3,7} avg)", "Total",
+ TypeStats.Totals.Count, TypeStats.Totals.Size,
+ (double)TypeStats.Totals.Size / TypeStats.Totals.Count);
+ P.formatLine("{0}", fmt_repeat('-', 74));
+
+ for (const auto &K : TypeStats.getStatsSortedBySize()) {
+ P.formatLine("{0,16}: {1,7} entries ({2,12:N} bytes, {3,7} avg)",
+ formatTypeLeafKind(TypeLeafKind(K.first)), K.second.Count,
+ K.second.Size, (double)K.second.Size / K.second.Count);
+ }
+ return Error::success();
+}
+
+static bool isValidNamespaceIdentifier(StringRef S) {
+ if (S.empty())
+ return false;
+
+ if (std::isdigit(S[0]))
+ return false;
+
+ return llvm::all_of(S, [](char C) { return std::isalnum(C); });
+}
+
+namespace {
+constexpr uint32_t kNoneUdtKind = 0;
+constexpr uint32_t kSimpleUdtKind = 1;
+constexpr uint32_t kUnknownUdtKind = 2;
+} // namespace
+
+static std::string getUdtStatLabel(uint32_t Kind) {
+ if (Kind == kNoneUdtKind)
+ return "<none type>";
+
+ if (Kind == kSimpleUdtKind)
+ return "<simple type>";
+
+ if (Kind == kUnknownUdtKind)
+ return "<unknown type>";
+
+ return formatTypeLeafKind(static_cast<TypeLeafKind>(Kind));
+}
+
+static uint32_t getLongestTypeLeafName(const StatCollection &Stats) {
+ size_t L = 0;
+ for (const auto &Stat : Stats.Individual) {
+ std::string Label = getUdtStatLabel(Stat.first);
+ L = std::max(L, Label.size());
+ }
+ return static_cast<uint32_t>(L);
+}
+
+Error DumpOutputStyle::dumpUdtStats() {
+ printHeader(P, "S_UDT Record Stats");
+
+ if (File.isPdb() && !getPdb().hasPDBGlobalsStream()) {
+ printStreamNotPresent("Globals");
+ return Error::success();
+ }
+
+ StatCollection UdtStats;
+ StatCollection UdtTargetStats;
+ AutoIndent Indent(P, 4);
+
+ auto &TpiTypes = File.types();
+
+ StringMap<StatCollection::Stat> NamespacedStats;
+
+ size_t LongestNamespace = 0;
+ auto HandleOneSymbol = [&](const CVSymbol &Sym) {
+ if (Sym.kind() != SymbolKind::S_UDT)
+ return;
+ UdtStats.update(SymbolKind::S_UDT, Sym.length());
+
+ UDTSym UDT = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(Sym));
+
+ uint32_t Kind = 0;
+ uint32_t RecordSize = 0;
+
+ if (UDT.Type.isNoneType())
+ Kind = kNoneUdtKind;
+ else if (UDT.Type.isSimple())
+ Kind = kSimpleUdtKind;
+ else if (Optional<CVType> T = TpiTypes.tryGetType(UDT.Type)) {
+ Kind = T->kind();
+ RecordSize = T->length();
+ } else
+ Kind = kUnknownUdtKind;
+
+ UdtTargetStats.update(Kind, RecordSize);
+
+ size_t Pos = UDT.Name.find("::");
+ if (Pos == StringRef::npos)
+ return;
+
+ StringRef Scope = UDT.Name.take_front(Pos);
+ if (Scope.empty() || !isValidNamespaceIdentifier(Scope))
+ return;
+
+ LongestNamespace = std::max(LongestNamespace, Scope.size());
+ NamespacedStats[Scope].update(RecordSize);
+ };
+
+ P.NewLine();
+
+ if (File.isPdb()) {
+ auto &SymbolRecords = cantFail(getPdb().getPDBSymbolStream());
+ auto ExpGlobals = getPdb().getPDBGlobalsStream();
+ if (!ExpGlobals)
+ return ExpGlobals.takeError();
+
+ for (uint32_t PubSymOff : ExpGlobals->getGlobalsTable()) {
+ CVSymbol Sym = SymbolRecords.readRecord(PubSymOff);
+ HandleOneSymbol(Sym);
+ }
+ } else {
+ for (const auto &Sec : File.symbol_groups()) {
+ for (const auto &SS : Sec.getDebugSubsections()) {
+ if (SS.kind() != DebugSubsectionKind::Symbols)
+ continue;
+
+ DebugSymbolsSubsectionRef Symbols;
+ BinaryStreamReader Reader(SS.getRecordData());
+ cantFail(Symbols.initialize(Reader));
+ for (const auto &S : Symbols)
+ HandleOneSymbol(S);
+ }
+ }
+ }
+
+ LongestNamespace += StringRef(" namespace ''").size();
+ size_t LongestTypeLeafKind = getLongestTypeLeafName(UdtTargetStats);
+ size_t FieldWidth = std::max(LongestNamespace, LongestTypeLeafKind);
+
+ // Compute the max number of digits for count and size fields, including comma
+ // separators.
+ StringRef CountHeader("Count");
+ StringRef SizeHeader("Size");
+ size_t CD = NumDigits(UdtStats.Totals.Count);
+ CD += (CD - 1) / 3;
+ CD = std::max(CD, CountHeader.size());
+
+ size_t SD = NumDigits(UdtStats.Totals.Size);
+ SD += (SD - 1) / 3;
+ SD = std::max(SD, SizeHeader.size());
+
+ uint32_t TableWidth = FieldWidth + 3 + CD + 2 + SD + 1;
+
+ P.formatLine("{0} | {1} {2}",
+ fmt_align("Record Kind", AlignStyle::Right, FieldWidth),
+ fmt_align(CountHeader, AlignStyle::Right, CD),
+ fmt_align(SizeHeader, AlignStyle::Right, SD));
+
+ P.formatLine("{0}", fmt_repeat('-', TableWidth));
+ for (const auto &Stat : UdtTargetStats.getStatsSortedBySize()) {
+ std::string Label = getUdtStatLabel(Stat.first);
+ P.formatLine("{0} | {1:N} {2:N}",
+ fmt_align(Label, AlignStyle::Right, FieldWidth),
+ fmt_align(Stat.second.Count, AlignStyle::Right, CD),
+ fmt_align(Stat.second.Size, AlignStyle::Right, SD));
+ }
+ P.formatLine("{0}", fmt_repeat('-', TableWidth));
+ P.formatLine("{0} | {1:N} {2:N}",
+ fmt_align("Total (S_UDT)", AlignStyle::Right, FieldWidth),
+ fmt_align(UdtStats.Totals.Count, AlignStyle::Right, CD),
+ fmt_align(UdtStats.Totals.Size, AlignStyle::Right, SD));
+ P.formatLine("{0}", fmt_repeat('-', TableWidth));
+ struct StrAndStat {
+ StringRef Key;
+ StatCollection::Stat Stat;
+ };
+
+ // Print namespace stats in descending order of size.
+ std::vector<StrAndStat> NamespacedStatsSorted;
+ for (const auto &Stat : NamespacedStats)
+ NamespacedStatsSorted.push_back({Stat.getKey(), Stat.second});
+ llvm::stable_sort(NamespacedStatsSorted,
+ [](const StrAndStat &L, const StrAndStat &R) {
+ return L.Stat.Size > R.Stat.Size;
+ });
+ for (const auto &Stat : NamespacedStatsSorted) {
+ std::string Label = std::string(formatv("namespace '{0}'", Stat.Key));
+ P.formatLine("{0} | {1:N} {2:N}",
+ fmt_align(Label, AlignStyle::Right, FieldWidth),
+ fmt_align(Stat.Stat.Count, AlignStyle::Right, CD),
+ fmt_align(Stat.Stat.Size, AlignStyle::Right, SD));
+ }
+ return Error::success();
+}
+
+static void typesetLinesAndColumns(LinePrinter &P, uint32_t Start,
+ const LineColumnEntry &E) {
+ const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
+ uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
+
+ // Let's try to keep it under 100 characters
+ constexpr uint32_t kMaxRowLength = 100;
+ // At least 3 spaces between columns.
+ uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
+ uint32_t ItemsLeft = E.LineNumbers.size();
+ auto LineIter = E.LineNumbers.begin();
+ while (ItemsLeft != 0) {
+ uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
+ for (uint32_t I = 0; I < RowColumns; ++I) {
+ LineInfo Line(LineIter->Flags);
+ std::string LineStr;
+ if (Line.isAlwaysStepInto())
+ LineStr = "ASI";
+ else if (Line.isNeverStepInto())
+ LineStr = "NSI";
+ else
+ LineStr = utostr(Line.getStartLine());
+ char Statement = Line.isStatement() ? ' ' : '!';
+ P.format("{0} {1:X-} {2} ",
+ fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
+ fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
+ Statement);
+ ++LineIter;
+ --ItemsLeft;
+ }
+ P.NewLine();
+ }
+}
+
+Error DumpOutputStyle::dumpLines() {
+ printHeader(P, "Lines");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ uint32_t LastModi = UINT32_MAX;
+ uint32_t LastNameIndex = UINT32_MAX;
+ iterateModuleSubsections<DebugLinesSubsectionRef>(
+ File, PrintScope{P, 4},
+ [this, &LastModi, &LastNameIndex](uint32_t Modi,
+ const SymbolGroup &Strings,
+ DebugLinesSubsectionRef &Lines) {
+ uint16_t Segment = Lines.header()->RelocSegment;
+ uint32_t Begin = Lines.header()->RelocOffset;
+ uint32_t End = Begin + Lines.header()->CodeSize;
+ for (const auto &Block : Lines) {
+ if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
+ LastModi = Modi;
+ LastNameIndex = Block.NameIndex;
+ Strings.formatFromChecksumsOffset(P, Block.NameIndex);
+ }
+
+ AutoIndent Indent(P, 2);
+ P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
+ uint32_t Count = Block.LineNumbers.size();
+ if (Lines.hasColumnInfo())
+ P.format("line/column/addr entries = {0}", Count);
+ else
+ P.format("line/addr entries = {0}", Count);
+
+ P.NewLine();
+ typesetLinesAndColumns(P, Begin, Block);
+ }
+ });
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpInlineeLines() {
+ printHeader(P, "Inlinee Lines");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
+ File, PrintScope{P, 2},
+ [this](uint32_t Modi, const SymbolGroup &Strings,
+ DebugInlineeLinesSubsectionRef &Lines) {
+ P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
+ for (const auto &Entry : Lines) {
+ P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
+ fmtle(Entry.Header->SourceLineNum));
+ Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
+ for (const auto &ExtraFileID : Entry.ExtraFiles) {
+ P.formatLine(" ");
+ Strings.formatFromChecksumsOffset(P, ExtraFileID, true);
+ }
+ }
+ P.NewLine();
+ });
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpXmi() {
+ printHeader(P, "Cross Module Imports");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
+ File, PrintScope{P, 2},
+ [this](uint32_t Modi, const SymbolGroup &Strings,
+ DebugCrossModuleImportsSubsectionRef &Imports) {
+ P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
+
+ for (const auto &Xmi : Imports) {
+ auto ExpectedModule =
+ Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
+ StringRef Module;
+ SmallString<32> ModuleStorage;
+ if (!ExpectedModule) {
+ Module = "(unknown module)";
+ consumeError(ExpectedModule.takeError());
+ } else
+ Module = *ExpectedModule;
+ if (Module.size() > 32) {
+ ModuleStorage = "...";
+ ModuleStorage += Module.take_back(32 - 3);
+ Module = ModuleStorage;
+ }
+ std::vector<std::string> TIs;
+ for (const auto I : Xmi.Imports)
+ TIs.push_back(std::string(formatv("{0,+10:X+}", fmtle(I))));
+ std::string Result =
+ typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
+ P.formatLine("{0,+32} | {1}", Module, Result);
+ }
+ });
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpXme() {
+ printHeader(P, "Cross Module Exports");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
+ File, PrintScope{P, 2},
+ [this](uint32_t Modi, const SymbolGroup &Strings,
+ DebugCrossModuleExportsSubsectionRef &Exports) {
+ P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
+ for (const auto &Export : Exports) {
+ P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
+ TypeIndex(Export.Global));
+ }
+ });
+
+ return Error::success();
+}
+
+std::string formatFrameType(object::frame_type FT) {
+ switch (FT) {
+ case object::frame_type::Fpo:
+ return "FPO";
+ case object::frame_type::NonFpo:
+ return "Non-FPO";
+ case object::frame_type::Trap:
+ return "Trap";
+ case object::frame_type::Tss:
+ return "TSS";
+ }
+ return "<unknown>";
+}
+
+Error DumpOutputStyle::dumpOldFpo(PDBFile &File) {
+ printHeader(P, "Old FPO Data");
+
+ ExitOnError Err("Error dumping old fpo data:");
+ auto &Dbi = Err(File.getPDBDbiStream());
+
+ if (!Dbi.hasOldFpoRecords()) {
+ printStreamNotPresent("FPO");
+ return Error::success();
+ }
+
+ const FixedStreamArray<object::FpoData>& Records = Dbi.getOldFpoRecords();
+
+ P.printLine(" RVA | Code | Locals | Params | Prolog | Saved Regs | Use "
+ "BP | Has SEH | Frame Type");
+
+ for (const object::FpoData &FD : Records) {
+ P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,6} | {5,10} | {6,6} | "
+ "{7,7} | {8,9}",
+ uint32_t(FD.Offset), uint32_t(FD.Size), uint32_t(FD.NumLocals),
+ uint32_t(FD.NumParams), FD.getPrologSize(),
+ FD.getNumSavedRegs(), FD.useBP(), FD.hasSEH(),
+ formatFrameType(FD.getFP()));
+ }
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpNewFpo(PDBFile &File) {
+ printHeader(P, "New FPO Data");
+
+ ExitOnError Err("Error dumping new fpo data:");
+ auto &Dbi = Err(File.getPDBDbiStream());
+
+ if (!Dbi.hasNewFpoRecords()) {
+ printStreamNotPresent("New FPO");
+ return Error::success();
+ }
+
+ const DebugFrameDataSubsectionRef& FDS = Dbi.getNewFpoRecords();
+
+ P.printLine(" RVA | Code | Locals | Params | Stack | Prolog | Saved Regs "
+ "| Has SEH | Has C++EH | Start | Program");
+ for (const FrameData &FD : FDS) {
+ bool IsFuncStart = FD.Flags & FrameData::IsFunctionStart;
+ bool HasEH = FD.Flags & FrameData::HasEH;
+ bool HasSEH = FD.Flags & FrameData::HasSEH;
+
+ auto &StringTable = Err(File.getStringTable());
+
+ auto Program = Err(StringTable.getStringForID(FD.FrameFunc));
+ P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,5} | {5,6} | {6,10} | "
+ "{7,7} | {8,9} | {9,5} | {10}",
+ uint32_t(FD.RvaStart), uint32_t(FD.CodeSize),
+ uint32_t(FD.LocalSize), uint32_t(FD.ParamsSize),
+ uint32_t(FD.MaxStackSize), uint16_t(FD.PrologSize),
+ uint16_t(FD.SavedRegsSize), HasSEH, HasEH, IsFuncStart,
+ Program);
+ }
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpFpo() {
+ if (!File.isPdb()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ PDBFile &File = getPdb();
+ if (!File.hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ if (auto EC = dumpOldFpo(File))
+ return EC;
+ if (auto EC = dumpNewFpo(File))
+ return EC;
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpStringTableFromPdb() {
+ AutoIndent Indent(P);
+ auto IS = getPdb().getStringTable();
+ if (!IS) {
+ P.formatLine("Not present in file");
+ consumeError(IS.takeError());
+ return Error::success();
+ }
+
+ if (opts::dump::DumpStringTable) {
+ if (IS->name_ids().empty())
+ P.formatLine("Empty");
+ else {
+ auto MaxID =
+ std::max_element(IS->name_ids().begin(), IS->name_ids().end());
+ uint32_t Digits = NumDigits(*MaxID);
+
+ P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
+ "String");
+
+ std::vector<uint32_t> SortedIDs(IS->name_ids().begin(),
+ IS->name_ids().end());
+ llvm::sort(SortedIDs);
+ for (uint32_t I : SortedIDs) {
+ auto ES = IS->getStringForID(I);
+ llvm::SmallString<32> Str;
+ if (!ES) {
+ consumeError(ES.takeError());
+ Str = "Error reading string";
+ } else if (!ES->empty()) {
+ Str.append("'");
+ Str.append(*ES);
+ Str.append("'");
+ }
+
+ if (!Str.empty())
+ P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits),
+ Str);
+ }
+ }
+ }
+
+ if (opts::dump::DumpStringTableDetails) {
+ P.NewLine();
+ {
+ P.printLine("String Table Header:");
+ AutoIndent Indent(P);
+ P.formatLine("Signature: {0}", IS->getSignature());
+ P.formatLine("Hash Version: {0}", IS->getHashVersion());
+ P.formatLine("Name Buffer Size: {0}", IS->getByteSize());
+ P.NewLine();
+ }
+
+ BinaryStreamRef NameBuffer = IS->getStringTable().getBuffer();
+ ArrayRef<uint8_t> Contents;
+ cantFail(NameBuffer.readBytes(0, NameBuffer.getLength(), Contents));
+ P.formatBinary("Name Buffer", Contents, 0);
+ P.NewLine();
+ {
+ P.printLine("Hash Table:");
+ AutoIndent Indent(P);
+ P.formatLine("Bucket Count: {0}", IS->name_ids().size());
+ for (const auto &Entry : enumerate(IS->name_ids()))
+ P.formatLine("Bucket[{0}] : {1}", Entry.index(),
+ uint32_t(Entry.value()));
+ P.formatLine("Name Count: {0}", IS->getNameCount());
+ }
+ }
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpStringTableFromObj() {
+ iterateModuleSubsections<DebugStringTableSubsectionRef>(
+ File, PrintScope{P, 4},
+ [&](uint32_t Modi, const SymbolGroup &Strings,
+ DebugStringTableSubsectionRef &Strings2) {
+ BinaryStreamRef StringTableBuffer = Strings2.getBuffer();
+ BinaryStreamReader Reader(StringTableBuffer);
+ while (Reader.bytesRemaining() > 0) {
+ StringRef Str;
+ uint32_t Offset = Reader.getOffset();
+ cantFail(Reader.readCString(Str));
+ if (Str.empty())
+ continue;
+
+ P.formatLine("{0} | {1}", fmt_align(Offset, AlignStyle::Right, 4),
+ Str);
+ }
+ });
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpNamedStreams() {
+ printHeader(P, "Named Streams");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Invalid PDB File: ");
+
+ auto &IS = Err(File.pdb().getPDBInfoStream());
+ const NamedStreamMap &NS = IS.getNamedStreams();
+ for (const auto &Entry : NS.entries()) {
+ P.printLine(Entry.getKey());
+ AutoIndent Indent2(P, 2);
+ P.formatLine("Index: {0}", Entry.getValue());
+ P.formatLine("Size in bytes: {0}",
+ File.pdb().getStreamByteSize(Entry.getValue()));
+ }
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpStringTable() {
+ printHeader(P, "String Table");
+
+ if (File.isPdb())
+ return dumpStringTableFromPdb();
+
+ return dumpStringTableFromObj();
+}
+
+static void buildDepSet(LazyRandomTypeCollection &Types,
+ ArrayRef<TypeIndex> Indices,
+ std::map<TypeIndex, CVType> &DepSet) {
+ SmallVector<TypeIndex, 4> DepList;
+ for (const auto &I : Indices) {
+ TypeIndex TI(I);
+ if (DepSet.find(TI) != DepSet.end() || TI.isSimple() || TI.isNoneType())
+ continue;
+
+ CVType Type = Types.getType(TI);
+ DepSet[TI] = Type;
+ codeview::discoverTypeIndices(Type, DepList);
+ buildDepSet(Types, DepList, DepSet);
+ }
+}
+
+static void
+dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types,
+ TypeReferenceTracker *RefTracker, uint32_t NumTypeRecords,
+ uint32_t NumHashBuckets,
+ FixedStreamArray<support::ulittle32_t> HashValues,
+ TpiStream *Stream, bool Bytes, bool Extras) {
+
+ Printer.formatLine("Showing {0:N} records", NumTypeRecords);
+ uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex + NumTypeRecords);
+
+ MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker,
+ NumHashBuckets, HashValues, Stream);
+
+ if (auto EC = codeview::visitTypeStream(Types, V)) {
+ Printer.formatLine("An error occurred dumping type records: {0}",
+ toString(std::move(EC)));
+ }
+}
+
+static void dumpPartialTypeStream(LinePrinter &Printer,
+ LazyRandomTypeCollection &Types,
+ TypeReferenceTracker *RefTracker,
+ TpiStream &Stream, ArrayRef<TypeIndex> TiList,
+ bool Bytes, bool Extras, bool Deps) {
+ uint32_t Width =
+ NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
+
+ MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker,
+ Stream.getNumHashBuckets(), Stream.getHashValues(),
+ &Stream);
+
+ if (opts::dump::DumpTypeDependents) {
+ // If we need to dump all dependents, then iterate each index and find
+ // all dependents, adding them to a map ordered by TypeIndex.
+ std::map<TypeIndex, CVType> DepSet;
+ buildDepSet(Types, TiList, DepSet);
+
+ Printer.formatLine(
+ "Showing {0:N} records and their dependents ({1:N} records total)",
+ TiList.size(), DepSet.size());
+
+ for (auto &Dep : DepSet) {
+ if (auto EC = codeview::visitTypeRecord(Dep.second, Dep.first, V))
+ Printer.formatLine("An error occurred dumping type record {0}: {1}",
+ Dep.first, toString(std::move(EC)));
+ }
+ } else {
+ Printer.formatLine("Showing {0:N} records.", TiList.size());
+
+ for (const auto &I : TiList) {
+ TypeIndex TI(I);
+ CVType Type = Types.getType(TI);
+ if (auto EC = codeview::visitTypeRecord(Type, TI, V))
+ Printer.formatLine("An error occurred dumping type record {0}: {1}", TI,
+ toString(std::move(EC)));
+ }
+ }
+}
+
+Error DumpOutputStyle::dumpTypesFromObjectFile() {
+ LazyRandomTypeCollection Types(100);
+
+ for (const auto &S : getObj().sections()) {
+ Expected<StringRef> NameOrErr = S.getName();
+ if (!NameOrErr)
+ return NameOrErr.takeError();
+ StringRef SectionName = *NameOrErr;
+
+ // .debug$T is a standard CodeView type section, while .debug$P is the same
+ // format but used for MSVC precompiled header object files.
+ if (SectionName == ".debug$T")
+ printHeader(P, "Types (.debug$T)");
+ else if (SectionName == ".debug$P")
+ printHeader(P, "Precompiled Types (.debug$P)");
+ else
+ continue;
+
+ Expected<StringRef> ContentsOrErr = S.getContents();
+ if (!ContentsOrErr)
+ return ContentsOrErr.takeError();
+
+ uint32_t Magic;
+ BinaryStreamReader Reader(*ContentsOrErr, llvm::support::little);
+ if (auto EC = Reader.readInteger(Magic))
+ return EC;
+ if (Magic != COFF::DEBUG_SECTION_MAGIC)
+ return make_error<StringError>("Invalid CodeView debug section.",
+ inconvertibleErrorCode());
+
+ Types.reset(Reader, 100);
+
+ if (opts::dump::DumpTypes) {
+ dumpFullTypeStream(P, Types, RefTracker.get(), 0, 0, {}, nullptr,
+ opts::dump::DumpTypeData, false);
+ } else if (opts::dump::DumpTypeExtras) {
+ auto LocalHashes = LocallyHashedType::hashTypeCollection(Types);
+ auto GlobalHashes = GloballyHashedType::hashTypeCollection(Types);
+ assert(LocalHashes.size() == GlobalHashes.size());
+
+ P.formatLine("Local / Global hashes:");
+ TypeIndex TI(TypeIndex::FirstNonSimpleIndex);
+ for (auto H : zip(LocalHashes, GlobalHashes)) {
+ AutoIndent Indent2(P);
+ LocallyHashedType &L = std::get<0>(H);
+ GloballyHashedType &G = std::get<1>(H);
+
+ P.formatLine("TI: {0}, LocalHash: {1:X}, GlobalHash: {2}", TI, L, G);
+
+ ++TI;
+ }
+ P.NewLine();
+ }
+ }
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
+ assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
+
+ if (StreamIdx == StreamTPI) {
+ printHeader(P, "Types (TPI Stream)");
+ } else if (StreamIdx == StreamIPI) {
+ printHeader(P, "Types (IPI Stream)");
+ }
+
+ assert(!File.isObj());
+
+ bool Present = false;
+ bool DumpTypes = false;
+ bool DumpBytes = false;
+ bool DumpExtras = false;
+ std::vector<uint32_t> Indices;
+ if (StreamIdx == StreamTPI) {
+ Present = getPdb().hasPDBTpiStream();
+ DumpTypes = opts::dump::DumpTypes;
+ DumpBytes = opts::dump::DumpTypeData;
+ DumpExtras = opts::dump::DumpTypeExtras;
+ Indices.assign(opts::dump::DumpTypeIndex.begin(),
+ opts::dump::DumpTypeIndex.end());
+ } else if (StreamIdx == StreamIPI) {
+ Present = getPdb().hasPDBIpiStream();
+ DumpTypes = opts::dump::DumpIds;
+ DumpBytes = opts::dump::DumpIdData;
+ DumpExtras = opts::dump::DumpIdExtras;
+ Indices.assign(opts::dump::DumpIdIndex.begin(),
+ opts::dump::DumpIdIndex.end());
+ }
+
+ if (!Present) {
+ printStreamNotPresent(StreamIdx == StreamTPI ? "TPI" : "IPI");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Unexpected error processing types: ");
+
+ auto &Stream = Err((StreamIdx == StreamTPI) ? getPdb().getPDBTpiStream()
+ : getPdb().getPDBIpiStream());
+
+ auto &Types = (StreamIdx == StreamTPI) ? File.types() : File.ids();
+
+ // Only emit notes about referenced/unreferenced for types.
+ TypeReferenceTracker *MaybeTracker =
+ (StreamIdx == StreamTPI) ? RefTracker.get() : nullptr;
+
+ // Enable resolving forward decls.
+ Stream.buildHashMap();
+
+ if (DumpTypes || !Indices.empty()) {
+ if (Indices.empty())
+ dumpFullTypeStream(P, Types, MaybeTracker, Stream.getNumTypeRecords(),
+ Stream.getNumHashBuckets(), Stream.getHashValues(),
+ &Stream, DumpBytes, DumpExtras);
+ else {
+ std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
+ dumpPartialTypeStream(P, Types, MaybeTracker, Stream, TiList, DumpBytes,
+ DumpExtras, opts::dump::DumpTypeDependents);
+ }
+ }
+
+ if (DumpExtras) {
+ P.NewLine();
+
+ P.formatLine("Header Version: {0}",
+ static_cast<uint32_t>(Stream.getTpiVersion()));
+ P.formatLine("Hash Stream Index: {0}", Stream.getTypeHashStreamIndex());
+ P.formatLine("Aux Hash Stream Index: {0}",
+ Stream.getTypeHashStreamAuxIndex());
+ P.formatLine("Hash Key Size: {0}", Stream.getHashKeySize());
+ P.formatLine("Num Hash Buckets: {0}", Stream.getNumHashBuckets());
+
+ auto IndexOffsets = Stream.getTypeIndexOffsets();
+ P.formatLine("Type Index Offsets:");
+ for (const auto &IO : IndexOffsets) {
+ AutoIndent Indent2(P);
+ P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
+ }
+
+ if (getPdb().hasPDBStringTable()) {
+ P.NewLine();
+ P.formatLine("Hash Adjusters:");
+ auto &Adjusters = Stream.getHashAdjusters();
+ auto &Strings = Err(getPdb().getStringTable());
+ for (const auto &A : Adjusters) {
+ AutoIndent Indent2(P);
+ auto ExpectedStr = Strings.getStringForID(A.first);
+ TypeIndex TI(A.second);
+ if (ExpectedStr)
+ P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
+ else {
+ P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
+ consumeError(ExpectedStr.takeError());
+ }
+ }
+ }
+ }
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpModuleSymsForObj() {
+ printHeader(P, "Symbols");
+
+ AutoIndent Indent(P);
+
+ ExitOnError Err("Unexpected error processing symbols: ");
+
+ auto &Types = File.types();
+
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::ObjectFile);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+ std::unique_ptr<llvm::Error> SymbolError;
+
+ iterateModuleSubsections<DebugSymbolsSubsectionRef>(
+ File, PrintScope{P, 2},
+ [&](uint32_t Modi, const SymbolGroup &Strings,
+ DebugSymbolsSubsectionRef &Symbols) {
+ Dumper.setSymbolGroup(&Strings);
+ for (auto Symbol : Symbols) {
+ if (auto EC = Visitor.visitSymbolRecord(Symbol)) {
+ SymbolError = std::make_unique<Error>(std::move(EC));
+ return;
+ }
+ }
+ });
+
+ if (SymbolError)
+ return std::move(*SymbolError);
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpModuleSymsForPdb() {
+ printHeader(P, "Symbols");
+
+ if (File.isPdb() && !getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Unexpected error processing symbols: ");
+
+ auto &Ids = File.ids();
+ auto &Types = File.types();
+
+ iterateSymbolGroups(
+ File, PrintScope{P, 2}, [&](uint32_t I, const SymbolGroup &Strings) {
+ auto ExpectedModS = getModuleDebugStream(File.pdb(), I);
+ if (!ExpectedModS) {
+ P.formatLine("Error loading module stream {0}. {1}", I,
+ toString(ExpectedModS.takeError()));
+ return;
+ }
+
+ ModuleDebugStreamRef &ModS = *ExpectedModS;
+
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Strings,
+ Ids, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ auto SS = ModS.getSymbolsSubstream();
+ if (auto EC =
+ Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) {
+ P.formatLine("Error while processing symbol records. {0}",
+ toString(std::move(EC)));
+ return;
+ }
+ });
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpTypeRefStats() {
+ printHeader(P, "Type Reference Statistics");
+ AutoIndent Indent(P);
+
+ // Sum the byte size of all type records, and the size and count of all
+ // referenced records.
+ size_t TotalRecs = File.types().size();
+ size_t RefRecs = 0;
+ size_t TotalBytes = 0;
+ size_t RefBytes = 0;
+ auto &Types = File.types();
+ for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
+ CVType Type = File.types().getType(*TI);
+ TotalBytes += Type.length();
+ if (RefTracker->isTypeReferenced(*TI)) {
+ ++RefRecs;
+ RefBytes += Type.length();
+ }
+ }
+
+ P.formatLine("Records referenced: {0:N} / {1:N} {2:P}", RefRecs, TotalRecs,
+ (double)RefRecs / TotalRecs);
+ P.formatLine("Bytes referenced: {0:N} / {1:N} {2:P}", RefBytes, TotalBytes,
+ (double)RefBytes / TotalBytes);
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpGSIRecords() {
+ printHeader(P, "GSI Records");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBSymbolStream()) {
+ printStreamNotPresent("GSI Common Symbol");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+
+ auto &Records = cantFail(getPdb().getPDBSymbolStream());
+ auto &Types = File.types();
+ auto &Ids = File.ids();
+
+ P.printLine("Records");
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+ BinaryStreamRef SymStream = Records.getSymbolArray().getUnderlyingStream();
+ if (auto E = Visitor.visitSymbolStream(Records.getSymbolArray(), 0))
+ return E;
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpGlobals() {
+ printHeader(P, "Global Symbols");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBGlobalsStream()) {
+ printStreamNotPresent("Globals");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Error dumping globals stream: ");
+ auto &Globals = Err(getPdb().getPDBGlobalsStream());
+
+ if (opts::dump::DumpGlobalNames.empty()) {
+ const GSIHashTable &Table = Globals.getGlobalsTable();
+ Err(dumpSymbolsFromGSI(Table, opts::dump::DumpGlobalExtras));
+ } else {
+ SymbolStream &SymRecords = cantFail(getPdb().getPDBSymbolStream());
+ auto &Types = File.types();
+ auto &Ids = File.ids();
+
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+ using ResultEntryType = std::pair<uint32_t, CVSymbol>;
+ for (StringRef Name : opts::dump::DumpGlobalNames) {
+ AutoIndent Indent(P);
+ P.formatLine("Global Name `{0}`", Name);
+ std::vector<ResultEntryType> Results =
+ Globals.findRecordsByName(Name, SymRecords);
+ if (Results.empty()) {
+ AutoIndent Indent(P);
+ P.printLine("(no matching records found)");
+ continue;
+ }
+
+ for (ResultEntryType Result : Results) {
+ if (auto E = Visitor.visitSymbolRecord(Result.second, Result.first))
+ return E;
+ }
+ }
+ }
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpPublics() {
+ printHeader(P, "Public Symbols");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBPublicsStream()) {
+ printStreamNotPresent("Publics");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Error dumping publics stream: ");
+ auto &Publics = Err(getPdb().getPDBPublicsStream());
+
+ const GSIHashTable &PublicsTable = Publics.getPublicsTable();
+ if (opts::dump::DumpPublicExtras) {
+ P.printLine("Publics Header");
+ AutoIndent Indent(P);
+ P.formatLine("sym hash = {0}, thunk table addr = {1}", Publics.getSymHash(),
+ formatSegmentOffset(Publics.getThunkTableSection(),
+ Publics.getThunkTableOffset()));
+ }
+ Err(dumpSymbolsFromGSI(PublicsTable, opts::dump::DumpPublicExtras));
+
+ // Skip the rest if we aren't dumping extras.
+ if (!opts::dump::DumpPublicExtras)
+ return Error::success();
+
+ P.formatLine("Address Map");
+ {
+ // These are offsets into the publics stream sorted by secidx:secrel.
+ AutoIndent Indent2(P);
+ for (uint32_t Addr : Publics.getAddressMap())
+ P.formatLine("off = {0}", Addr);
+ }
+
+ // The thunk map is optional debug info used for ILT thunks.
+ if (!Publics.getThunkMap().empty()) {
+ P.formatLine("Thunk Map");
+ AutoIndent Indent2(P);
+ for (uint32_t Addr : Publics.getThunkMap())
+ P.formatLine("{0:x8}", Addr);
+ }
+
+ // The section offsets table appears to be empty when incremental linking
+ // isn't in use.
+ if (!Publics.getSectionOffsets().empty()) {
+ P.formatLine("Section Offsets");
+ AutoIndent Indent2(P);
+ for (const SectionOffset &SO : Publics.getSectionOffsets())
+ P.formatLine("{0:x4}:{1:x8}", uint16_t(SO.Isect), uint32_t(SO.Off));
+ }
+
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
+ bool HashExtras) {
+ auto ExpectedSyms = getPdb().getPDBSymbolStream();
+ if (!ExpectedSyms)
+ return ExpectedSyms.takeError();
+ auto &Types = File.types();
+ auto &Ids = File.ids();
+
+ if (HashExtras) {
+ P.printLine("GSI Header");
+ AutoIndent Indent(P);
+ P.formatLine("sig = {0:X}, hdr = {1:X}, hr size = {2}, num buckets = {3}",
+ Table.getVerSignature(), Table.getVerHeader(),
+ Table.getHashRecordSize(), Table.getNumBuckets());
+ }
+
+ {
+ P.printLine("Records");
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+
+ BinaryStreamRef SymStream =
+ ExpectedSyms->getSymbolArray().getUnderlyingStream();
+ for (uint32_t PubSymOff : Table) {
+ Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
+ if (!Sym)
+ return Sym.takeError();
+ if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
+ return E;
+ }
+ }
+
+ // Return early if we aren't dumping public hash table and address map info.
+ if (HashExtras) {
+ P.formatLine("Hash Entries");
+ {
+ AutoIndent Indent2(P);
+ for (const PSHashRecord &HR : Table.HashRecords)
+ P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
+ uint32_t(HR.CRef));
+ }
+
+ P.formatLine("Hash Buckets");
+ {
+ AutoIndent Indent2(P);
+ for (uint32_t Hash : Table.HashBuckets)
+ P.formatLine("{0:x8}", Hash);
+ }
+ }
+
+ return Error::success();
+}
+
+static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
+ OMFSegDescFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == OMFSegDescFlags::None)
+ return "none";
+
+ PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
+ PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
+ PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
+ PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
+ PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
+ PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
+ PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
+ return typesetItemList(Opts, IndentLevel, 4, " | ");
+}
+
+Error DumpOutputStyle::dumpSectionHeaders() {
+ dumpSectionHeaders("Section Headers", DbgHeaderType::SectionHdr);
+ dumpSectionHeaders("Original Section Headers", DbgHeaderType::SectionHdrOrig);
+ return Error::success();
+}
+
+void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
+ printHeader(P, Label);
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return;
+ }
+
+ if (!getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return;
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Error dumping section headers: ");
+ std::unique_ptr<MappedBlockStream> Stream;
+ ArrayRef<object::coff_section> Headers;
+ auto ExpectedHeaders = loadSectionHeaders(getPdb(), Type);
+ if (!ExpectedHeaders) {
+ P.printLine(toString(ExpectedHeaders.takeError()));
+ return;
+ }
+ std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
+
+ uint32_t I = 1;
+ for (const auto &Header : Headers) {
+ P.NewLine();
+ P.formatLine("SECTION HEADER #{0}", I);
+ P.formatLine("{0,8} name", Header.Name);
+ P.formatLine("{0,8:X-} virtual size", uint32_t(Header.VirtualSize));
+ P.formatLine("{0,8:X-} virtual address", uint32_t(Header.VirtualAddress));
+ P.formatLine("{0,8:X-} size of raw data", uint32_t(Header.SizeOfRawData));
+ P.formatLine("{0,8:X-} file pointer to raw data",
+ uint32_t(Header.PointerToRawData));
+ P.formatLine("{0,8:X-} file pointer to relocation table",
+ uint32_t(Header.PointerToRelocations));
+ P.formatLine("{0,8:X-} file pointer to line numbers",
+ uint32_t(Header.PointerToLinenumbers));
+ P.formatLine("{0,8:X-} number of relocations",
+ uint32_t(Header.NumberOfRelocations));
+ P.formatLine("{0,8:X-} number of line numbers",
+ uint32_t(Header.NumberOfLinenumbers));
+ P.formatLine("{0,8:X-} flags", uint32_t(Header.Characteristics));
+ AutoIndent IndentMore(P, 9);
+ P.formatLine("{0}", formatSectionCharacteristics(
+ P.getIndentLevel(), Header.Characteristics, 1, ""));
+ ++I;
+ }
+}
+
+Error DumpOutputStyle::dumpSectionContribs() {
+ printHeader(P, "Section Contributions");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Error dumping section contributions: ");
+
+ auto &Dbi = Err(getPdb().getPDBDbiStream());
+
+ class Visitor : public ISectionContribVisitor {
+ public:
+ Visitor(LinePrinter &P, ArrayRef<std::string> Names) : P(P), Names(Names) {
+ auto Max = std::max_element(
+ Names.begin(), Names.end(),
+ [](StringRef S1, StringRef S2) { return S1.size() < S2.size(); });
+ MaxNameLen = (Max == Names.end() ? 0 : Max->size());
+ }
+ void visit(const SectionContrib &SC) override {
+ dumpSectionContrib(P, SC, Names, MaxNameLen);
+ }
+ void visit(const SectionContrib2 &SC) override {
+ dumpSectionContrib(P, SC, Names, MaxNameLen);
+ }
+
+ private:
+ LinePrinter &P;
+ uint32_t MaxNameLen;
+ ArrayRef<std::string> Names;
+ };
+
+ std::vector<std::string> Names = getSectionNames(getPdb());
+ Visitor V(P, makeArrayRef(Names));
+ Dbi.visitSectionContributions(V);
+ return Error::success();
+}
+
+Error DumpOutputStyle::dumpSectionMap() {
+ printHeader(P, "Section Map");
+
+ if (File.isObj()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ if (!getPdb().hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ AutoIndent Indent(P);
+ ExitOnError Err("Error dumping section map: ");
+
+ auto &Dbi = Err(getPdb().getPDBDbiStream());
+
+ uint32_t I = 0;
+ for (auto &M : Dbi.getSectionMap()) {
+ P.formatLine(
+ "Section {0:4} | ovl = {1}, group = {2}, frame = {3}, name = {4}", I,
+ fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
+ P.formatLine(" class = {0}, offset = {1}, size = {2}",
+ fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
+ P.formatLine(" flags = {0}",
+ formatSegMapDescriptorFlag(
+ P.getIndentLevel() + 13,
+ static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
+ ++I;
+ }
+ return Error::success();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.h b/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.h
new file mode 100644
index 0000000000..796cd7a10c
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -0,0 +1,122 @@
+//===- DumpOutputStyle.h -------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+class TypeReferenceTracker;
+
+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;
+ }
+ };
+
+ using KindAndStat = std::pair<uint32_t, Stat>;
+
+ 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;
+
+ std::vector<KindAndStat> getStatsSortedBySize() const;
+};
+
+class DumpOutputStyle : public OutputStyle {
+
+public:
+ DumpOutputStyle(InputFile &File);
+ ~DumpOutputStyle() override;
+
+ Error dump() override;
+
+private:
+ PDBFile &getPdb();
+ object::COFFObjectFile &getObj();
+
+ void printStreamNotValidForObj();
+ void printStreamNotPresent(StringRef StreamName);
+
+ Error dumpFileSummary();
+ Error dumpStreamSummary();
+ Error dumpSymbolStats();
+ Error dumpUdtStats();
+ Error dumpTypeStats();
+ Error dumpNamedStreams();
+ Error dumpStringTable();
+ Error dumpStringTableFromPdb();
+ Error dumpStringTableFromObj();
+ Error dumpLines();
+ Error dumpInlineeLines();
+ Error dumpXmi();
+ Error dumpXme();
+ Error dumpFpo();
+ Error dumpOldFpo(PDBFile &File);
+ Error dumpNewFpo(PDBFile &File);
+ Error dumpTpiStream(uint32_t StreamIdx);
+ Error dumpTypesFromObjectFile();
+ Error dumpTypeRefStats();
+ Error dumpModules();
+ Error dumpModuleFiles();
+ Error dumpModuleSymsForPdb();
+ Error dumpModuleSymsForObj();
+ Error dumpGSIRecords();
+ 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;
+ std::unique_ptr<TypeReferenceTracker> RefTracker;
+ LinePrinter P;
+ SmallVector<StreamInfo, 32> StreamPurposes;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.cpp
new file mode 100644
index 0000000000..3d2490509c
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.cpp
@@ -0,0 +1,468 @@
+//===- ExplainOutputStyle.cpp --------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExplainOutputStyle.h"
+
+#include "FormatUtil.h"
+#include "InputFile.h"
+#include "StreamUtil.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/CodeView/Formatters.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/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+ExplainOutputStyle::ExplainOutputStyle(InputFile &File, uint64_t FileOffset)
+ : File(File), FileOffset(FileOffset), P(2, false, outs()) {}
+
+Error ExplainOutputStyle::dump() {
+ P.formatLine("Explaining file offset {0} of file '{1}'.", FileOffset,
+ File.getFilePath());
+
+ if (File.isPdb())
+ return explainPdbFile();
+
+ return explainBinaryFile();
+}
+
+Error ExplainOutputStyle::explainPdbFile() {
+ bool IsAllocated = explainPdbBlockStatus();
+ if (!IsAllocated)
+ return Error::success();
+
+ AutoIndent Indent(P);
+ if (isPdbSuperBlock())
+ explainPdbSuperBlockOffset();
+ else if (isPdbFpmBlock())
+ explainPdbFpmBlockOffset();
+ else if (isPdbBlockMapBlock())
+ explainPdbBlockMapOffset();
+ else if (isPdbStreamDirectoryBlock())
+ explainPdbStreamDirectoryOffset();
+ else if (auto Index = getPdbBlockStreamIndex())
+ explainPdbStreamOffset(*Index);
+ else
+ explainPdbUnknownBlock();
+ return Error::success();
+}
+
+Error ExplainOutputStyle::explainBinaryFile() {
+ std::unique_ptr<BinaryByteStream> Stream =
+ std::make_unique<BinaryByteStream>(File.unknown().getBuffer(),
+ llvm::support::little);
+ switch (opts::explain::InputType) {
+ case opts::explain::InputFileType::DBIStream: {
+ DbiStream Dbi(std::move(Stream));
+ if (auto EC = Dbi.reload(nullptr))
+ return EC;
+ explainStreamOffset(Dbi, FileOffset);
+ break;
+ }
+ case opts::explain::InputFileType::PDBStream: {
+ InfoStream Info(std::move(Stream));
+ if (auto EC = Info.reload())
+ return EC;
+ explainStreamOffset(Info, FileOffset);
+ break;
+ }
+ default:
+ llvm_unreachable("Invalid input file type!");
+ }
+ return Error::success();
+}
+
+uint32_t ExplainOutputStyle::pdbBlockIndex() const {
+ return FileOffset / File.pdb().getBlockSize();
+}
+
+uint32_t ExplainOutputStyle::pdbBlockOffset() const {
+ uint64_t BlockStart = pdbBlockIndex() * File.pdb().getBlockSize();
+ assert(FileOffset >= BlockStart);
+ return FileOffset - BlockStart;
+}
+
+bool ExplainOutputStyle::isPdbSuperBlock() const {
+ return pdbBlockIndex() == 0;
+}
+
+bool ExplainOutputStyle::isPdbFpm1() const {
+ return ((pdbBlockIndex() - 1) % File.pdb().getBlockSize() == 0);
+}
+bool ExplainOutputStyle::isPdbFpm2() const {
+ return ((pdbBlockIndex() - 2) % File.pdb().getBlockSize() == 0);
+}
+
+bool ExplainOutputStyle::isPdbFpmBlock() const {
+ return isPdbFpm1() || isPdbFpm2();
+}
+
+bool ExplainOutputStyle::isPdbBlockMapBlock() const {
+ return pdbBlockIndex() == File.pdb().getBlockMapIndex();
+}
+
+bool ExplainOutputStyle::isPdbStreamDirectoryBlock() const {
+ const auto &Layout = File.pdb().getMsfLayout();
+ return llvm::is_contained(Layout.DirectoryBlocks, pdbBlockIndex());
+}
+
+Optional<uint32_t> ExplainOutputStyle::getPdbBlockStreamIndex() const {
+ const auto &Layout = File.pdb().getMsfLayout();
+ for (const auto &Entry : enumerate(Layout.StreamMap)) {
+ if (!llvm::is_contained(Entry.value(), pdbBlockIndex()))
+ continue;
+ return Entry.index();
+ }
+ return None;
+}
+
+bool ExplainOutputStyle::explainPdbBlockStatus() {
+ if (FileOffset >= File.pdb().getFileSize()) {
+ P.formatLine("Address {0} is not in the file (file size = {1}).",
+ FileOffset, File.pdb().getFileSize());
+ return false;
+ }
+ P.formatLine("Block:Offset = {2:X-}:{1:X-4}.", FileOffset, pdbBlockOffset(),
+ pdbBlockIndex());
+
+ bool IsFree = File.pdb().getMsfLayout().FreePageMap[pdbBlockIndex()];
+ P.formatLine("Address is in block {0} ({1}allocated).", pdbBlockIndex(),
+ IsFree ? "un" : "");
+ return !IsFree;
+}
+
+#define endof(Class, Field) (offsetof(Class, Field) + sizeof(Class::Field))
+
+void ExplainOutputStyle::explainPdbSuperBlockOffset() {
+ P.formatLine("This corresponds to offset {0} of the MSF super block, ",
+ pdbBlockOffset());
+ if (pdbBlockOffset() < endof(SuperBlock, MagicBytes))
+ P.printLine("which is part of the MSF file magic.");
+ else if (pdbBlockOffset() < endof(SuperBlock, BlockSize)) {
+ P.printLine("which contains the block size of the file.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->BlockSize));
+ } else if (pdbBlockOffset() < endof(SuperBlock, FreeBlockMapBlock)) {
+ P.printLine("which contains the index of the FPM block (e.g. 1 or 2).");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->FreeBlockMapBlock));
+ } else if (pdbBlockOffset() < endof(SuperBlock, NumBlocks)) {
+ P.printLine("which contains the number of blocks in the file.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->NumBlocks));
+ } else if (pdbBlockOffset() < endof(SuperBlock, NumDirectoryBytes)) {
+ P.printLine("which contains the number of bytes in the stream directory.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->NumDirectoryBytes));
+ } else if (pdbBlockOffset() < endof(SuperBlock, Unknown1)) {
+ P.printLine("whose purpose is unknown.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->Unknown1));
+ } else if (pdbBlockOffset() < endof(SuperBlock, BlockMapAddr)) {
+ P.printLine("which contains the file offset of the block map.");
+ P.formatLine("The current value is {0}.",
+ uint32_t(File.pdb().getMsfLayout().SB->BlockMapAddr));
+ } else {
+ assert(pdbBlockOffset() > sizeof(SuperBlock));
+ P.printLine(
+ "which is outside the range of valid data for the super block.");
+ }
+}
+
+static std::string toBinaryString(uint8_t Byte) {
+ char Result[9] = {0};
+ for (int I = 0; I < 8; ++I) {
+ char C = (Byte & 1) ? '1' : '0';
+ Result[I] = C;
+ Byte >>= 1;
+ }
+ return std::string(Result);
+}
+
+void ExplainOutputStyle::explainPdbFpmBlockOffset() {
+ const MSFLayout &Layout = File.pdb().getMsfLayout();
+ uint32_t MainFpm = Layout.mainFpmBlock();
+ uint32_t AltFpm = Layout.alternateFpmBlock();
+
+ assert(isPdbFpmBlock());
+ uint32_t Fpm = isPdbFpm1() ? 1 : 2;
+ uint32_t FpmChunk = pdbBlockIndex() / File.pdb().getBlockSize();
+ assert((Fpm == MainFpm) || (Fpm == AltFpm));
+ (void)AltFpm;
+ bool IsMain = (Fpm == MainFpm);
+ P.formatLine("Address is in FPM{0} ({1} FPM)", Fpm, IsMain ? "Main" : "Alt");
+ uint32_t DescribedBlockStart =
+ 8 * (FpmChunk * File.pdb().getBlockSize() + pdbBlockOffset());
+ if (DescribedBlockStart > File.pdb().getBlockCount()) {
+ P.printLine("Address is in extraneous FPM space.");
+ return;
+ }
+
+ P.formatLine("Address describes the allocation status of blocks [{0},{1})",
+ DescribedBlockStart, DescribedBlockStart + 8);
+ ArrayRef<uint8_t> Bytes;
+ cantFail(File.pdb().getMsfBuffer().readBytes(FileOffset, 1, Bytes));
+ P.formatLine("Status = {0} (Note: 0 = allocated, 1 = free)",
+ toBinaryString(Bytes[0]));
+}
+
+void ExplainOutputStyle::explainPdbBlockMapOffset() {
+ uint64_t BlockMapOffset = File.pdb().getBlockMapOffset();
+ uint32_t OffsetInBlock = FileOffset - BlockMapOffset;
+ P.formatLine("Address is at offset {0} of the directory block list",
+ OffsetInBlock);
+}
+
+static uint32_t getOffsetInStream(ArrayRef<support::ulittle32_t> StreamBlocks,
+ uint64_t FileOffset, uint32_t BlockSize) {
+ uint32_t BlockIndex = FileOffset / BlockSize;
+ uint32_t OffsetInBlock = FileOffset - BlockIndex * BlockSize;
+
+ auto Iter = llvm::find(StreamBlocks, BlockIndex);
+ assert(Iter != StreamBlocks.end());
+ uint32_t StreamBlockIndex = std::distance(StreamBlocks.begin(), Iter);
+ return StreamBlockIndex * BlockSize + OffsetInBlock;
+}
+
+void ExplainOutputStyle::explainPdbStreamOffset(uint32_t Stream) {
+ SmallVector<StreamInfo, 12> Streams;
+ discoverStreamPurposes(File.pdb(), Streams);
+
+ assert(Stream <= Streams.size());
+ const StreamInfo &S = Streams[Stream];
+ const auto &Layout = File.pdb().getStreamLayout(Stream);
+ uint32_t StreamOff =
+ getOffsetInStream(Layout.Blocks, FileOffset, File.pdb().getBlockSize());
+ P.formatLine("Address is at offset {0}/{1} of Stream {2} ({3}){4}.",
+ StreamOff, Layout.Length, Stream, S.getLongName(),
+ (StreamOff > Layout.Length) ? " in unused space" : "");
+ switch (S.getPurpose()) {
+ case StreamPurpose::DBI: {
+ DbiStream &Dbi = cantFail(File.pdb().getPDBDbiStream());
+ explainStreamOffset(Dbi, StreamOff);
+ break;
+ }
+ case StreamPurpose::PDB: {
+ InfoStream &Info = cantFail(File.pdb().getPDBInfoStream());
+ explainStreamOffset(Info, StreamOff);
+ break;
+ }
+ case StreamPurpose::IPI:
+ case StreamPurpose::TPI:
+ case StreamPurpose::ModuleStream:
+ case StreamPurpose::NamedStream:
+ default:
+ break;
+ }
+}
+
+void ExplainOutputStyle::explainPdbStreamDirectoryOffset() {
+ auto DirectoryBlocks = File.pdb().getDirectoryBlockArray();
+ const auto &Layout = File.pdb().getMsfLayout();
+ uint32_t StreamOff =
+ getOffsetInStream(DirectoryBlocks, FileOffset, File.pdb().getBlockSize());
+ P.formatLine("Address is at offset {0}/{1} of Stream Directory{2}.",
+ StreamOff, uint32_t(Layout.SB->NumDirectoryBytes),
+ uint32_t(StreamOff > Layout.SB->NumDirectoryBytes)
+ ? " in unused space"
+ : "");
+}
+
+void ExplainOutputStyle::explainPdbUnknownBlock() {
+ P.formatLine("Address has unknown purpose.");
+}
+
+template <typename T>
+static void printStructField(LinePrinter &P, StringRef Label, T Value) {
+ P.formatLine("which contains {0}.", Label);
+ P.formatLine("The current value is {0}.", Value);
+}
+
+static void explainDbiHeaderOffset(LinePrinter &P, DbiStream &Dbi,
+ uint32_t Offset) {
+ const DbiStreamHeader *Header = Dbi.getHeader();
+ assert(Header != nullptr);
+
+ if (Offset < endof(DbiStreamHeader, VersionSignature))
+ printStructField(P, "the DBI Stream Version Signature",
+ int32_t(Header->VersionSignature));
+ else if (Offset < endof(DbiStreamHeader, VersionHeader))
+ printStructField(P, "the DBI Stream Version Header",
+ uint32_t(Header->VersionHeader));
+ else if (Offset < endof(DbiStreamHeader, Age))
+ printStructField(P, "the age of the DBI Stream", uint32_t(Header->Age));
+ else if (Offset < endof(DbiStreamHeader, GlobalSymbolStreamIndex))
+ printStructField(P, "the index of the Global Symbol Stream",
+ uint16_t(Header->GlobalSymbolStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, BuildNumber))
+ printStructField(P, "the build number", uint16_t(Header->BuildNumber));
+ else if (Offset < endof(DbiStreamHeader, PublicSymbolStreamIndex))
+ printStructField(P, "the index of the Public Symbol Stream",
+ uint16_t(Header->PublicSymbolStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, PdbDllVersion))
+ printStructField(P, "the version of mspdb.dll",
+ uint16_t(Header->PdbDllVersion));
+ else if (Offset < endof(DbiStreamHeader, SymRecordStreamIndex))
+ printStructField(P, "the index of the Symbol Record Stream",
+ uint16_t(Header->SymRecordStreamIndex));
+ else if (Offset < endof(DbiStreamHeader, PdbDllRbld))
+ printStructField(P, "the rbld of mspdb.dll", uint16_t(Header->PdbDllRbld));
+ else if (Offset < endof(DbiStreamHeader, ModiSubstreamSize))
+ printStructField(P, "the size of the Module Info Substream",
+ int32_t(Header->ModiSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, SecContrSubstreamSize))
+ printStructField(P, "the size of the Section Contribution Substream",
+ int32_t(Header->SecContrSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, SectionMapSize))
+ printStructField(P, "the size of the Section Map Substream",
+ int32_t(Header->SectionMapSize));
+ else if (Offset < endof(DbiStreamHeader, FileInfoSize))
+ printStructField(P, "the size of the File Info Substream",
+ int32_t(Header->FileInfoSize));
+ else if (Offset < endof(DbiStreamHeader, TypeServerSize))
+ printStructField(P, "the size of the Type Server Map",
+ int32_t(Header->TypeServerSize));
+ else if (Offset < endof(DbiStreamHeader, MFCTypeServerIndex))
+ printStructField(P, "the index of the MFC Type Server stream",
+ uint32_t(Header->MFCTypeServerIndex));
+ else if (Offset < endof(DbiStreamHeader, OptionalDbgHdrSize))
+ printStructField(P, "the size of the Optional Debug Stream array",
+ int32_t(Header->OptionalDbgHdrSize));
+ else if (Offset < endof(DbiStreamHeader, ECSubstreamSize))
+ printStructField(P, "the size of the Edit & Continue Substream",
+ int32_t(Header->ECSubstreamSize));
+ else if (Offset < endof(DbiStreamHeader, Flags))
+ printStructField(P, "the DBI Stream flags", uint16_t(Header->Flags));
+ else if (Offset < endof(DbiStreamHeader, MachineType))
+ printStructField(P, "the machine type", uint16_t(Header->MachineType));
+ else if (Offset < endof(DbiStreamHeader, Reserved))
+ printStructField(P, "reserved data", uint32_t(Header->Reserved));
+}
+
+static void explainDbiModiSubstreamOffset(LinePrinter &P, DbiStream &Dbi,
+ uint32_t Offset) {
+ VarStreamArray<DbiModuleDescriptor> ModuleDescriptors;
+ BinaryStreamRef ModiSubstreamData = Dbi.getModiSubstreamData().StreamData;
+ BinaryStreamReader Reader(ModiSubstreamData);
+
+ cantFail(Reader.readArray(ModuleDescriptors, ModiSubstreamData.getLength()));
+ auto Prev = ModuleDescriptors.begin();
+ assert(Prev.offset() == 0);
+ auto Current = Prev;
+ uint32_t Index = 0;
+ while (true) {
+ Prev = Current;
+ ++Current;
+ if (Current == ModuleDescriptors.end() || Offset < Current.offset())
+ break;
+ ++Index;
+ }
+
+ DbiModuleDescriptor &Descriptor = *Prev;
+ P.formatLine("which contains the descriptor for module {0} ({1}).", Index,
+ Descriptor.getModuleName());
+}
+
+template <typename T>
+static void dontExplain(LinePrinter &Printer, T &Stream, uint32_t Offset) {}
+
+template <typename T, typename SubstreamRangeT>
+static void explainSubstreamOffset(LinePrinter &P, uint32_t OffsetInStream,
+ T &Stream,
+ const SubstreamRangeT &Substreams) {
+ uint32_t SubOffset = OffsetInStream;
+ for (const auto &Entry : Substreams) {
+ if (Entry.Size <= 0)
+ continue;
+ uint32_t S = static_cast<uint32_t>(Entry.Size);
+ if (SubOffset < S) {
+ P.formatLine("address is at offset {0}/{1} of the {2}.", SubOffset, S,
+ Entry.Label);
+ Entry.Explain(P, Stream, SubOffset);
+ return;
+ }
+ SubOffset -= S;
+ }
+}
+
+void ExplainOutputStyle::explainStreamOffset(DbiStream &Dbi,
+ uint32_t OffsetInStream) {
+ P.printLine("Within the DBI stream:");
+ AutoIndent Indent(P);
+ const DbiStreamHeader *Header = Dbi.getHeader();
+ assert(Header != nullptr);
+
+ struct SubstreamInfo {
+ int32_t Size;
+ StringRef Label;
+ void (*Explain)(LinePrinter &, DbiStream &, uint32_t);
+ } Substreams[] = {
+ {sizeof(DbiStreamHeader), "DBI Stream Header", explainDbiHeaderOffset},
+ {int32_t(Header->ModiSubstreamSize), "Module Info Substream",
+ explainDbiModiSubstreamOffset},
+ {int32_t(Header->SecContrSubstreamSize), "Section Contribution Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->SectionMapSize), "Section Map", dontExplain<DbiStream>},
+ {int32_t(Header->FileInfoSize), "File Info Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->TypeServerSize), "Type Server Map Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->ECSubstreamSize), "Edit & Continue Substream",
+ dontExplain<DbiStream>},
+ {int32_t(Header->OptionalDbgHdrSize), "Optional Debug Stream Array",
+ dontExplain<DbiStream>},
+ };
+
+ explainSubstreamOffset(P, OffsetInStream, Dbi, Substreams);
+}
+
+static void explainPdbStreamHeaderOffset(LinePrinter &P, InfoStream &Info,
+ uint32_t Offset) {
+ const InfoStreamHeader *Header = Info.getHeader();
+ assert(Header != nullptr);
+
+ if (Offset < endof(InfoStreamHeader, Version))
+ printStructField(P, "the PDB Stream Version Signature",
+ uint32_t(Header->Version));
+ else if (Offset < endof(InfoStreamHeader, Signature))
+ printStructField(P, "the signature of the PDB Stream",
+ uint32_t(Header->Signature));
+ else if (Offset < endof(InfoStreamHeader, Age))
+ printStructField(P, "the age of the PDB", uint32_t(Header->Age));
+ else if (Offset < endof(InfoStreamHeader, Guid))
+ printStructField(P, "the guid of the PDB", fmt_guid(Header->Guid.Guid));
+}
+
+void ExplainOutputStyle::explainStreamOffset(InfoStream &Info,
+ uint32_t OffsetInStream) {
+ P.printLine("Within the PDB stream:");
+ AutoIndent Indent(P);
+
+ struct SubstreamInfo {
+ uint32_t Size;
+ StringRef Label;
+ void (*Explain)(LinePrinter &, InfoStream &, uint32_t);
+ } Substreams[] = {{sizeof(InfoStreamHeader), "PDB Stream Header",
+ explainPdbStreamHeaderOffset},
+ {Info.getNamedStreamMapByteSize(), "Named Stream Map",
+ dontExplain<InfoStream>},
+ {Info.getStreamSize(), "PDB Feature Signatures",
+ dontExplain<InfoStream>}};
+
+ explainSubstreamOffset(P, OffsetInStream, Info, Substreams);
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.h b/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.h
new file mode 100644
index 0000000000..f405cf615e
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/ExplainOutputStyle.h
@@ -0,0 +1,67 @@
+//===- ExplainOutputStyle.h ----------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_EXPLAINOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_EXPLAINOUTPUTSTYLE_H
+
+#include "LinePrinter.h"
+#include "OutputStyle.h"
+
+#include <string>
+
+namespace llvm {
+
+namespace pdb {
+
+class DbiStream;
+class InfoStream;
+class InputFile;
+
+class ExplainOutputStyle : public OutputStyle {
+
+public:
+ ExplainOutputStyle(InputFile &File, uint64_t FileOffset);
+
+ Error dump() override;
+
+private:
+ Error explainPdbFile();
+ Error explainBinaryFile();
+
+ bool explainPdbBlockStatus();
+
+ bool isPdbFpm1() const;
+ bool isPdbFpm2() const;
+
+ bool isPdbSuperBlock() const;
+ bool isPdbFpmBlock() const;
+ bool isPdbBlockMapBlock() const;
+ bool isPdbStreamDirectoryBlock() const;
+ Optional<uint32_t> getPdbBlockStreamIndex() const;
+
+ void explainPdbSuperBlockOffset();
+ void explainPdbFpmBlockOffset();
+ void explainPdbBlockMapOffset();
+ void explainPdbStreamDirectoryOffset();
+ void explainPdbStreamOffset(uint32_t Stream);
+ void explainPdbUnknownBlock();
+
+ void explainStreamOffset(DbiStream &Stream, uint32_t OffsetInStream);
+ void explainStreamOffset(InfoStream &Stream, uint32_t OffsetInStream);
+
+ uint32_t pdbBlockIndex() const;
+ uint32_t pdbBlockOffset() const;
+
+ InputFile &File;
+ const uint64_t FileOffset;
+ LinePrinter P;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.cpp
new file mode 100644
index 0000000000..b4837398f1
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.cpp
@@ -0,0 +1,258 @@
+//===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 std::string(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 std::string(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 std::string(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 += std::string(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 += std::string(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);
+}
+
+std::string llvm::pdb::formatTypeLeafKind(TypeLeafKind K) {
+ switch (K) {
+#define TYPE_RECORD(EnumName, value, name) \
+ case EnumName: \
+ return #EnumName;
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+ default:
+ return formatv("UNKNOWN RECORD ({0:X})",
+ static_cast<std::underlying_type_t<TypeLeafKind>>(K))
+ .str();
+ }
+}
+
+std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) {
+ return std::string(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);
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.h b/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.h
new file mode 100644
index 0000000000..b99ccec215
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/FormatUtil.h
@@ -0,0 +1,141 @@
+//===- FormatUtil.h ------------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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<std::underlying_type_t<T>>(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);
+std::string 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) override {
+ 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
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.cpp
new file mode 100644
index 0000000000..b316882de6
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.cpp
@@ -0,0 +1,509 @@
+//===- InputFile.cpp ------------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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();
+ if (Index >= Modules.getModuleCount())
+ return make_error<RawError>(raw_error_code::index_out_of_bounds,
+ "Invalid module index");
+
+ 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) {
+ if (Expected<StringRef> NameOrErr = Section.getName()) {
+ if (*NameOrErr != Name)
+ return false;
+ } else {
+ consumeError(NameOrErr.takeError());
+ return false;
+ }
+
+ Expected<StringRef> ContentsOrErr = Section.getContents();
+ if (!ContentsOrErr) {
+ consumeError(ContentsOrErr.takeError());
+ return false;
+ }
+
+ Reader = BinaryStreamReader(*ContentsOrErr, 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) &&
+ !isCodeViewDebugSubsection(Section, ".debug$P", 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);
+}
+
+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()) {
+ auto StringTable = File->pdb().getStringTable();
+ if (StringTable)
+ SC.setStrings(StringTable->getStringTable());
+ else
+ consumeError(StringTable.takeError());
+ }
+
+ 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, bool AllowUnknownFile) {
+ 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::pdb) {
+ 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);
+ }
+
+ if (!AllowUnknownFile)
+ return make_error<StringError>(
+ formatv("File {0} is not a supported file type", Path),
+ inconvertibleErrorCode());
+
+ auto Result = MemoryBuffer::getFile(Path, -1LL, false);
+ if (!Result)
+ return make_error<StringError>(
+ formatv("File {0} could not be opened", Path), Result.getError());
+
+ IF.UnknownFile = std::move(*Result);
+ IF.PdbOrObj = IF.UnknownFile.get();
+ return std::move(IF);
+}
+
+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 *>();
+}
+
+MemoryBuffer &InputFile::unknown() {
+ assert(isUnknown());
+ return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+const MemoryBuffer &InputFile::unknown() const {
+ assert(isUnknown());
+ return *PdbOrObj.get<MemoryBuffer *>();
+}
+
+StringRef InputFile::getFilePath() const {
+ if (isPdb())
+ return pdb().getFilePath();
+ if (isObj())
+ return obj().getFileName();
+ assert(isUnknown());
+ return unknown().getBufferIdentifier();
+}
+
+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 *>();
+}
+
+bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); }
+
+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 =
+ std::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 = std::make_unique<LazyRandomTypeCollection>(Records, 100);
+ return *Types;
+ }
+
+ Types = std::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();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.h b/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.h
new file mode 100644
index 0000000000..a5d2897f56
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/InputFile.h
@@ -0,0 +1,155 @@
+//===- InputFile.h -------------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+ std::unique_ptr<MemoryBuffer> UnknownFile;
+ PointerUnion<PDBFile *, object::COFFObjectFile *, MemoryBuffer *> 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,
+ bool AllowUnknownFile = false);
+
+ PDBFile &pdb();
+ const PDBFile &pdb() const;
+ object::COFFObjectFile &obj();
+ const object::COFFObjectFile &obj() const;
+ MemoryBuffer &unknown();
+ const MemoryBuffer &unknown() const;
+
+ StringRef getFilePath() 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;
+ bool isUnknown() 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; }
+
+ bool hasDebugStream() const { return DebugStream != nullptr; }
+
+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
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.cpp
new file mode 100644
index 0000000000..280c000bd6
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.cpp
@@ -0,0 +1,333 @@
+//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 = File.createIndexedStream(StreamIdx);
+ 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;
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.h b/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.h
new file mode 100644
index 0000000000..7ecfae1735
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/LinePrinter.h
@@ -0,0 +1,168 @@
+//===- LinePrinter.h ------------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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) {
+ return Printer.getStream() << Item;
+}
+
+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
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
new file mode 100644
index 0000000000..787785c34b
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -0,0 +1,899 @@
+//===- MinimalSymbolDumper.cpp -------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MinimalSymbolDumper.h"
+
+#include "FormatUtil.h"
+#include "InputFile.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static std::string formatLocalSymFlags(uint32_t IndentLevel,
+ LocalSymFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == LocalSymFlags::None)
+ return "none";
+
+ PUSH_FLAG(LocalSymFlags, IsParameter, Flags, "param");
+ PUSH_FLAG(LocalSymFlags, IsAddressTaken, Flags, "address is taken");
+ PUSH_FLAG(LocalSymFlags, IsCompilerGenerated, Flags, "compiler generated");
+ PUSH_FLAG(LocalSymFlags, IsAggregate, Flags, "aggregate");
+ PUSH_FLAG(LocalSymFlags, IsAggregated, Flags, "aggregated");
+ PUSH_FLAG(LocalSymFlags, IsAliased, Flags, "aliased");
+ PUSH_FLAG(LocalSymFlags, IsAlias, Flags, "alias");
+ PUSH_FLAG(LocalSymFlags, IsReturnValue, Flags, "return val");
+ PUSH_FLAG(LocalSymFlags, IsOptimizedOut, Flags, "optimized away");
+ PUSH_FLAG(LocalSymFlags, IsEnregisteredGlobal, Flags, "enreg global");
+ PUSH_FLAG(LocalSymFlags, IsEnregisteredStatic, Flags, "enreg static");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatExportFlags(uint32_t IndentLevel, ExportFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == ExportFlags::None)
+ return "none";
+
+ PUSH_FLAG(ExportFlags, IsConstant, Flags, "constant");
+ PUSH_FLAG(ExportFlags, IsData, Flags, "data");
+ PUSH_FLAG(ExportFlags, IsPrivate, Flags, "private");
+ PUSH_FLAG(ExportFlags, HasNoName, Flags, "no name");
+ PUSH_FLAG(ExportFlags, HasExplicitOrdinal, Flags, "explicit ord");
+ PUSH_FLAG(ExportFlags, IsForwarder, Flags, "forwarder");
+
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatCompileSym2Flags(uint32_t IndentLevel,
+ CompileSym2Flags Flags) {
+ std::vector<std::string> Opts;
+ Flags &= ~CompileSym2Flags::SourceLanguageMask;
+ if (Flags == CompileSym2Flags::None)
+ return "none";
+
+ PUSH_FLAG(CompileSym2Flags, EC, Flags, "edit and continue");
+ PUSH_FLAG(CompileSym2Flags, NoDbgInfo, Flags, "no dbg info");
+ PUSH_FLAG(CompileSym2Flags, LTCG, Flags, "ltcg");
+ PUSH_FLAG(CompileSym2Flags, NoDataAlign, Flags, "no data align");
+ PUSH_FLAG(CompileSym2Flags, ManagedPresent, Flags, "has managed code");
+ PUSH_FLAG(CompileSym2Flags, SecurityChecks, Flags, "security checks");
+ PUSH_FLAG(CompileSym2Flags, HotPatch, Flags, "hot patchable");
+ PUSH_FLAG(CompileSym2Flags, CVTCIL, Flags, "cvtcil");
+ PUSH_FLAG(CompileSym2Flags, MSILModule, Flags, "msil module");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatCompileSym3Flags(uint32_t IndentLevel,
+ CompileSym3Flags Flags) {
+ std::vector<std::string> Opts;
+ Flags &= ~CompileSym3Flags::SourceLanguageMask;
+
+ if (Flags == CompileSym3Flags::None)
+ return "none";
+
+ PUSH_FLAG(CompileSym3Flags, EC, Flags, "edit and continue");
+ PUSH_FLAG(CompileSym3Flags, NoDbgInfo, Flags, "no dbg info");
+ PUSH_FLAG(CompileSym3Flags, LTCG, Flags, "ltcg");
+ PUSH_FLAG(CompileSym3Flags, NoDataAlign, Flags, "no data align");
+ PUSH_FLAG(CompileSym3Flags, ManagedPresent, Flags, "has managed code");
+ PUSH_FLAG(CompileSym3Flags, SecurityChecks, Flags, "security checks");
+ PUSH_FLAG(CompileSym3Flags, HotPatch, Flags, "hot patchable");
+ PUSH_FLAG(CompileSym3Flags, CVTCIL, Flags, "cvtcil");
+ PUSH_FLAG(CompileSym3Flags, MSILModule, Flags, "msil module");
+ PUSH_FLAG(CompileSym3Flags, Sdl, Flags, "sdl");
+ PUSH_FLAG(CompileSym3Flags, PGO, Flags, "pgo");
+ PUSH_FLAG(CompileSym3Flags, Exp, Flags, "exp");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatFrameProcedureOptions(uint32_t IndentLevel,
+ FrameProcedureOptions FPO) {
+ std::vector<std::string> Opts;
+ if (FPO == FrameProcedureOptions::None)
+ return "none";
+
+ PUSH_FLAG(FrameProcedureOptions, HasAlloca, FPO, "has alloca");
+ PUSH_FLAG(FrameProcedureOptions, HasSetJmp, FPO, "has setjmp");
+ PUSH_FLAG(FrameProcedureOptions, HasLongJmp, FPO, "has longjmp");
+ PUSH_FLAG(FrameProcedureOptions, HasInlineAssembly, FPO, "has inline asm");
+ PUSH_FLAG(FrameProcedureOptions, HasExceptionHandling, FPO, "has eh");
+ PUSH_FLAG(FrameProcedureOptions, MarkedInline, FPO, "marked inline");
+ PUSH_FLAG(FrameProcedureOptions, HasStructuredExceptionHandling, FPO,
+ "has seh");
+ PUSH_FLAG(FrameProcedureOptions, Naked, FPO, "naked");
+ PUSH_FLAG(FrameProcedureOptions, SecurityChecks, FPO, "secure checks");
+ PUSH_FLAG(FrameProcedureOptions, AsynchronousExceptionHandling, FPO,
+ "has async eh");
+ PUSH_FLAG(FrameProcedureOptions, NoStackOrderingForSecurityChecks, FPO,
+ "no stack order");
+ PUSH_FLAG(FrameProcedureOptions, Inlined, FPO, "inlined");
+ PUSH_FLAG(FrameProcedureOptions, StrictSecurityChecks, FPO,
+ "strict secure checks");
+ PUSH_FLAG(FrameProcedureOptions, SafeBuffers, FPO, "safe buffers");
+ PUSH_FLAG(FrameProcedureOptions, ProfileGuidedOptimization, FPO, "pgo");
+ PUSH_FLAG(FrameProcedureOptions, ValidProfileCounts, FPO,
+ "has profile counts");
+ PUSH_FLAG(FrameProcedureOptions, OptimizedForSpeed, FPO, "opt speed");
+ PUSH_FLAG(FrameProcedureOptions, GuardCfg, FPO, "guard cfg");
+ PUSH_FLAG(FrameProcedureOptions, GuardCfw, FPO, "guard cfw");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatPublicSymFlags(uint32_t IndentLevel,
+ PublicSymFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == PublicSymFlags::None)
+ return "none";
+
+ PUSH_FLAG(PublicSymFlags, Code, Flags, "code");
+ PUSH_FLAG(PublicSymFlags, Function, Flags, "function");
+ PUSH_FLAG(PublicSymFlags, Managed, Flags, "managed");
+ PUSH_FLAG(PublicSymFlags, MSIL, Flags, "msil");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatProcSymFlags(uint32_t IndentLevel,
+ ProcSymFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == ProcSymFlags::None)
+ return "none";
+
+ PUSH_FLAG(ProcSymFlags, HasFP, Flags, "has fp");
+ PUSH_FLAG(ProcSymFlags, HasIRET, Flags, "has iret");
+ PUSH_FLAG(ProcSymFlags, HasFRET, Flags, "has fret");
+ PUSH_FLAG(ProcSymFlags, IsNoReturn, Flags, "noreturn");
+ PUSH_FLAG(ProcSymFlags, IsUnreachable, Flags, "unreachable");
+ PUSH_FLAG(ProcSymFlags, HasCustomCallingConv, Flags, "custom calling conv");
+ PUSH_FLAG(ProcSymFlags, IsNoInline, Flags, "noinline");
+ PUSH_FLAG(ProcSymFlags, HasOptimizedDebugInfo, Flags, "opt debuginfo");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatThunkOrdinal(ThunkOrdinal Ordinal) {
+ switch (Ordinal) {
+ RETURN_CASE(ThunkOrdinal, Standard, "thunk");
+ RETURN_CASE(ThunkOrdinal, ThisAdjustor, "this adjustor");
+ RETURN_CASE(ThunkOrdinal, Vcall, "vcall");
+ RETURN_CASE(ThunkOrdinal, Pcode, "pcode");
+ RETURN_CASE(ThunkOrdinal, UnknownLoad, "unknown load");
+ RETURN_CASE(ThunkOrdinal, TrampIncremental, "tramp incremental");
+ RETURN_CASE(ThunkOrdinal, BranchIsland, "branch island");
+ }
+ return formatUnknownEnum(Ordinal);
+}
+
+static std::string formatTrampolineType(TrampolineType Tramp) {
+ switch (Tramp) {
+ RETURN_CASE(TrampolineType, TrampIncremental, "tramp incremental");
+ RETURN_CASE(TrampolineType, BranchIsland, "branch island");
+ }
+ return formatUnknownEnum(Tramp);
+}
+
+static std::string formatSourceLanguage(SourceLanguage Lang) {
+ switch (Lang) {
+ RETURN_CASE(SourceLanguage, C, "c");
+ RETURN_CASE(SourceLanguage, Cpp, "c++");
+ RETURN_CASE(SourceLanguage, Fortran, "fortran");
+ RETURN_CASE(SourceLanguage, Masm, "masm");
+ RETURN_CASE(SourceLanguage, Pascal, "pascal");
+ RETURN_CASE(SourceLanguage, Basic, "basic");
+ RETURN_CASE(SourceLanguage, Cobol, "cobol");
+ RETURN_CASE(SourceLanguage, Link, "link");
+ RETURN_CASE(SourceLanguage, VB, "vb");
+ RETURN_CASE(SourceLanguage, Cvtres, "cvtres");
+ RETURN_CASE(SourceLanguage, Cvtpgd, "cvtpgd");
+ RETURN_CASE(SourceLanguage, CSharp, "c#");
+ RETURN_CASE(SourceLanguage, ILAsm, "il asm");
+ RETURN_CASE(SourceLanguage, Java, "java");
+ RETURN_CASE(SourceLanguage, JScript, "javascript");
+ RETURN_CASE(SourceLanguage, MSIL, "msil");
+ RETURN_CASE(SourceLanguage, HLSL, "hlsl");
+ RETURN_CASE(SourceLanguage, D, "d");
+ RETURN_CASE(SourceLanguage, Swift, "swift");
+ }
+ return formatUnknownEnum(Lang);
+}
+
+static std::string formatMachineType(CPUType Cpu) {
+ switch (Cpu) {
+ RETURN_CASE(CPUType, Intel8080, "intel 8080");
+ RETURN_CASE(CPUType, Intel8086, "intel 8086");
+ RETURN_CASE(CPUType, Intel80286, "intel 80286");
+ RETURN_CASE(CPUType, Intel80386, "intel 80386");
+ RETURN_CASE(CPUType, Intel80486, "intel 80486");
+ RETURN_CASE(CPUType, Pentium, "intel pentium");
+ RETURN_CASE(CPUType, PentiumPro, "intel pentium pro");
+ RETURN_CASE(CPUType, Pentium3, "intel pentium 3");
+ RETURN_CASE(CPUType, MIPS, "mips");
+ RETURN_CASE(CPUType, MIPS16, "mips-16");
+ RETURN_CASE(CPUType, MIPS32, "mips-32");
+ RETURN_CASE(CPUType, MIPS64, "mips-64");
+ RETURN_CASE(CPUType, MIPSI, "mips i");
+ RETURN_CASE(CPUType, MIPSII, "mips ii");
+ RETURN_CASE(CPUType, MIPSIII, "mips iii");
+ RETURN_CASE(CPUType, MIPSIV, "mips iv");
+ RETURN_CASE(CPUType, MIPSV, "mips v");
+ RETURN_CASE(CPUType, M68000, "motorola 68000");
+ RETURN_CASE(CPUType, M68010, "motorola 68010");
+ RETURN_CASE(CPUType, M68020, "motorola 68020");
+ RETURN_CASE(CPUType, M68030, "motorola 68030");
+ RETURN_CASE(CPUType, M68040, "motorola 68040");
+ RETURN_CASE(CPUType, Alpha, "alpha");
+ RETURN_CASE(CPUType, Alpha21164, "alpha 21164");
+ RETURN_CASE(CPUType, Alpha21164A, "alpha 21164a");
+ RETURN_CASE(CPUType, Alpha21264, "alpha 21264");
+ RETURN_CASE(CPUType, Alpha21364, "alpha 21364");
+ RETURN_CASE(CPUType, PPC601, "powerpc 601");
+ RETURN_CASE(CPUType, PPC603, "powerpc 603");
+ RETURN_CASE(CPUType, PPC604, "powerpc 604");
+ RETURN_CASE(CPUType, PPC620, "powerpc 620");
+ RETURN_CASE(CPUType, PPCFP, "powerpc fp");
+ RETURN_CASE(CPUType, PPCBE, "powerpc be");
+ RETURN_CASE(CPUType, SH3, "sh3");
+ RETURN_CASE(CPUType, SH3E, "sh3e");
+ RETURN_CASE(CPUType, SH3DSP, "sh3 dsp");
+ RETURN_CASE(CPUType, SH4, "sh4");
+ RETURN_CASE(CPUType, SHMedia, "shmedia");
+ RETURN_CASE(CPUType, ARM3, "arm 3");
+ RETURN_CASE(CPUType, ARM4, "arm 4");
+ RETURN_CASE(CPUType, ARM4T, "arm 4t");
+ RETURN_CASE(CPUType, ARM5, "arm 5");
+ RETURN_CASE(CPUType, ARM5T, "arm 5t");
+ RETURN_CASE(CPUType, ARM6, "arm 6");
+ RETURN_CASE(CPUType, ARM_XMAC, "arm xmac");
+ RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx");
+ RETURN_CASE(CPUType, ARM7, "arm 7");
+ RETURN_CASE(CPUType, ARM64, "arm64");
+ RETURN_CASE(CPUType, Omni, "omni");
+ RETURN_CASE(CPUType, Ia64, "intel itanium ia64");
+ RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2");
+ RETURN_CASE(CPUType, CEE, "cee");
+ RETURN_CASE(CPUType, AM33, "am33");
+ RETURN_CASE(CPUType, M32R, "m32r");
+ RETURN_CASE(CPUType, TriCore, "tri-core");
+ RETURN_CASE(CPUType, X64, "intel x86-x64");
+ RETURN_CASE(CPUType, EBC, "ebc");
+ RETURN_CASE(CPUType, Thumb, "thumb");
+ RETURN_CASE(CPUType, ARMNT, "arm nt");
+ RETURN_CASE(CPUType, D3D11_Shader, "d3d11 shader");
+ }
+ return formatUnknownEnum(Cpu);
+}
+
+static std::string formatCookieKind(FrameCookieKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(FrameCookieKind, Copy, "copy");
+ RETURN_CASE(FrameCookieKind, XorStackPointer, "xor stack ptr");
+ RETURN_CASE(FrameCookieKind, XorFramePointer, "xor frame ptr");
+ RETURN_CASE(FrameCookieKind, XorR13, "xor rot13");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string formatRegisterId(RegisterId Id, CPUType Cpu) {
+ if (Cpu == CPUType::ARMNT) {
+ switch (Id) {
+#define CV_REGISTERS_ARM
+#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
+#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
+#undef CV_REGISTER
+#undef CV_REGISTERS_ARM
+
+ default:
+ break;
+ }
+ } else if (Cpu == CPUType::ARM64) {
+ switch (Id) {
+#define CV_REGISTERS_ARM64
+#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
+#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
+#undef CV_REGISTER
+#undef CV_REGISTERS_ARM64
+
+ default:
+ break;
+ }
+ } else {
+ switch (Id) {
+#define CV_REGISTERS_X86
+#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
+#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
+#undef CV_REGISTER
+#undef CV_REGISTERS_X86
+
+ default:
+ break;
+ }
+ }
+ return formatUnknownEnum(Id);
+}
+
+static std::string formatRegisterId(uint16_t Reg16, CPUType Cpu) {
+ return formatRegisterId(RegisterId(Reg16), Cpu);
+}
+
+static std::string formatRegisterId(ulittle16_t &Reg16, CPUType Cpu) {
+ return formatRegisterId(uint16_t(Reg16), Cpu);
+}
+
+static std::string formatRange(LocalVariableAddrRange Range) {
+ return formatv("[{0},+{1})",
+ formatSegmentOffset(Range.ISectStart, Range.OffsetStart),
+ Range.Range)
+ .str();
+}
+
+static std::string formatGaps(uint32_t IndentLevel,
+ ArrayRef<LocalVariableAddrGap> Gaps) {
+ std::vector<std::string> GapStrs;
+ for (const auto &G : Gaps) {
+ GapStrs.push_back(formatv("({0},{1})", G.GapStartOffset, G.Range).str());
+ }
+ return typesetItemList(GapStrs, 7, IndentLevel, ", ");
+}
+
+Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) {
+ return visitSymbolBegin(Record, 0);
+}
+
+Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record,
+ uint32_t Offset) {
+ // formatLine puts the newline at the beginning, so we use formatLine here
+ // to start a new line, and then individual visit methods use format to
+ // append to the existing line.
+ P.formatLine("{0} | {1} [size = {2}]",
+ fmt_align(Offset, AlignStyle::Right, 6),
+ formatSymbolKind(Record.kind()), Record.length());
+ P.Indent();
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) {
+ if (RecordBytes) {
+ AutoIndent Indent(P, 7);
+ P.formatBinary("bytes", Record.content(), 0);
+ }
+ P.Unindent();
+ return Error::success();
+}
+
+std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI,
+ bool IsType) const {
+ if (TI.isSimple() || TI.isDecoratedItemId())
+ return formatv("{0}", TI).str();
+ auto &Container = IsType ? Types : Ids;
+ StringRef Name = Container.getTypeName(TI);
+ if (Name.size() > 32) {
+ Name = Name.take_front(32);
+ return std::string(formatv("{0} ({1}...)", TI, Name));
+ } else
+ return std::string(formatv("{0} ({1})", TI, Name));
+}
+
+std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const {
+ return typeOrIdIndex(TI, false);
+}
+
+std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
+ return typeOrIdIndex(TI, true);
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+ P.format(" `{0}`", Block.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("parent = {0}, end = {1}", Block.Parent, Block.End);
+ P.formatLine("code size = {0}, addr = {1}", Block.CodeSize,
+ formatSegmentOffset(Block.Segment, Block.CodeOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+ P.format(" `{0}`", Thunk.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("parent = {0}, end = {1}, next = {2}", Thunk.Parent, Thunk.End,
+ Thunk.Next);
+ P.formatLine("kind = {0}, size = {1}, addr = {2}",
+ formatThunkOrdinal(Thunk.Thunk), Thunk.Length,
+ formatSegmentOffset(Thunk.Segment, Thunk.Offset));
+
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, size = {1}, source = {2}, target = {3}",
+ formatTrampolineType(Tramp.Type), Tramp.Size,
+ formatSegmentOffset(Tramp.ThunkSection, Tramp.ThunkOffset),
+ formatSegmentOffset(Tramp.TargetSection, Tramp.ThunkOffset));
+
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ SectionSym &Section) {
+ P.format(" `{0}`", Section.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("length = {0}, alignment = {1}, rva = {2}, section # = {3}",
+ Section.Length, Section.Alignment, Section.Rva,
+ Section.SectionNumber);
+ P.printLine("characteristics =");
+ AutoIndent Indent2(P, 2);
+ P.printLine(formatSectionCharacteristics(P.getIndentLevel(),
+ Section.Characteristics, 1, "",
+ CharacteristicStyle::Descriptive));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CoffGroupSym &CG) {
+ P.format(" `{0}`", CG.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("length = {0}, addr = {1}", CG.Size,
+ formatSegmentOffset(CG.Segment, CG.Offset));
+ P.printLine("characteristics =");
+ AutoIndent Indent2(P, 2);
+ P.printLine(formatSectionCharacteristics(P.getIndentLevel(),
+ CG.Characteristics, 1, "",
+ CharacteristicStyle::Descriptive));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
+ P.format(" `{0}`", BPRel.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, offset = {1}", typeIndex(BPRel.Type), BPRel.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ BuildInfoSym &BuildInfo) {
+ P.format(" BuildId = `{0}`", BuildInfo.BuildId);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CSI) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(CSI.Type),
+ formatSegmentOffset(CSI.Segment, CSI.CodeOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
+ AutoIndent Indent(P, 7);
+ for (const auto &Entry : EnvBlock.Fields) {
+ P.formatLine("- {0}", Entry);
+ }
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) {
+ P.format(" `{0}`", FS.Name);
+ AutoIndent Indent(P, 7);
+ if (SymGroup) {
+ Expected<StringRef> FileName =
+ SymGroup->getNameFromStringTable(FS.ModFilenameOffset);
+ if (FileName) {
+ P.formatLine("type = {0}, file name = {1} ({2}), flags = {3}",
+ typeIndex(FS.Index), FS.ModFilenameOffset, *FileName,
+ formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
+ }
+ return Error::success();
+ }
+
+ P.formatLine("type = {0}, file name offset = {1}, flags = {2}",
+ typeIndex(FS.Index), FS.ModFilenameOffset,
+ formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+ P.format(" `{0}`", Export.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("ordinal = {0}, flags = {1}", Export.Ordinal,
+ formatExportFlags(P.getIndentLevel() + 9, Export.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
+ AutoIndent Indent(P, 7);
+ SourceLanguage Lang = static_cast<SourceLanguage>(
+ Compile2.Flags & CompileSym2Flags::SourceLanguageMask);
+ CompilationCPU = Compile2.Machine;
+ P.formatLine("machine = {0}, ver = {1}, language = {2}",
+ formatMachineType(Compile2.Machine), Compile2.Version,
+ formatSourceLanguage(Lang));
+ P.formatLine("frontend = {0}.{1}.{2}, backend = {3}.{4}.{5}",
+ Compile2.VersionFrontendMajor, Compile2.VersionFrontendMinor,
+ Compile2.VersionFrontendBuild, Compile2.VersionBackendMajor,
+ Compile2.VersionBackendMinor, Compile2.VersionBackendBuild);
+ P.formatLine("flags = {0}",
+ formatCompileSym2Flags(P.getIndentLevel() + 9, Compile2.Flags));
+ P.formatLine(
+ "extra strings = {0}",
+ typesetStringList(P.getIndentLevel() + 9 + 2, Compile2.ExtraStrings));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
+ AutoIndent Indent(P, 7);
+ SourceLanguage Lang = static_cast<SourceLanguage>(
+ Compile3.Flags & CompileSym3Flags::SourceLanguageMask);
+ CompilationCPU = Compile3.Machine;
+ P.formatLine("machine = {0}, Ver = {1}, language = {2}",
+ formatMachineType(Compile3.Machine), Compile3.Version,
+ formatSourceLanguage(Lang));
+ P.formatLine("frontend = {0}.{1}.{2}.{3}, backend = {4}.{5}.{6}.{7}",
+ Compile3.VersionFrontendMajor, Compile3.VersionFrontendMinor,
+ Compile3.VersionFrontendBuild, Compile3.VersionFrontendQFE,
+ Compile3.VersionBackendMajor, Compile3.VersionBackendMinor,
+ Compile3.VersionBackendBuild, Compile3.VersionBackendQFE);
+ P.formatLine("flags = {0}",
+ formatCompileSym3Flags(P.getIndentLevel() + 9, Compile3.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
+ P.format(" `{0}`", Constant.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type),
+ Constant.Value.toString(10));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+ P.format(" `{0}`", Data.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
+ formatSegmentOffset(Data.Segment, Data.DataOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelFullScopeSym &Def) {
+ P.format(" offset = {0}", Def.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeFramePointerRelSym &Def) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("offset = {0}, range = {1}", Def.Hdr.Offset,
+ formatRange(Def.Range));
+ P.formatLine("gaps = {2}", Def.Hdr.Offset,
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeRegisterRelSym &Def) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("register = {0}, offset = {1}, offset in parent = {2}, has "
+ "spilled udt = {3}",
+ formatRegisterId(Def.Hdr.Register, CompilationCPU),
+ int32_t(Def.Hdr.BasePointerOffset), Def.offsetInParent(),
+ Def.hasSpilledUDTMember());
+ P.formatLine("range = {0}, gaps = {1}", formatRange(Def.Range),
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("register = {0}, may have no name = {1}, range start = "
+ "{2}, length = {3}",
+ formatRegisterId(DefRangeRegister.Hdr.Register, CompilationCPU),
+ bool(DefRangeRegister.Hdr.MayHaveNoName),
+ formatSegmentOffset(DefRangeRegister.Range.ISectStart,
+ DefRangeRegister.Range.OffsetStart),
+ DefRangeRegister.Range.Range);
+ P.formatLine("gaps = [{0}]",
+ formatGaps(P.getIndentLevel() + 9, DefRangeRegister.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSubfieldRegisterSym &Def) {
+ AutoIndent Indent(P, 7);
+ bool NoName = !!(Def.Hdr.MayHaveNoName == 0);
+ P.formatLine("register = {0}, may have no name = {1}, offset in parent = {2}",
+ formatRegisterId(Def.Hdr.Register, CompilationCPU), NoName,
+ uint32_t(Def.Hdr.OffsetInParent));
+ P.formatLine("range = {0}, gaps = {1}", formatRange(Def.Range),
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSubfieldSym &Def) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("program = {0}, offset in parent = {1}, range = {2}",
+ Def.Program, Def.OffsetInParent, formatRange(Def.Range));
+ P.formatLine("gaps = {0}", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeSym &Def) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("program = {0}, range = {1}", Def.Program,
+ formatRange(Def.Range));
+ P.formatLine("gaps = {0}", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameCookieSym &FC) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("code offset = {0}, Register = {1}, kind = {2}, flags = {3}",
+ FC.CodeOffset, formatRegisterId(FC.Register, CompilationCPU),
+ formatCookieKind(FC.CookieKind), FC.Flags);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("size = {0}, padding size = {1}, offset to padding = {2}",
+ FP.TotalFrameBytes, FP.PaddingFrameBytes, FP.OffsetToPadding);
+ P.formatLine("bytes of callee saved registers = {0}, exception handler addr "
+ "= {1}",
+ FP.BytesOfCalleeSavedRegisters,
+ formatSegmentOffset(FP.SectionIdOfExceptionHandler,
+ FP.OffsetOfExceptionHandler));
+ P.formatLine(
+ "local fp reg = {0}, param fp reg = {1}",
+ formatRegisterId(FP.getLocalFramePtrReg(CompilationCPU), CompilationCPU),
+ formatRegisterId(FP.getParamFramePtrReg(CompilationCPU), CompilationCPU));
+ P.formatLine("flags = {0}",
+ formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ HeapAllocationSiteSym &HAS) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, addr = {1} call size = {2}", typeIndex(HAS.Type),
+ formatSegmentOffset(HAS.Segment, HAS.CodeOffset),
+ HAS.CallInstructionSize);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("inlinee = {0}, parent = {1}, end = {2}", idIndex(IS.Inlinee),
+ IS.Parent, IS.End);
+
+ // Break down the annotation byte code and calculate code and line offsets.
+ // FIXME: It would be helpful if we could look up the initial file and inlinee
+ // lines offset using the inlinee index above.
+ uint32_t CodeOffset = 0;
+ int32_t LineOffset = 0;
+ for (auto &Annot : IS.annotations()) {
+ P.formatLine(" {0}", fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9));
+
+ auto formatCodeOffset = [&](uint32_t Delta) {
+ CodeOffset += Delta;
+ P.format(" code 0x{0} (+0x{1})", utohexstr(CodeOffset), utohexstr(Delta));
+ };
+ auto formatCodeLength = [&](uint32_t Length) {
+ // Notably, changing the code length does not affect the code offset.
+ P.format(" code end 0x{0} (+0x{1})", utohexstr(CodeOffset + Length),
+ utohexstr(Length));
+ };
+ auto formatLineOffset = [&](int32_t Delta) {
+ LineOffset += Delta;
+ char Sign = Delta > 0 ? '+' : '-';
+ P.format(" line {0} ({1}{2})", LineOffset, Sign, std::abs(Delta));
+ };
+
+ // Use the opcode to interpret the integer values.
+ switch (Annot.OpCode) {
+ case BinaryAnnotationsOpCode::Invalid:
+ break;
+ case BinaryAnnotationsOpCode::CodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ formatCodeOffset(Annot.U1);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineOffset:
+ formatLineOffset(Annot.S1);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ formatCodeLength(Annot.U1);
+ // Apparently this annotation updates the code offset. It's hard to make
+ // MSVC produce this opcode, but clang uses it, and debuggers seem to use
+ // this interpretation.
+ CodeOffset += Annot.U1;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+ formatCodeOffset(Annot.U1);
+ formatLineOffset(Annot.S1);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+ formatCodeOffset(Annot.U2);
+ formatCodeLength(Annot.U1);
+ break;
+
+ case BinaryAnnotationsOpCode::ChangeFile: {
+ uint32_t FileOffset = Annot.U1;
+ StringRef Filename = "<unknown>";
+ if (SymGroup) {
+ if (Expected<StringRef> MaybeFile =
+ SymGroup->getNameFromStringTable(FileOffset))
+ Filename = *MaybeFile;
+ else
+ return MaybeFile.takeError();
+ }
+ P.format(" setfile {0} 0x{1}", utohexstr(FileOffset));
+ break;
+ }
+
+ // The rest of these are hard to convince MSVC to emit, so they are not as
+ // well understood.
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+ formatCodeOffset(Annot.U1);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+ case BinaryAnnotationsOpCode::ChangeRangeKind:
+ case BinaryAnnotationsOpCode::ChangeColumnStart:
+ case BinaryAnnotationsOpCode::ChangeColumnEnd:
+ P.format(" {0} {1}", Annot.Name, Annot.U1);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+ P.format(" {0} {1}", Annot.Name, Annot.S1);
+ break;
+ }
+ }
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
+ P.format(" `{0}`", Register.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("register = {0}, type = {1}",
+ formatRegisterId(Register.Register, CompilationCPU),
+ typeIndex(Register.Index));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ PublicSym32 &Public) {
+ P.format(" `{0}`", Public.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("flags = {0}, addr = {1}",
+ formatPublicSymFlags(P.getIndentLevel() + 9, Public.Flags),
+ formatSegmentOffset(Public.Segment, Public.Offset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcRefSym &PR) {
+ P.format(" `{0}`", PR.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("module = {0}, sum name = {1}, offset = {2}", PR.Module,
+ PR.SumName, PR.SymOffset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+ P.format(" `{0}` (addr = {1})", Label.Name,
+ formatSegmentOffset(Label.Segment, Label.CodeOffset));
+ AutoIndent Indent(P, 7);
+ P.formatLine("flags = {0}",
+ formatProcSymFlags(P.getIndentLevel() + 9, Label.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+ P.format(" `{0}`", Local.Name);
+ AutoIndent Indent(P, 7);
+
+ std::string FlagStr =
+ formatLocalSymFlags(P.getIndentLevel() + 9, Local.Flags);
+ P.formatLine("type={0}, flags = {1}", typeIndex(Local.Type), FlagStr);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ObjNameSym &ObjName) {
+ P.format(" sig={0}, `{1}`", ObjName.Signature, ObjName.Name);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+ P.format(" `{0}`", Proc.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("parent = {0}, end = {1}, addr = {2}, code size = {3}",
+ Proc.Parent, Proc.End,
+ formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
+ Proc.CodeSize);
+ bool IsType = true;
+ switch (Proc.getKind()) {
+ case SymbolRecordKind::GlobalProcIdSym:
+ case SymbolRecordKind::ProcIdSym:
+ case SymbolRecordKind::DPCProcIdSym:
+ IsType = false;
+ break;
+ default:
+ break;
+ }
+ P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}",
+ typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart,
+ Proc.DbgEnd,
+ formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ AutoIndent Indent(P, 7);
+ for (const auto &I : Caller.Indices) {
+ P.formatLine("callee: {0}", idIndex(I));
+ }
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
+ P.format(" `{0}`", RegRel.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine(
+ "type = {0}, register = {1}, offset = {2}", typeIndex(RegRel.Type),
+ formatRegisterId(RegRel.Register, CompilationCPU), RegRel.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
+ P.format(" `{0}`", Data.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
+ formatSegmentOffset(Data.Segment, Data.DataOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+ P.format(" `{0}`", UDT.Name);
+ AutoIndent Indent(P, 7);
+ P.formatLine("original type = {0}", UDT.Type);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ UsingNamespaceSym &UN) {
+ P.format(" `{0}`", UN.Name);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ AnnotationSym &Annot) {
+ AutoIndent Indent(P, 7);
+ P.formatLine("addr = {0}", formatSegmentOffset(Annot.Segment, Annot.CodeOffset));
+ P.formatLine("strings = {0}", typesetStringList(P.getIndentLevel() + 9 + 2,
+ Annot.Strings));
+ return Error::success();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.h
new file mode 100644
index 0000000000..cdc75c1cfb
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalSymbolDumper.h
@@ -0,0 +1,68 @@
+//===- MinimalSymbolDumper.h ---------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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 SymbolGroup;
+
+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) {}
+ MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
+ const SymbolGroup &SymGroup,
+ codeview::LazyRandomTypeCollection &Ids,
+ codeview::LazyRandomTypeCollection &Types)
+ : P(P), RecordBytes(RecordBytes), SymGroup(&SymGroup), 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;
+
+ void setSymbolGroup(const SymbolGroup *Group) { SymGroup = Group; }
+
+#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;
+
+ /// Dumping certain records requires knowing what machine this is. The
+ /// S_COMPILE3 record will tell us, but if we don't see one, default to X64.
+ codeview::CPUType CompilationCPU = codeview::CPUType::X64;
+
+ bool RecordBytes;
+ const SymbolGroup *SymGroup = nullptr;
+ codeview::LazyRandomTypeCollection &Ids;
+ codeview::LazyRandomTypeCollection &Types;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.cpp
new file mode 100644
index 0000000000..8e46a97272
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -0,0 +1,592 @@
+//===- MinimalTypeDumper.cpp ---------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MinimalTypeDumper.h"
+
+#include "FormatUtil.h"
+#include "LinePrinter.h"
+#include "TypeReferenceTracker.h"
+
+#include "llvm-pdbutil.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static std::string formatClassOptions(uint32_t IndentLevel,
+ ClassOptions Options, TpiStream *Stream,
+ TypeIndex CurrentTypeIndex) {
+ std::vector<std::string> Opts;
+
+ if (Stream && Stream->supportsTypeLookup() &&
+ !opts::dump::DontResolveForwardRefs &&
+ ((Options & ClassOptions::ForwardReference) != ClassOptions::None)) {
+ // If we're able to resolve forward references, do that.
+ Expected<TypeIndex> ETI =
+ Stream->findFullDeclForForwardRef(CurrentTypeIndex);
+ if (!ETI) {
+ consumeError(ETI.takeError());
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref (??\?)");
+ } else {
+ const char *Direction = (*ETI == CurrentTypeIndex)
+ ? "="
+ : ((*ETI < CurrentTypeIndex) ? "<-" : "->");
+ std::string Formatted =
+ formatv("forward ref ({0} {1})", Direction, *ETI).str();
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, std::move(Formatted));
+ }
+ } else {
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
+ }
+
+ PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,
+ "has ctor / dtor");
+ PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,
+ "contains nested class");
+ PUSH_FLAG(ClassOptions, HasConversionOperator, Options,
+ "conversion operator");
+ PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");
+ PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");
+ PUSH_FLAG(ClassOptions, Nested, Options, "is nested");
+ PUSH_FLAG(ClassOptions, HasOverloadedOperator, Options,
+ "overloaded operator");
+ PUSH_FLAG(ClassOptions, HasOverloadedAssignmentOperator, Options,
+ "overloaded operator=");
+ PUSH_FLAG(ClassOptions, Packed, Options, "packed");
+ PUSH_FLAG(ClassOptions, Scoped, Options, "scoped");
+ PUSH_FLAG(ClassOptions, Sealed, Options, "sealed");
+
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string pointerOptions(PointerOptions Options) {
+ std::vector<std::string> Opts;
+ PUSH_FLAG(PointerOptions, Flat32, Options, "flat32");
+ PUSH_FLAG(PointerOptions, Volatile, Options, "volatile");
+ PUSH_FLAG(PointerOptions, Const, Options, "const");
+ PUSH_FLAG(PointerOptions, Unaligned, Options, "unaligned");
+ PUSH_FLAG(PointerOptions, Restrict, Options, "restrict");
+ PUSH_FLAG(PointerOptions, WinRTSmartPointer, Options, "winrt");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+static std::string modifierOptions(ModifierOptions Options) {
+ std::vector<std::string> Opts;
+ PUSH_FLAG(ModifierOptions, Const, Options, "const");
+ PUSH_FLAG(ModifierOptions, Volatile, Options, "volatile");
+ PUSH_FLAG(ModifierOptions, Unaligned, Options, "unaligned");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+static std::string formatCallingConvention(CallingConvention Convention) {
+ switch (Convention) {
+ RETURN_CASE(CallingConvention, AlphaCall, "alphacall");
+ RETURN_CASE(CallingConvention, AM33Call, "am33call");
+ RETURN_CASE(CallingConvention, ArmCall, "armcall");
+ RETURN_CASE(CallingConvention, ClrCall, "clrcall");
+ RETURN_CASE(CallingConvention, FarC, "far cdecl");
+ RETURN_CASE(CallingConvention, FarFast, "far fastcall");
+ RETURN_CASE(CallingConvention, FarPascal, "far pascal");
+ RETURN_CASE(CallingConvention, FarStdCall, "far stdcall");
+ RETURN_CASE(CallingConvention, FarSysCall, "far syscall");
+ RETURN_CASE(CallingConvention, Generic, "generic");
+ RETURN_CASE(CallingConvention, Inline, "inline");
+ RETURN_CASE(CallingConvention, M32RCall, "m32rcall");
+ RETURN_CASE(CallingConvention, MipsCall, "mipscall");
+ RETURN_CASE(CallingConvention, NearC, "cdecl");
+ RETURN_CASE(CallingConvention, NearFast, "fastcall");
+ RETURN_CASE(CallingConvention, NearPascal, "pascal");
+ RETURN_CASE(CallingConvention, NearStdCall, "stdcall");
+ RETURN_CASE(CallingConvention, NearSysCall, "near syscall");
+ RETURN_CASE(CallingConvention, NearVector, "vectorcall");
+ RETURN_CASE(CallingConvention, PpcCall, "ppccall");
+ RETURN_CASE(CallingConvention, SHCall, "shcall");
+ RETURN_CASE(CallingConvention, SH5Call, "sh5call");
+ RETURN_CASE(CallingConvention, ThisCall, "thiscall");
+ RETURN_CASE(CallingConvention, TriCall, "tricall");
+ }
+ return formatUnknownEnum(Convention);
+}
+
+static std::string formatPointerMode(PointerMode Mode) {
+ switch (Mode) {
+ RETURN_CASE(PointerMode, LValueReference, "ref");
+ RETURN_CASE(PointerMode, Pointer, "pointer");
+ RETURN_CASE(PointerMode, PointerToDataMember, "data member pointer");
+ RETURN_CASE(PointerMode, PointerToMemberFunction, "member fn pointer");
+ RETURN_CASE(PointerMode, RValueReference, "rvalue ref");
+ }
+ return formatUnknownEnum(Mode);
+}
+
+static std::string memberAccess(MemberAccess Access) {
+ switch (Access) {
+ RETURN_CASE(MemberAccess, None, "");
+ RETURN_CASE(MemberAccess, Private, "private");
+ RETURN_CASE(MemberAccess, Protected, "protected");
+ RETURN_CASE(MemberAccess, Public, "public");
+ }
+ return formatUnknownEnum(Access);
+}
+
+static std::string methodKind(MethodKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(MethodKind, Vanilla, "");
+ RETURN_CASE(MethodKind, Virtual, "virtual");
+ RETURN_CASE(MethodKind, Static, "static");
+ RETURN_CASE(MethodKind, Friend, "friend");
+ RETURN_CASE(MethodKind, IntroducingVirtual, "intro virtual");
+ RETURN_CASE(MethodKind, PureVirtual, "pure virtual");
+ RETURN_CASE(MethodKind, PureIntroducingVirtual, "pure intro virtual");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string pointerKind(PointerKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(PointerKind, Near16, "ptr16");
+ RETURN_CASE(PointerKind, Far16, "far ptr16");
+ RETURN_CASE(PointerKind, Huge16, "huge ptr16");
+ RETURN_CASE(PointerKind, BasedOnSegment, "segment based");
+ RETURN_CASE(PointerKind, BasedOnValue, "value based");
+ RETURN_CASE(PointerKind, BasedOnSegmentValue, "segment value based");
+ RETURN_CASE(PointerKind, BasedOnAddress, "address based");
+ RETURN_CASE(PointerKind, BasedOnSegmentAddress, "segment address based");
+ RETURN_CASE(PointerKind, BasedOnType, "type based");
+ RETURN_CASE(PointerKind, BasedOnSelf, "self based");
+ RETURN_CASE(PointerKind, Near32, "ptr32");
+ RETURN_CASE(PointerKind, Far32, "far ptr32");
+ RETURN_CASE(PointerKind, Near64, "ptr64");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string memberAttributes(const MemberAttributes &Attrs) {
+ std::vector<std::string> Opts;
+ std::string Access = memberAccess(Attrs.getAccess());
+ std::string Kind = methodKind(Attrs.getMethodKind());
+ if (!Access.empty())
+ Opts.push_back(Access);
+ if (!Kind.empty())
+ Opts.push_back(Kind);
+ MethodOptions Flags = Attrs.getFlags();
+ PUSH_FLAG(MethodOptions, Pseudo, Flags, "pseudo");
+ PUSH_FLAG(MethodOptions, NoInherit, Flags, "noinherit");
+ PUSH_FLAG(MethodOptions, NoConstruct, Flags, "noconstruct");
+ PUSH_FLAG(MethodOptions, CompilerGenerated, Flags, "compiler-generated");
+ PUSH_FLAG(MethodOptions, Sealed, Flags, "sealed");
+ return join(Opts, " ");
+}
+
+static std::string formatPointerAttrs(const PointerRecord &Record) {
+ PointerMode Mode = Record.getMode();
+ PointerOptions Opts = Record.getOptions();
+ PointerKind Kind = Record.getPointerKind();
+ return std::string(formatv("mode = {0}, opts = {1}, kind = {2}",
+ formatPointerMode(Mode), pointerOptions(Opts),
+ pointerKind(Kind)));
+}
+
+static std::string formatFunctionOptions(FunctionOptions Options) {
+ std::vector<std::string> Opts;
+
+ PUSH_FLAG(FunctionOptions, CxxReturnUdt, Options, "returns cxx udt");
+ PUSH_FLAG(FunctionOptions, ConstructorWithVirtualBases, Options,
+ "constructor with virtual bases");
+ PUSH_FLAG(FunctionOptions, Constructor, Options, "constructor");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
+ CurrentTypeIndex = Index;
+ // formatLine puts the newline at the beginning, so we use formatLine here
+ // to start a new line, and then individual visit methods use format to
+ // append to the existing line.
+ P.formatLine("{0} | {1} [size = {2}",
+ fmt_align(Index, AlignStyle::Right, Width),
+ formatTypeLeafKind(Record.kind()), Record.length());
+ if (Hashes) {
+ std::string H;
+ if (Index.toArrayIndex() >= HashValues.size()) {
+ H = "(not present)";
+ } else {
+ uint32_t Hash = HashValues[Index.toArrayIndex()];
+ Expected<uint32_t> MaybeHash = hashTypeRecord(Record);
+ if (!MaybeHash)
+ return MaybeHash.takeError();
+ uint32_t OurHash = *MaybeHash;
+ OurHash %= NumHashBuckets;
+ if (Hash == OurHash)
+ H = "0x" + utohexstr(Hash);
+ else
+ H = "0x" + utohexstr(Hash) + ", our hash = 0x" + utohexstr(OurHash);
+ }
+ P.format(", hash = {0}", H);
+ }
+ if (RefTracker) {
+ if (RefTracker->isTypeReferenced(Index))
+ P.format(", referenced");
+ else
+ P.format(", unreferenced");
+ }
+ P.format("]");
+ P.Indent(Width + 3);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitTypeEnd(CVType &Record) {
+ P.Unindent(Width + 3);
+ if (RecordBytes) {
+ AutoIndent Indent(P, 9);
+ P.formatBinary("Bytes", Record.RecordData, 0);
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ P.formatLine("- {0}", formatTypeLeafKind(Record.Kind));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
+ if (RecordBytes) {
+ AutoIndent Indent(P, 2);
+ P.formatBinary("Bytes", Record.Data, 0);
+ }
+ return Error::success();
+}
+
+StringRef MinimalTypeDumpVisitor::getTypeName(TypeIndex TI) const {
+ if (TI.isNoneType())
+ return "";
+ return Types.getTypeName(TI);
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
+ return EC;
+
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ StringIdRecord &String) {
+ P.format(" ID: {0}, String: {1}", String.getId(), String.getString());
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ArgListRecord &Args) {
+ auto Indices = Args.getIndices();
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ StringListRecord &Strings) {
+ auto Indices = Strings.getIndices();
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ClassRecord &Class) {
+ P.format(" `{0}`", Class.Name);
+ if (Class.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Class.UniqueName);
+ P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
+ Class.VTableShape, Class.DerivationList, Class.FieldList);
+ P.formatLine("options: {0}, sizeof {1}",
+ formatClassOptions(P.getIndentLevel(), Class.Options, Stream,
+ CurrentTypeIndex),
+ Class.Size);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UnionRecord &Union) {
+ P.format(" `{0}`", Union.Name);
+ if (Union.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Union.UniqueName);
+ P.formatLine("field list: {0}", Union.FieldList);
+ P.formatLine("options: {0}, sizeof {1}",
+ formatClassOptions(P.getIndentLevel(), Union.Options, Stream,
+ CurrentTypeIndex),
+ Union.Size);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+ P.format(" `{0}`", Enum.Name);
+ if (Enum.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Enum.UniqueName);
+ P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,
+ Enum.UnderlyingType);
+ P.formatLine("options: {0}",
+ formatClassOptions(P.getIndentLevel(), Enum.Options, Stream,
+ CurrentTypeIndex));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+ if (AT.Name.empty()) {
+ P.formatLine("size: {0}, index type: {1}, element type: {2}", AT.Size,
+ AT.IndexType, AT.ElementType);
+ } else {
+ P.formatLine("name: {0}, size: {1}, index type: {2}, element type: {3}",
+ AT.Name, AT.Size, AT.IndexType, AT.ElementType);
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableRecord &VFT) {
+ P.formatLine("offset: {0}, complete class: {1}, overridden vftable: {2}",
+ VFT.VFPtrOffset, VFT.CompleteClass, VFT.OverriddenVFTable);
+ P.formatLine("method names: ");
+ if (!VFT.MethodNames.empty()) {
+ std::string Sep =
+ formatv("\n{0}",
+ fmt_repeat(' ', P.getIndentLevel() + strlen("method names: ")))
+ .str();
+ P.print(join(VFT.MethodNames, Sep));
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Id) {
+ P.formatLine("name = {0}, type = {1}, class type = {2}", Id.Name,
+ Id.FunctionType, Id.ClassType);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Proc) {
+ P.formatLine("return type = {0}, # args = {1}, param list = {2}",
+ Proc.ReturnType, Proc.ParameterCount, Proc.ArgumentList);
+ P.formatLine("calling conv = {0}, options = {1}",
+ formatCallingConvention(Proc.CallConv),
+ formatFunctionOptions(Proc.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &MF) {
+ P.formatLine("return type = {0}, # args = {1}, param list = {2}",
+ MF.ReturnType, MF.ParameterCount, MF.ArgumentList);
+ P.formatLine("class type = {0}, this type = {1}, this adjust = {2}",
+ MF.ClassType, MF.ThisType, MF.ThisPointerAdjustment);
+ P.formatLine("calling conv = {0}, options = {1}",
+ formatCallingConvention(MF.CallConv),
+ formatFunctionOptions(MF.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FuncIdRecord &Func) {
+ P.formatLine("name = {0}, type = {1}, parent scope = {2}", Func.Name,
+ Func.FunctionType, Func.ParentScope);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &TS) {
+ P.formatLine("name = {0}, age = {1}, guid = {2}", TS.Name, TS.Age, TS.Guid);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ PointerRecord &Ptr) {
+ P.formatLine("referent = {0}, {1}", Ptr.ReferentType,
+ formatPointerAttrs(Ptr));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ModifierRecord &Mod) {
+ P.formatLine("referent = {0}, modifiers = {1}", Mod.ModifiedType,
+ modifierOptions(Mod.Modifiers));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &U) {
+ P.formatLine("udt = {0}, mod = {1}, file = {2}, line = {3}", U.UDT, U.Module,
+ U.SourceFile.getIndex(), U.LineNumber);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &U) {
+ P.formatLine("udt = {0}, file = {1}, line = {2}", U.UDT,
+ U.SourceFile.getIndex(), U.LineNumber);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ BitFieldRecord &BF) {
+ P.formatLine("type = {0}, bit offset = {1}, # bits = {2}", BF.Type,
+ BF.BitOffset, BF.BitSize);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(
+ CVType &CVR, MethodOverloadListRecord &Overloads) {
+ for (auto &M : Overloads.Methods)
+ P.formatLine("- Method [type = {0}, vftable offset = {1}, attrs = {2}]",
+ M.Type, M.VFTableOffset, memberAttributes(M.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ BuildInfoRecord &BI) {
+ auto Indices = BI.ArgIndices;
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
+ std::string Type = (R.Mode == LabelType::Far) ? "far" : "near";
+ P.format(" type = {0}", Type);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ PrecompRecord &Precomp) {
+ P.format(" start index = {0:X+}, types count = {1:X+}, signature = {2:X+},"
+ " precomp path = {3}",
+ Precomp.StartTypeIndex, Precomp.TypesCount, Precomp.Signature,
+ Precomp.PrecompFilePath);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ EndPrecompRecord &EP) {
+ P.format(" signature = {0:X+}", EP.Signature);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
+ P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ P.format(" [name = `{0}`]", Method.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, vftable offset = {1}, attrs = {2}", Method.Type,
+ Method.VFTableOffset, memberAttributes(Method.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
+ P.format(" [name = `{0}`, # overloads = {1}, overload list = {2}]",
+ Method.Name, Method.NumOverloads, Method.MethodList);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
+ P.format(" [name = `{0}`, Type = {1}, offset = {2}, attrs = {3}]", Field.Name,
+ Field.Type, Field.FieldOffset, memberAttributes(Field.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
+ P.format(" [name = `{0}`, type = {1}, attrs = {2}]", Field.Name, Field.Type,
+ memberAttributes(Field.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
+ P.format(" [{0} = {1}]", Enum.Name,
+ Enum.Value.toString(10, Enum.Value.isSigned()));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, offset = {1}, attrs = {2}", Base.Type, Base.Offset,
+ memberAttributes(Base.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Base) {
+ AutoIndent Indent(P);
+ P.formatLine(
+ "base = {0}, vbptr = {1}, vbptr offset = {2}, vtable index = {3}",
+ Base.BaseType, Base.VBPtrType, Base.VBPtrOffset, Base.VTableIndex);
+ P.formatLine("attrs = {0}", memberAttributes(Base.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
+ P.format(" continuation = {0}", Cont.ContinuationIndex);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFP) {
+ P.format(" type = {0}", VFP.Type);
+ return Error::success();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.h
new file mode 100644
index 0000000000..6bc456d47a
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/MinimalTypeDumper.h
@@ -0,0 +1,70 @@
+//===- MinimalTypeDumper.h ------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_TYPE_DUMPER_H
+#define LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_TYPE_DUMPER_H
+
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/BinaryStreamArray.h"
+
+namespace llvm {
+namespace codeview {
+class LazyRandomTypeCollection;
+}
+
+namespace pdb {
+class LinePrinter;
+class TpiStream;
+class TypeReferenceTracker;
+
+class MinimalTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
+public:
+ MinimalTypeDumpVisitor(LinePrinter &P, uint32_t Width, bool RecordBytes,
+ bool Hashes, codeview::LazyRandomTypeCollection &Types,
+ TypeReferenceTracker *RefTracker,
+ uint32_t NumHashBuckets,
+ FixedStreamArray<support::ulittle32_t> HashValues,
+ pdb::TpiStream *Stream)
+ : P(P), Width(Width), RecordBytes(RecordBytes), Hashes(Hashes),
+ Types(Types), RefTracker(RefTracker), NumHashBuckets(NumHashBuckets),
+ HashValues(HashValues), Stream(Stream) {}
+
+ Error visitTypeBegin(codeview::CVType &Record,
+ codeview::TypeIndex Index) override;
+ Error visitTypeEnd(codeview::CVType &Record) override;
+ Error visitMemberBegin(codeview::CVMemberRecord &Record) override;
+ Error visitMemberEnd(codeview::CVMemberRecord &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownRecord(codeview::CVType &CVR, \
+ codeview::Name##Record &Record) override;
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownMember(codeview::CVMemberRecord &CVR, \
+ codeview::Name##Record &Record) override;
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+
+private:
+ StringRef getTypeName(codeview::TypeIndex TI) const;
+
+ LinePrinter &P;
+ uint32_t Width;
+ bool RecordBytes = false;
+ bool Hashes = false;
+ codeview::LazyRandomTypeCollection &Types;
+ pdb::TypeReferenceTracker *RefTracker = nullptr;
+ uint32_t NumHashBuckets;
+ codeview::TypeIndex CurrentTypeIndex;
+ FixedStreamArray<support::ulittle32_t> HashValues;
+ pdb::TpiStream *Stream = nullptr;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/OutputStyle.h b/contrib/libs/llvm12/tools/llvm-pdbutil/OutputStyle.h
new file mode 100644
index 0000000000..40b0de8bdf
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/OutputStyle.h
@@ -0,0 +1,27 @@
+//===- OutputStyle.h ------------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class OutputStyle {
+public:
+ virtual ~OutputStyle() {}
+
+ virtual Error dump() = 0;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.cpp
new file mode 100644
index 0000000000..a26241967b
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.cpp
@@ -0,0 +1,189 @@
+//===-- PdbYaml.cpp ------------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbYaml.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+using namespace llvm::pdb::yaml;
+using namespace llvm::yaml;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PDB_Machine> {
+ static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) {
+ io.enumCase(Value, "Invalid", PDB_Machine::Invalid);
+ io.enumCase(Value, "Am33", PDB_Machine::Am33);
+ io.enumCase(Value, "Amd64", PDB_Machine::Amd64);
+ io.enumCase(Value, "Arm", PDB_Machine::Arm);
+ io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT);
+ io.enumCase(Value, "Ebc", PDB_Machine::Ebc);
+ io.enumCase(Value, "x86", PDB_Machine::x86);
+ io.enumCase(Value, "Ia64", PDB_Machine::Ia64);
+ io.enumCase(Value, "M32R", PDB_Machine::M32R);
+ io.enumCase(Value, "Mips16", PDB_Machine::Mips16);
+ io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu);
+ io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16);
+ io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP);
+ io.enumCase(Value, "R4000", PDB_Machine::R4000);
+ io.enumCase(Value, "SH3", PDB_Machine::SH3);
+ io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP);
+ io.enumCase(Value, "Thumb", PDB_Machine::Thumb);
+ io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2);
+ io.enumCase(Value, "Arm64", PDB_Machine::Arm64);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_DbiVer> {
+ static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) {
+ io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41);
+ io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50);
+ io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60);
+ io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70);
+ io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_ImplVer> {
+ static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) {
+ io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2);
+ io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4);
+ io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41);
+ io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50);
+ io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98);
+ io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep);
+ io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70);
+ io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80);
+ io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110);
+ io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> {
+ static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) {
+ io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40);
+ io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41);
+ io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50);
+ io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70);
+ io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_FeatureSig> {
+ static void enumeration(IO &io, PdbRaw_FeatureSig &Features) {
+ io.enumCase(Features, "MinimalDebugInfo",
+ PdbRaw_FeatureSig::MinimalDebugInfo);
+ io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge);
+ io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110);
+ io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140);
+ }
+};
+}
+}
+
+void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
+ IO.mapOptional("MSF", Obj.Headers);
+ IO.mapOptional("StreamSizes", Obj.StreamSizes);
+ IO.mapOptional("StreamMap", Obj.StreamMap);
+ IO.mapOptional("StringTable", Obj.StringTable);
+ IO.mapOptional("PdbStream", Obj.PdbStream);
+ IO.mapOptional("DbiStream", Obj.DbiStream);
+ IO.mapOptional("TpiStream", Obj.TpiStream);
+ IO.mapOptional("IpiStream", Obj.IpiStream);
+ IO.mapOptional("PublicsStream", Obj.PublicsStream);
+}
+
+void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
+ IO.mapOptional("SuperBlock", Obj.SuperBlock);
+ IO.mapOptional("NumDirectoryBlocks", Obj.NumDirectoryBlocks);
+ IO.mapOptional("DirectoryBlocks", Obj.DirectoryBlocks);
+ IO.mapOptional("NumStreams", Obj.NumStreams);
+ IO.mapOptional("FileSize", Obj.FileSize);
+}
+
+void MappingTraits<msf::SuperBlock>::mapping(IO &IO, msf::SuperBlock &SB) {
+ if (!IO.outputting()) {
+ ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic));
+ }
+
+ using u32 = support::ulittle32_t;
+ IO.mapOptional("BlockSize", SB.BlockSize, u32(4096U));
+ IO.mapOptional("FreeBlockMap", SB.FreeBlockMapBlock, u32(0U));
+ IO.mapOptional("NumBlocks", SB.NumBlocks, u32(0U));
+ IO.mapOptional("NumDirectoryBytes", SB.NumDirectoryBytes, u32(0U));
+ IO.mapOptional("Unknown1", SB.Unknown1, u32(0U));
+ IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U));
+}
+
+void MappingTraits<StreamBlockList>::mapping(IO &IO, StreamBlockList &SB) {
+ IO.mapRequired("Stream", SB.Blocks);
+}
+
+void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) {
+ IO.mapOptional("Age", Obj.Age, 1U);
+ IO.mapOptional("Guid", Obj.Guid);
+ IO.mapOptional("Signature", Obj.Signature, 0U);
+ IO.mapOptional("Features", Obj.Features);
+ IO.mapOptional("Version", Obj.Version, PdbImplVC70);
+}
+
+void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
+ IO.mapOptional("VerHeader", Obj.VerHeader, PdbDbiV70);
+ IO.mapOptional("Age", Obj.Age, 1U);
+ IO.mapOptional("BuildNumber", Obj.BuildNumber, uint16_t(0U));
+ IO.mapOptional("PdbDllVersion", Obj.PdbDllVersion, 0U);
+ IO.mapOptional("PdbDllRbld", Obj.PdbDllRbld, uint16_t(0U));
+ IO.mapOptional("Flags", Obj.Flags, uint16_t(1U));
+ IO.mapOptional("MachineType", Obj.MachineType, PDB_Machine::x86);
+ IO.mapOptional("Modules", Obj.ModInfos);
+}
+
+void MappingTraits<PdbTpiStream>::mapping(IO &IO,
+ pdb::yaml::PdbTpiStream &Obj) {
+ IO.mapOptional("Version", Obj.Version, PdbTpiV80);
+ IO.mapRequired("Records", Obj.Records);
+}
+
+void MappingTraits<PdbPublicsStream>::mapping(
+ IO &IO, pdb::yaml::PdbPublicsStream &Obj) {
+ IO.mapRequired("Records", Obj.PubSyms);
+}
+
+void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
+ NamedStreamMapping &Obj) {
+ IO.mapRequired("Name", Obj.StreamName);
+ IO.mapRequired("StreamNum", Obj.StreamNumber);
+}
+
+void MappingTraits<PdbModiStream>::mapping(IO &IO, PdbModiStream &Obj) {
+ IO.mapOptional("Signature", Obj.Signature, 4U);
+ IO.mapRequired("Records", Obj.Symbols);
+}
+
+void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
+ IO.mapRequired("Module", Obj.Mod);
+ IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod);
+ IO.mapOptional("SourceFiles", Obj.SourceFiles);
+ IO.mapOptional("Subsections", Obj.Subsections);
+ IO.mapOptional("Modi", Obj.Modi);
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.h
new file mode 100644
index 0000000000..ed6346c2c4
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PdbYaml.h
@@ -0,0 +1,130 @@
+//===- PdbYAML.h ---------------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
+
+#include "OutputStyle.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/YAMLTraits.h"
+
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class DebugStringTableSubsection;
+}
+namespace pdb {
+
+namespace yaml {
+struct SerializationContext;
+
+struct MSFHeaders {
+ msf::SuperBlock SuperBlock;
+ uint32_t NumDirectoryBlocks = 0;
+ std::vector<uint32_t> DirectoryBlocks;
+ uint32_t NumStreams = 0;
+ uint32_t FileSize = 0;
+};
+
+struct StreamBlockList {
+ std::vector<uint32_t> Blocks;
+};
+
+struct NamedStreamMapping {
+ StringRef StreamName;
+ uint32_t StreamNumber;
+};
+
+struct PdbInfoStream {
+ PdbRaw_ImplVer Version = PdbImplVC70;
+ uint32_t Signature = 0;
+ uint32_t Age = 1;
+ codeview::GUID Guid;
+ std::vector<PdbRaw_FeatureSig> Features;
+ std::vector<NamedStreamMapping> NamedStreams;
+};
+
+struct PdbModiStream {
+ uint32_t Signature;
+ std::vector<CodeViewYAML::SymbolRecord> Symbols;
+};
+
+struct PdbDbiModuleInfo {
+ StringRef Obj;
+ StringRef Mod;
+ std::vector<StringRef> SourceFiles;
+ std::vector<CodeViewYAML::YAMLDebugSubsection> Subsections;
+ Optional<PdbModiStream> Modi;
+};
+
+struct PdbDbiStream {
+ PdbRaw_DbiVer VerHeader = PdbDbiV70;
+ uint32_t Age = 1;
+ uint16_t BuildNumber = 0;
+ uint32_t PdbDllVersion = 0;
+ uint16_t PdbDllRbld = 0;
+ uint16_t Flags = 1;
+ PDB_Machine MachineType = PDB_Machine::x86;
+
+ std::vector<PdbDbiModuleInfo> ModInfos;
+};
+
+struct PdbTpiStream {
+ PdbRaw_TpiVer Version = PdbTpiV80;
+ std::vector<CodeViewYAML::LeafRecord> Records;
+};
+
+struct PdbPublicsStream {
+ std::vector<CodeViewYAML::SymbolRecord> PubSyms;
+};
+
+struct PdbObject {
+ explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
+
+ Optional<MSFHeaders> Headers;
+ Optional<std::vector<uint32_t>> StreamSizes;
+ Optional<std::vector<StreamBlockList>> StreamMap;
+ Optional<PdbInfoStream> PdbStream;
+ Optional<PdbDbiStream> DbiStream;
+ Optional<PdbTpiStream> TpiStream;
+ Optional<PdbTpiStream> IpiStream;
+ Optional<PdbPublicsStream> PublicsStream;
+
+ Optional<std::vector<StringRef>> StringTable;
+
+ BumpPtrAllocator &Allocator;
+};
+}
+}
+}
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbObject)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::MSFHeaders)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(msf::SuperBlock)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::StreamBlockList)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbInfoStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbTpiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbPublicsStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::NamedStreamMapping)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbModiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiModuleInfo)
+
+#endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
new file mode 100644
index 0000000000..cd01a40048
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
@@ -0,0 +1,97 @@
+//===- PrettyBuiltinDumper.cpp ---------------------------------- *- C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyBuiltinDumper.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+BuiltinDumper::BuiltinDumper(LinePrinter &P)
+ : PDBSymDumper(false), Printer(P) {}
+
+void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol);
+}
+
+StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
+ PDB_BuiltinType Type = Symbol.getBuiltinType();
+ switch (Type) {
+ case PDB_BuiltinType::Float:
+ if (Symbol.getLength() == 4)
+ return "float";
+ return "double";
+ case PDB_BuiltinType::UInt:
+ switch (Symbol.getLength()) {
+ case 8:
+ return "unsigned __int64";
+ case 4:
+ return "unsigned int";
+ case 2:
+ return "unsigned short";
+ case 1:
+ return "unsigned char";
+ default:
+ return "unsigned";
+ }
+ case PDB_BuiltinType::Int:
+ switch (Symbol.getLength()) {
+ case 8:
+ return "__int64";
+ case 4:
+ return "int";
+ case 2:
+ return "short";
+ case 1:
+ return "char";
+ default:
+ return "int";
+ }
+ case PDB_BuiltinType::Char:
+ return "char";
+ case PDB_BuiltinType::WCharT:
+ return "wchar_t";
+ case PDB_BuiltinType::Void:
+ return "void";
+ case PDB_BuiltinType::Long:
+ return "long";
+ case PDB_BuiltinType::ULong:
+ return "unsigned long";
+ case PDB_BuiltinType::Bool:
+ return "bool";
+ case PDB_BuiltinType::Currency:
+ return "CURRENCY";
+ case PDB_BuiltinType::Date:
+ return "DATE";
+ case PDB_BuiltinType::Variant:
+ return "VARIANT";
+ case PDB_BuiltinType::Complex:
+ return "complex";
+ case PDB_BuiltinType::Bitfield:
+ return "bitfield";
+ case PDB_BuiltinType::BSTR:
+ return "BSTR";
+ case PDB_BuiltinType::HResult:
+ return "HRESULT";
+ case PDB_BuiltinType::BCD:
+ return "HRESULT";
+ case PDB_BuiltinType::Char16:
+ return "char16_t";
+ case PDB_BuiltinType::Char32:
+ return "char32_t";
+ case PDB_BuiltinType::None:
+ return "...";
+ }
+ llvm_unreachable("Unknown PDB_BuiltinType");
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.h
new file mode 100644
index 0000000000..3bdef34c48
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyBuiltinDumper.h
@@ -0,0 +1,34 @@
+//===- PrettyBuiltinDumper.h ---------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class BuiltinDumper : public PDBSymDumper {
+public:
+ BuiltinDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeBuiltin &Symbol);
+
+private:
+ StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol);
+
+ LinePrinter &Printer;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
new file mode 100644
index 0000000000..b7eccac598
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
@@ -0,0 +1,114 @@
+//===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassDefinitionDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyClassLayoutGraphicalDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
+ assert(opts::pretty::ClassFormat !=
+ opts::pretty::ClassDefinitionFormat::None);
+
+ ClassLayout Layout(Class);
+ start(Layout);
+}
+
+void ClassDefinitionDumper::start(const ClassLayout &Layout) {
+ prettyPrintClassIntro(Layout);
+
+ PrettyClassLayoutGraphicalDumper Dumper(Printer, 1, 0);
+ DumpedAnything |= Dumper.start(Layout);
+
+ prettyPrintClassOutro(Layout);
+}
+
+void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) {
+ DumpedAnything = false;
+ Printer.NewLine();
+
+ uint32_t Size = Layout.getSize();
+ const PDBSymbolTypeUDT &Class = Layout.getClass();
+
+ if (Layout.getClass().isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Layout.getClass().isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ if (Layout.getClass().isUnalignedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
+
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+ WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
+ << "]";
+ uint32_t BaseCount = Layout.bases().size();
+ if (BaseCount > 0) {
+ Printer.Indent();
+ char NextSeparator = ':';
+ for (auto BC : Layout.bases()) {
+ const auto &Base = BC->getBase();
+ if (Base.isIndirectVirtualBaseClass())
+ continue;
+
+ Printer.NewLine();
+ Printer << NextSeparator << " ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess();
+ if (BC->isVirtualBase())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
+
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
+ NextSeparator = ',';
+ }
+
+ Printer.Unindent();
+ }
+
+ Printer << " {";
+ Printer.Indent();
+}
+
+void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) {
+ Printer.Unindent();
+ if (DumpedAnything)
+ Printer.NewLine();
+ Printer << "}";
+ Printer.NewLine();
+ if (Layout.deepPaddingSize() > 0) {
+ APFloat Pct(100.0 * (double)Layout.deepPaddingSize() /
+ (double)Layout.getSize());
+ SmallString<8> PctStr;
+ Pct.toString(PctStr, 4);
+ WithColor(Printer, PDB_ColorItem::Padding).get()
+ << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr
+ << "% of class size)";
+ Printer.NewLine();
+ APFloat Pct2(100.0 * (double)Layout.immediatePadding() /
+ (double)Layout.getSize());
+ PctStr.clear();
+ Pct2.toString(PctStr, 4);
+ WithColor(Printer, PDB_ColorItem::Padding).get()
+ << "Immediate padding " << Layout.immediatePadding() << " bytes ("
+ << PctStr << "% of class size)";
+ Printer.NewLine();
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
new file mode 100644
index 0000000000..f43c5c11bd
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
@@ -0,0 +1,46 @@
+//===- PrettyClassDefinitionDumper.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+
+#include <list>
+#include <memory>
+#include <unordered_map>
+
+namespace llvm {
+class BitVector;
+
+namespace pdb {
+
+class ClassLayout;
+class LinePrinter;
+
+class ClassDefinitionDumper : public PDBSymDumper {
+public:
+ ClassDefinitionDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeUDT &Class);
+ void start(const ClassLayout &Class);
+
+private:
+ void prettyPrintClassIntro(const ClassLayout &Class);
+ void prettyPrintClassOutro(const ClassLayout &Class);
+
+ LinePrinter &Printer;
+ bool DumpedAnything = false;
+};
+}
+}
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
new file mode 100644
index 0000000000..a522935e34
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
@@ -0,0 +1,212 @@
+//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassLayoutGraphicalDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "PrettyVariableDumper.h"
+#include "PrettyVariableDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
+ LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
+ : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
+ ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
+
+bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
+
+ if (RecursionLevel == 1 &&
+ opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
+ for (auto &Other : Layout.other_items())
+ Other->dump(*this);
+ for (auto &Func : Layout.funcs())
+ Func->dump(*this);
+ }
+
+ const BitVector &UseMap = Layout.usedBytes();
+ int NextPaddingByte = UseMap.find_first_unset();
+
+ for (auto &Item : Layout.layout_items()) {
+ // Calculate the absolute offset of the first byte of the next field.
+ uint32_t RelativeOffset = Item->getOffsetInParent();
+ CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
+
+ // This might be an empty base, in which case it could extend outside the
+ // bounds of the parent class.
+ if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
+ // If there is any remaining padding in this class, and the offset of the
+ // new item is after the padding, then we must have just jumped over some
+ // padding. Print a padding row and then look for where the next block
+ // of padding begins.
+ if ((NextPaddingByte >= 0) &&
+ (RelativeOffset > uint32_t(NextPaddingByte))) {
+ printPaddingRow(RelativeOffset - NextPaddingByte);
+ NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
+ }
+ }
+
+ CurrentItem = Item;
+ if (Item->isVBPtr()) {
+ VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
+
+ VariableDumper VarDumper(Printer);
+ VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
+ } else {
+ if (auto Sym = Item->getSymbol())
+ Sym->dump(*this);
+ }
+
+ if (Item->getLayoutSize() > 0) {
+ uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
+ if (Prev < UseMap.size())
+ NextPaddingByte = UseMap.find_next_unset(Prev);
+ }
+ }
+
+ auto TailPadding = Layout.tailPadding();
+ if (TailPadding > 0) {
+ if (TailPadding != 1 || Layout.getSize() != 1) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Padding).get()
+ << "<padding> (" << TailPadding << " bytes)";
+ DumpedAnything = true;
+ }
+ }
+
+ return DumpedAnything;
+}
+
+void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
+ if (Amount == 0)
+ return;
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
+ << " bytes)";
+ DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+ const PDBSymbolTypeBaseClass &Symbol) {
+ assert(CurrentItem != nullptr);
+
+ Printer.NewLine();
+ BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
+
+ std::string Label = "base";
+ if (Layout.isVirtualBase()) {
+ Label.insert(Label.begin(), 'v');
+ if (Layout.getBase().isIndirectVirtualBaseClass())
+ Label.insert(Label.begin(), 'i');
+ }
+ Printer << Label << " ";
+
+ uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
+
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
+ << "] ";
+
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
+
+ if (shouldRecurse()) {
+ Printer.Indent();
+ uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+ PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
+ ChildOffsetZero);
+ DumpedAnything |= BaseDumper.start(Layout);
+ Printer.Unindent();
+ }
+
+ DumpedAnything = true;
+}
+
+bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
+ uint32_t Limit = opts::pretty::ClassRecursionDepth;
+ if (Limit == 0)
+ return true;
+ return RecursionLevel < Limit;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
+ VariableDumper VarDumper(Printer);
+ VarDumper.start(Symbol, ClassOffsetZero);
+
+ if (CurrentItem != nullptr) {
+ DataMemberLayoutItem &Layout =
+ static_cast<DataMemberLayoutItem &>(*CurrentItem);
+
+ if (Layout.hasUDTLayout() && shouldRecurse()) {
+ uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+ Printer.Indent();
+ PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
+ ChildOffsetZero);
+ TypeDumper.start(Layout.getUDTLayout());
+ Printer.Unindent();
+ }
+ }
+
+ DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+ assert(CurrentItem != nullptr);
+
+ VariableDumper VarDumper(Printer);
+ VarDumper.start(Symbol, ClassOffsetZero);
+
+ DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ DumpedAnything = true;
+ Printer.NewLine();
+ EnumDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+ const PDBSymbolTypeTypedef &Symbol) {
+ DumpedAnything = true;
+ Printer.NewLine();
+ TypedefDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+ const PDBSymbolTypeBuiltin &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+ if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+ return;
+ if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
+ !Symbol.isIntroVirtualFunction())
+ return;
+
+ DumpedAnything = true;
+ Printer.NewLine();
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
new file mode 100644
index 0000000000..8f78b3b503
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
@@ -0,0 +1,57 @@
+//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+namespace pdb {
+
+class UDTLayoutBase;
+class LayoutItemBase;
+class LinePrinter;
+
+class PrettyClassLayoutGraphicalDumper : public PDBSymDumper {
+public:
+ PrettyClassLayoutGraphicalDumper(LinePrinter &P, uint32_t RecurseLevel,
+ uint32_t InitialOffset);
+
+ bool start(const UDTLayoutBase &Layout);
+
+ // Layout based symbol types.
+ void dump(const PDBSymbolTypeBaseClass &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+ // Non layout-based symbol types.
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+
+private:
+ bool shouldRecurse() const;
+ void printPaddingRow(uint32_t Amount);
+
+ LinePrinter &Printer;
+
+ LayoutItemBase *CurrentItem = nullptr;
+ uint32_t RecursionLevel = 0;
+ uint32_t ClassOffsetZero = 0;
+ uint32_t CurrentAbsoluteOffset = 0;
+ bool DumpedAnything = false;
+};
+}
+}
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
new file mode 100644
index 0000000000..cf769ff664
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
@@ -0,0 +1,228 @@
+//===- PrettyCompilandDumper.cpp - llvm-pdbutil compiland dumper -*- C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyCompilandDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyFunctionDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+CompilandDumper::CompilandDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {}
+
+void CompilandDumper::start(const PDBSymbolCompiland &Symbol,
+ CompilandDumpFlags opts) {
+ std::string FullName = Symbol.getName();
+ if (Printer.IsCompilandExcluded(FullName))
+ return;
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Path).get() << FullName;
+
+ if (opts & Flags::Lines) {
+ const IPDBSession &Session = Symbol.getSession();
+ if (auto Files = Session.getSourceFilesForCompiland(Symbol)) {
+ Printer.Indent();
+ while (auto File = Files->getNext()) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName();
+ if (File->getChecksumType() != PDB_Checksum::None) {
+ auto ChecksumType = File->getChecksumType();
+ auto ChecksumHexString = toHex(File->getChecksum());
+ WithColor(Printer, PDB_ColorItem::Comment).get()
+ << " (" << ChecksumType << ": " << ChecksumHexString << ")";
+ }
+
+ auto Lines = Session.findLineNumbers(Symbol, *File);
+ if (!Lines)
+ continue;
+
+ Printer.Indent();
+ while (auto Line = Lines->getNext()) {
+ Printer.NewLine();
+ uint32_t LineStart = Line->getLineNumber();
+ uint32_t LineEnd = Line->getLineNumberEnd();
+
+ Printer << "Line ";
+ PDB_ColorItem StatementColor = Line->isStatement()
+ ? PDB_ColorItem::Keyword
+ : PDB_ColorItem::LiteralValue;
+ WithColor(Printer, StatementColor).get() << LineStart;
+ if (LineStart != LineEnd)
+ WithColor(Printer, StatementColor).get() << " - " << LineEnd;
+
+ uint32_t ColumnStart = Line->getColumnNumber();
+ uint32_t ColumnEnd = Line->getColumnNumberEnd();
+ if (ColumnStart != 0 || ColumnEnd != 0) {
+ Printer << ", Column: ";
+ WithColor(Printer, StatementColor).get() << ColumnStart;
+ if (ColumnEnd != ColumnStart)
+ WithColor(Printer, StatementColor).get() << " - " << ColumnEnd;
+ }
+
+ Printer << ", Address: ";
+ if (Line->getLength() > 0) {
+ uint64_t AddrStart = Line->getVirtualAddress();
+ uint64_t AddrEnd = AddrStart + Line->getLength() - 1;
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(AddrStart, 10) << " - "
+ << format_hex(AddrEnd, 10) << "]";
+ Printer << " (" << Line->getLength() << " bytes)";
+ } else {
+ uint64_t AddrStart = Line->getVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(AddrStart, 10) << "] ";
+ Printer << "(0 bytes)";
+ }
+ }
+ Printer.Unindent();
+ }
+ Printer.Unindent();
+ }
+ }
+
+ if (opts & Flags::Children) {
+ if (auto ChildrenEnum = Symbol.findAllChildren()) {
+ Printer.Indent();
+ while (auto Child = ChildrenEnum->getNext())
+ Child->dump(*this);
+ Printer.Unindent();
+ }
+ }
+}
+
+void CompilandDumper::dump(const PDBSymbolData &Symbol) {
+ if (!shouldDumpSymLevel(opts::pretty::SymLevel::Data))
+ return;
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+
+ switch (auto LocType = Symbol.getLocationType()) {
+ case PDB_LocType::Static:
+ Printer << "data: ";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]";
+
+ WithColor(Printer, PDB_ColorItem::Comment).get()
+ << " [sizeof = " << getTypeLength(Symbol) << "]";
+
+ break;
+ case PDB_LocType::Constant:
+ Printer << "constant: ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+ << "[" << Symbol.getValue() << "]";
+ WithColor(Printer, PDB_ColorItem::Comment).get()
+ << " [sizeof = " << getTypeLength(Symbol) << "]";
+ break;
+ default:
+ Printer << "data(unexpected type=" << LocType << ")";
+ }
+
+ Printer << " ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolFunc &Symbol) {
+ if (!shouldDumpSymLevel(opts::pretty::SymLevel::Functions))
+ return;
+ if (Symbol.getLength() == 0)
+ return;
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
+
+void CompilandDumper::dump(const PDBSymbolLabel &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ Printer << "label ";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
+ if (!shouldDumpSymLevel(opts::pretty::SymLevel::Thunks))
+ return;
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ Printer << "thunk ";
+ codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
+ uint64_t VA = Symbol.getVirtualAddress();
+ if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) {
+ uint64_t Target = Symbol.getTargetVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10);
+ Printer << " -> ";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10);
+ } else {
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(VA, 10) << " - "
+ << format_hex(VA + Symbol.getLength(), 10) << "]";
+ }
+ Printer << " (";
+ WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
+ Printer << ") ";
+ std::string Name = Symbol.getName();
+ if (!Name.empty())
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+}
+
+void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) {
+ Printer.NewLine();
+ Printer << "unknown (" << Symbol.getSymTag() << ")";
+}
+
+void CompilandDumper::dump(const PDBSymbolUsingNamespace &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ Printer << "using namespace ";
+ std::string Name = Symbol.getName();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.h
new file mode 100644
index 0000000000..c83a58672d
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyCompilandDumper.h
@@ -0,0 +1,44 @@
+//===- PrettyCompilandDumper.h - llvm-pdbutil compiland dumper -*- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+typedef int CompilandDumpFlags;
+class CompilandDumper : public PDBSymDumper {
+public:
+ enum Flags { None = 0x0, Children = 0x1, Symbols = 0x2, Lines = 0x4 };
+
+ CompilandDumper(LinePrinter &P);
+
+ void start(const PDBSymbolCompiland &Symbol, CompilandDumpFlags flags);
+
+ void dump(const PDBSymbolCompilandDetails &Symbol) override;
+ void dump(const PDBSymbolCompilandEnv &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolLabel &Symbol) override;
+ void dump(const PDBSymbolThunk &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolUnknown &Symbol) override;
+ void dump(const PDBSymbolUsingNamespace &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.cpp
new file mode 100644
index 0000000000..9ed5893f25
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.cpp
@@ -0,0 +1,68 @@
+//===- PrettyEnumDumper.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyEnumDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
+ if (Symbol.getUnmodifiedTypeId() != 0) {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ if (Symbol.isUnalignedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+ return;
+ }
+
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+ if (!opts::pretty::NoEnumDefs) {
+ auto UnderlyingType = Symbol.getUnderlyingType();
+ if (!UnderlyingType)
+ return;
+ if (UnderlyingType->getBuiltinType() != PDB_BuiltinType::Int ||
+ UnderlyingType->getLength() != 4) {
+ Printer << " : ";
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(*UnderlyingType);
+ }
+ auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
+ Printer << " {";
+ Printer.Indent();
+ if (EnumValues && EnumValues->getChildCount() > 0) {
+ while (auto EnumValue = EnumValues->getNext()) {
+ if (EnumValue->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << EnumValue->getName();
+ Printer << " = ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+ << EnumValue->getValue();
+ }
+ }
+ Printer.Unindent();
+ Printer.NewLine();
+ Printer << "}";
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.h
new file mode 100644
index 0000000000..e7c5c1aeb0
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyEnumDumper.h
@@ -0,0 +1,30 @@
+//===- PrettyEnumDumper.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class EnumDumper : public PDBSymDumper {
+public:
+ EnumDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeEnum &Symbol);
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
new file mode 100644
index 0000000000..fede031ec0
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
@@ -0,0 +1,41 @@
+//===- PrettyExternalSymbolDumper.cpp -------------------------- *- C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyExternalSymbolDumper.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
+ if (auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>()) {
+ while (auto Var = Vars->getNext())
+ Var->dump(*this);
+ }
+}
+
+void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+ std::string LinkageName = Symbol.getName();
+ if (Printer.IsSymbolExcluded(LinkageName))
+ return;
+
+ Printer.NewLine();
+ uint64_t Addr = Symbol.getVirtualAddress();
+
+ Printer << "public [";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
+ Printer << "] ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h
new file mode 100644
index 0000000000..58fafe9433
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h
@@ -0,0 +1,33 @@
+//===- PrettyExternalSymbolDumper.h --------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class ExternalSymbolDumper : public PDBSymDumper {
+public:
+ ExternalSymbolDumper(LinePrinter &P);
+
+ void start(const PDBSymbolExe &Symbol);
+
+ void dump(const PDBSymbolPublicSymbol &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
new file mode 100644
index 0000000000..b820ca3339
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
@@ -0,0 +1,267 @@
+//===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyFunctionDumper.h"
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+template <class T>
+void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
+ FunctionDumper &Dumper) {
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+ if (!ClassParent)
+ return;
+
+ WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
+ Printer << "::";
+}
+}
+
+FunctionDumper::FunctionDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
+ const char *Name, PointerType Pointer) {
+ auto ReturnType = Symbol.getReturnType();
+ if (!ReturnType)
+ Printer << "<unknown-type>";
+ else
+ ReturnType->dump(*this);
+ Printer << " ";
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+
+ PDB_CallingConv CC = Symbol.getCallingConvention();
+ bool ShouldDumpCallingConvention = true;
+ if ((ClassParent && CC == CallingConvention::ThisCall) ||
+ (!ClassParent && CC == CallingConvention::NearStdCall)) {
+ ShouldDumpCallingConvention = false;
+ }
+
+ if (Pointer == PointerType::None) {
+ if (ShouldDumpCallingConvention)
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+ if (ClassParent) {
+ Printer << "(";
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << ClassParent->getName();
+ Printer << "::)";
+ }
+ } else {
+ Printer << "(";
+ if (ShouldDumpCallingConvention)
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+ if (ClassParent) {
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << ClassParent->getName();
+ Printer << "::";
+ }
+ if (Pointer == PointerType::Reference)
+ Printer << "&";
+ else
+ Printer << "*";
+ if (Name)
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+ Printer << ")";
+ }
+
+ Printer << "(";
+ if (auto ChildEnum = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = ChildEnum->getNext()) {
+ Arg->dump(*this);
+ if (++Index < ChildEnum->getChildCount())
+ Printer << ", ";
+ }
+ }
+ Printer << ")";
+
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+}
+
+void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
+ uint64_t FuncStart = Symbol.getVirtualAddress();
+ uint64_t FuncEnd = FuncStart + Symbol.getLength();
+
+ Printer << "func [";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
+ if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
+ uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << formatv("+{0,2}", Prologue);
+ }
+ Printer << " - ";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
+ if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
+ uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << formatv("-{0,2}", Epilogue);
+ }
+
+ WithColor(Printer, PDB_ColorItem::Comment).get()
+ << formatv(" | sizeof={0,3}", Symbol.getLength());
+ Printer << "] (";
+
+ if (Symbol.hasFramePointer()) {
+ WithColor(Printer, PDB_ColorItem::Register).get()
+ << CPURegister{Symbol.getRawSymbol().getPlatform(),
+ Symbol.getLocalBasePointerRegisterId()};
+ } else {
+ WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
+ }
+ Printer << ") ";
+
+ if (Symbol.isVirtual() || Symbol.isPureVirtual())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
+
+ auto Signature = Symbol.getSignature();
+ if (!Signature) {
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+ if (Pointer == PointerType::Pointer)
+ Printer << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ Printer << "&";
+ return;
+ }
+
+ auto ReturnType = Signature->getReturnType();
+ ReturnType->dump(*this);
+ Printer << " ";
+
+ auto ClassParent = Symbol.getClassParent();
+ CallingConvention CC = Signature->getCallingConvention();
+ if (Pointer != FunctionDumper::PointerType::None)
+ Printer << "(";
+
+ if ((ClassParent && CC != CallingConvention::ThisCall) ||
+ (!ClassParent && CC != CallingConvention::NearStdCall)) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get()
+ << Signature->getCallingConvention() << " ";
+ }
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+ if (Pointer != FunctionDumper::PointerType::None) {
+ if (Pointer == PointerType::Pointer)
+ Printer << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ Printer << "&";
+ Printer << ")";
+ }
+
+ Printer << "(";
+ if (auto Arguments = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = Arguments->getNext()) {
+ auto ArgType = Arg->getType();
+ ArgType->dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+ << Arg->getName();
+ if (++Index < Arguments->getChildCount())
+ Printer << ", ";
+ }
+ if (Signature->isCVarArgs())
+ Printer << ", ...";
+ }
+ Printer << ")";
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+ if (Symbol.isPureVirtual())
+ Printer << " = 0";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ auto ElementType = Symbol.getElementType();
+
+ ElementType->dump(*this);
+ Printer << "[";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
+ Printer << "]";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
+ // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
+ // through to the real thing and dump it.
+ uint32_t TypeId = Symbol.getTypeId();
+ auto Type = Symbol.getSession().getSymbolById(TypeId);
+ if (Type)
+ Type->dump(*this);
+ else
+ Printer << "<unknown-type>";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ auto PointeeType = Symbol.getPointeeType();
+ if (!PointeeType)
+ return;
+
+ if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+ FunctionDumper NestedDumper(Printer);
+ PointerType Pointer =
+ Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
+ NestedDumper.start(*FuncSig, nullptr, Pointer);
+ } else {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ PointeeType->dump(*this);
+ Printer << (Symbol.isReference() ? "&" : "*");
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
+ }
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.h
new file mode 100644
index 0000000000..df62604ac8
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyFunctionDumper.h
@@ -0,0 +1,42 @@
+//===- PrettyFunctionDumper.h --------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+class LinePrinter;
+
+class FunctionDumper : public PDBSymDumper {
+public:
+ FunctionDumper(LinePrinter &P);
+
+ enum class PointerType { None, Pointer, Reference };
+
+ void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name,
+ PointerType Pointer);
+ void start(const PDBSymbolFunc &Symbol, PointerType Pointer);
+
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionArg &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.cpp
new file mode 100644
index 0000000000..2f7a39803c
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.cpp
@@ -0,0 +1,359 @@
+//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyTypeDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+using LayoutPtr = std::unique_ptr<ClassLayout>;
+
+typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
+
+static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
+ return S1->getName() < S2->getName();
+}
+
+static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
+ return S1->getSize() < S2->getSize();
+}
+
+static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
+ return S1->deepPaddingSize() < S2->deepPaddingSize();
+}
+
+static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {
+ double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();
+ double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();
+ return Pct1 < Pct2;
+}
+
+static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {
+ return S1->immediatePadding() < S2->immediatePadding();
+}
+
+static bool ComparePaddingPctImmediate(const LayoutPtr &S1,
+ const LayoutPtr &S2) {
+ double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();
+ double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();
+ return Pct1 < Pct2;
+}
+
+static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
+ switch (Mode) {
+ case opts::pretty::ClassSortMode::Name:
+ return CompareNames;
+ case opts::pretty::ClassSortMode::Size:
+ return CompareSizes;
+ case opts::pretty::ClassSortMode::Padding:
+ return ComparePadding;
+ case opts::pretty::ClassSortMode::PaddingPct:
+ return ComparePaddingPct;
+ case opts::pretty::ClassSortMode::PaddingImmediate:
+ return ComparePaddingImmediate;
+ case opts::pretty::ClassSortMode::PaddingPctImmediate:
+ return ComparePaddingPctImmediate;
+ default:
+ return nullptr;
+ }
+}
+
+template <typename Enumerator>
+static std::vector<std::unique_ptr<ClassLayout>>
+filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
+ uint32_t UnfilteredCount) {
+ std::vector<std::unique_ptr<ClassLayout>> Filtered;
+
+ Filtered.reserve(UnfilteredCount);
+ CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
+
+ if (UnfilteredCount > 10000) {
+ errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);
+ errs().flush();
+ }
+ uint32_t Examined = 0;
+ uint32_t Discarded = 0;
+ while (auto Class = E.getNext()) {
+ ++Examined;
+ if (Examined % 10000 == 0) {
+ errs() << formatv("Examined {0}/{1} items. {2} items discarded\n",
+ Examined, UnfilteredCount, Discarded);
+ errs().flush();
+ }
+
+ if (Class->getUnmodifiedTypeId() != 0) {
+ ++Discarded;
+ continue;
+ }
+
+ if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
+ ++Discarded;
+ continue;
+ }
+
+ auto Layout = std::make_unique<ClassLayout>(std::move(Class));
+ if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
+ ++Discarded;
+ continue;
+ }
+ if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {
+ ++Discarded;
+ continue;
+ }
+
+ Filtered.push_back(std::move(Layout));
+ }
+
+ if (Comp)
+ llvm::sort(Filtered, Comp);
+ return Filtered;
+}
+
+TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+template <typename T>
+static bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) {
+ return false;
+}
+
+static bool isTypeExcluded(LinePrinter &Printer,
+ const PDBSymbolTypeEnum &Enum) {
+ if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength()))
+ return true;
+ // Dump member enums when dumping their class definition.
+ if (nullptr != Enum.getClassParent())
+ return true;
+ return false;
+}
+
+static bool isTypeExcluded(LinePrinter &Printer,
+ const PDBSymbolTypeTypedef &Typedef) {
+ return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength());
+}
+
+template <typename SymbolT>
+static void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe,
+ TypeDumper &TD, StringRef Label) {
+ if (auto Children = Exe.findAllChildren<SymbolT>()) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Label;
+ Printer << ": (" << Children->getChildCount() << " items)";
+ Printer.Indent();
+ while (auto Child = Children->getNext()) {
+ if (isTypeExcluded(Printer, *Child))
+ continue;
+
+ Printer.NewLine();
+ Child->dump(TD);
+ }
+ Printer.Unindent();
+ }
+}
+
+static void printClassDecl(LinePrinter &Printer,
+ const PDBSymbolTypeUDT &Class) {
+ if (Class.getUnmodifiedTypeId() != 0) {
+ if (Class.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Class.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ if (Class.isUnalignedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
+ }
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+}
+
+void TypeDumper::start(const PDBSymbolExe &Exe) {
+ if (opts::pretty::Enums)
+ dumpSymbolCategory<PDBSymbolTypeEnum>(Printer, Exe, *this, "Enums");
+
+ if (opts::pretty::Funcsigs)
+ dumpSymbolCategory<PDBSymbolTypeFunctionSig>(Printer, Exe, *this,
+ "Function Signatures");
+
+ if (opts::pretty::Typedefs)
+ dumpSymbolCategory<PDBSymbolTypeTypedef>(Printer, Exe, *this, "Typedefs");
+
+ if (opts::pretty::Arrays)
+ dumpSymbolCategory<PDBSymbolTypeArray>(Printer, Exe, *this, "Arrays");
+
+ if (opts::pretty::Pointers)
+ dumpSymbolCategory<PDBSymbolTypePointer>(Printer, Exe, *this, "Pointers");
+
+ if (opts::pretty::VTShapes)
+ dumpSymbolCategory<PDBSymbolTypeVTableShape>(Printer, Exe, *this,
+ "VFTable Shapes");
+
+ if (opts::pretty::Classes) {
+ if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
+ uint32_t All = Classes->getChildCount();
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
+
+ bool Precompute = false;
+ Precompute =
+ (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
+
+ // If we're using no sort mode, then we can start getting immediate output
+ // from the tool by just filtering as we go, rather than processing
+ // everything up front so that we can sort it. This makes the tool more
+ // responsive. So only precompute the filtered/sorted set of classes if
+ // necessary due to the specified options.
+ std::vector<LayoutPtr> Filtered;
+ uint32_t Shown = All;
+ if (Precompute) {
+ Filtered = filterAndSortClassDefs(Printer, *Classes, All);
+
+ Shown = Filtered.size();
+ }
+
+ Printer << ": (Showing " << Shown << " items";
+ if (Shown < All)
+ Printer << ", " << (All - Shown) << " filtered";
+ Printer << ")";
+ Printer.Indent();
+
+ // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
+ // the DIA enumerator and filter on the fly.
+ if (Precompute) {
+ for (auto &Class : Filtered)
+ dumpClassLayout(*Class);
+ } else {
+ while (auto Class = Classes->getNext()) {
+ if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
+ continue;
+
+ // No point duplicating a full class layout. Just print the modified
+ // declaration and continue.
+ if (Class->getUnmodifiedTypeId() != 0) {
+ Printer.NewLine();
+ printClassDecl(Printer, *Class);
+ continue;
+ }
+
+ auto Layout = std::make_unique<ClassLayout>(std::move(Class));
+ if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
+ continue;
+
+ dumpClassLayout(*Layout);
+ }
+ }
+
+ Printer.Unindent();
+ }
+ }
+}
+
+void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ assert(opts::pretty::Enums);
+
+ EnumDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper BD(Printer);
+ BD.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ printClassDecl(Printer, Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ assert(opts::pretty::Typedefs);
+
+ TypedefDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ auto ElementType = Symbol.getElementType();
+
+ ElementType->dump(*this);
+ Printer << "[";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getCount();
+ Printer << "]";
+}
+
+void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
+}
+
+void TypeDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ std::unique_ptr<PDBSymbol> P = Symbol.getPointeeType();
+
+ if (auto *FS = dyn_cast<PDBSymbolTypeFunctionSig>(P.get())) {
+ FunctionDumper Dumper(Printer);
+ FunctionDumper::PointerType PT =
+ Symbol.isReference() ? FunctionDumper::PointerType::Reference
+ : FunctionDumper::PointerType::Pointer;
+ Dumper.start(*FS, nullptr, PT);
+ return;
+ }
+
+ if (auto *UDT = dyn_cast<PDBSymbolTypeUDT>(P.get())) {
+ printClassDecl(Printer, *UDT);
+ } else if (P) {
+ P->dump(*this);
+ }
+
+ if (auto Parent = Symbol.getClassParent()) {
+ auto UDT = llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Parent));
+ if (UDT)
+ Printer << " " << UDT->getName() << "::";
+ }
+
+ if (Symbol.isReference())
+ Printer << "&";
+ else if (Symbol.isRValueReference())
+ Printer << "&&";
+ else
+ Printer << "*";
+}
+
+void TypeDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {
+ Printer.format("<vtshape ({0} methods)>", Symbol.getCount());
+}
+
+void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
+ assert(opts::pretty::Classes);
+
+ if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get()
+ << Class.getClass().getUdtKind() << " ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+ } else {
+ ClassDefinitionDumper Dumper(Printer);
+ Dumper.start(Class);
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.h
new file mode 100644
index 0000000000..b6539d95bf
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypeDumper.h
@@ -0,0 +1,41 @@
+//===- PrettyTypeDumper.h - PDBSymDumper implementation for types *- C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+class LinePrinter;
+class ClassLayout;
+
+class TypeDumper : public PDBSymDumper {
+public:
+ TypeDumper(LinePrinter &P);
+
+ void start(const PDBSymbolExe &Exe);
+
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeVTableShape &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+ void dumpClassLayout(const ClassLayout &Class);
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
new file mode 100644
index 0000000000..ef73a8cdf9
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
@@ -0,0 +1,82 @@
+//===- PrettyTypedefDumper.cpp - PDBSymDumper impl for typedefs -- * C++ *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyTypedefDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypeDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+ uint32_t TargetId = Symbol.getTypeId();
+ if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
+ TypeSymbol->dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+ << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ TypeDumper Dumper(Printer);
+ Dumper.dump(Symbol);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ auto PointeeType = Symbol.getPointeeType();
+ if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+ FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
+ if (Symbol.isReference())
+ Pointer = FunctionDumper::PointerType::Reference;
+ FunctionDumper NestedDumper(Printer);
+ NestedDumper.start(*FuncSig, nullptr, Pointer);
+ } else {
+ PointeeType->dump(*this);
+ Printer << ((Symbol.isReference()) ? "&" : "*");
+ }
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.h
new file mode 100644
index 0000000000..ad8b3f37dc
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyTypedefDumper.h
@@ -0,0 +1,38 @@
+//===- PrettyTypedefDumper.h - llvm-pdbutil typedef dumper ---*- C++ ----*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class TypedefDumper : public PDBSymDumper {
+public:
+ TypedefDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeTypedef &Symbol);
+
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.cpp
new file mode 100644
index 0000000000..6dd7cc384c
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.cpp
@@ -0,0 +1,225 @@
+//===- PrettyVariableDumper.cpp ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyVariableDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+VariableDumper::VariableDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) {
+ if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+ return;
+ if (Printer.IsSymbolExcluded(Var.getName()))
+ return;
+
+ auto VarType = Var.getType();
+
+ uint64_t Length = VarType->getRawSymbol().getLength();
+
+ switch (auto LocType = Var.getLocationType()) {
+ case PDB_LocType::Static:
+ Printer.NewLine();
+ Printer << "data [";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << format_hex(Var.getVirtualAddress(), 10);
+ Printer << ", sizeof=" << Length << "] ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ break;
+ case PDB_LocType::Constant:
+ if (isa<PDBSymbolTypeEnum>(*VarType))
+ break;
+ Printer.NewLine();
+ Printer << "data [sizeof=" << Length << "] ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ Printer << " = ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
+ break;
+ case PDB_LocType::ThisRel:
+ Printer.NewLine();
+ Printer << "data ";
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Offset + Var.getOffset(), 4)
+ << " [sizeof=" << Length << "] ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ break;
+ case PDB_LocType::BitField:
+ Printer.NewLine();
+ Printer << "data ";
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Offset + Var.getOffset(), 4)
+ << " [sizeof=" << Length << "] ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ Printer << " : ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
+ break;
+ default:
+ Printer.NewLine();
+ Printer << "data [sizeof=" << Length << "] ";
+ Printer << "unknown(" << LocType << ") ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
+ break;
+ }
+}
+
+void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) {
+ Printer.NewLine();
+ Printer << "vbptr ";
+
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] ";
+}
+
+void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) {
+ Printer.NewLine();
+ Printer << "vfptr ";
+ auto VTableType = cast<PDBSymbolTypePointer>(Var.getType());
+ uint32_t PointerSize = VTableType->getLength();
+
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Offset + Var.getOffset(), 4)
+ << " [sizeof=" << PointerSize << "] ";
+}
+
+void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ auto ElementType = Symbol.getElementType();
+ assert(ElementType);
+ if (!ElementType)
+ return;
+ ElementType->dump(*this);
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) {
+ auto ElementType = Symbol.getElementType();
+ assert(ElementType);
+ if (!ElementType)
+ return;
+ Printer << '[' << Symbol.getCount() << ']';
+ ElementType->dumpRight(*this);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+ auto ReturnType = Symbol.getReturnType();
+ ReturnType->dump(*this);
+ Printer << " ";
+
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+
+ if (ClassParent) {
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << ClassParent->getName();
+ Printer << "::";
+ }
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {
+ Printer << "(";
+ if (auto Arguments = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = Arguments->getNext()) {
+ Arg->dump(*this);
+ if (++Index < Arguments->getChildCount())
+ Printer << ", ";
+ }
+ }
+ Printer << ")";
+
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
+}
+
+void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ auto PointeeType = Symbol.getPointeeType();
+ if (!PointeeType)
+ return;
+ PointeeType->dump(*this);
+ if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+ // A hack to get the calling convention in the right spot.
+ Printer << " (";
+ PDB_CallingConv CC = FuncSig->getCallingConvention();
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+ } else if (isa<PDBSymbolTypeArray>(PointeeType)) {
+ Printer << " (";
+ }
+ Printer << (Symbol.isReference() ? "&" : "*");
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile ";
+
+ if (Symbol.getRawSymbol().isRestrictedType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict ";
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) {
+ auto PointeeType = Symbol.getPointeeType();
+ assert(PointeeType);
+ if (!PointeeType)
+ return;
+ if (isa<PDBSymbolTypeFunctionSig>(PointeeType) ||
+ isa<PDBSymbolTypeArray>(PointeeType)) {
+ Printer << ")";
+ }
+ PointeeType->dumpRight(*this);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
+ StringRef Name) {
+ Type.dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
+ Type.dumpRight(*this);
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.h b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.h
new file mode 100644
index 0000000000..65cf5cd2cf
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/PrettyVariableDumper.h
@@ -0,0 +1,49 @@
+//===- PrettyVariableDumper.h - PDBSymDumper variable dumper ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class StringRef;
+
+namespace pdb {
+
+class LinePrinter;
+
+class VariableDumper : public PDBSymDumper {
+public:
+ VariableDumper(LinePrinter &P);
+
+ void start(const PDBSymbolData &Var, uint32_t Offset = 0);
+ void start(const PDBSymbolTypeVTable &Var, uint32_t Offset = 0);
+ void startVbptr(uint32_t Offset, uint32_t Size);
+
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+ void dumpRight(const PDBSymbolTypeArray &Symbol) override;
+ void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dumpRight(const PDBSymbolTypePointer &Symbol) override;
+
+private:
+ void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name);
+
+ LinePrinter &Printer;
+};
+}
+}
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.cpp
new file mode 100644
index 0000000000..d0d0a9fbe9
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.cpp
@@ -0,0 +1,194 @@
+//===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "StreamUtil.h"
+#include "FormatUtil.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+std::string StreamInfo::getLongName() const {
+ if (Purpose == StreamPurpose::NamedStream)
+ return formatv("Named Stream \"{0}\"", Name).str();
+ if (Purpose == StreamPurpose::ModuleStream)
+ return formatv("Module \"{0}\"", Name).str();
+ return Name;
+}
+
+StreamInfo StreamInfo::createStream(StreamPurpose Purpose, StringRef Name,
+ uint32_t StreamIndex) {
+ StreamInfo Result;
+ Result.Name = std::string(Name);
+ Result.StreamIndex = StreamIndex;
+ Result.Purpose = Purpose;
+ return Result;
+}
+
+StreamInfo StreamInfo::createModuleStream(StringRef Module,
+ uint32_t StreamIndex, uint32_t Modi) {
+ StreamInfo Result;
+ Result.Name = std::string(Module);
+ Result.StreamIndex = StreamIndex;
+ Result.ModuleIndex = Modi;
+ Result.Purpose = StreamPurpose::ModuleStream;
+ return Result;
+}
+
+static inline StreamInfo stream(StreamPurpose Purpose, StringRef Label,
+ uint32_t Idx) {
+ return StreamInfo::createStream(Purpose, Label, Idx);
+}
+
+static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
+ uint32_t Modi) {
+ return StreamInfo::createModuleStream(Label, StreamIdx, Modi);
+}
+
+struct IndexedModuleDescriptor {
+ uint32_t Modi;
+ DbiModuleDescriptor Descriptor;
+};
+
+void llvm::pdb::discoverStreamPurposes(PDBFile &File,
+ SmallVectorImpl<StreamInfo> &Streams) {
+ // It's OK if we fail to load some of these streams, we still attempt to print
+ // what we can.
+ auto Dbi = File.getPDBDbiStream();
+ auto Tpi = File.getPDBTpiStream();
+ auto Ipi = File.getPDBIpiStream();
+ auto Info = File.getPDBInfoStream();
+
+ uint32_t StreamCount = File.getNumStreams();
+ DenseMap<uint16_t, IndexedModuleDescriptor> ModStreams;
+ DenseMap<uint16_t, std::string> NamedStreams;
+
+ if (Dbi) {
+ const DbiModuleList &Modules = Dbi->modules();
+ for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
+ IndexedModuleDescriptor IMD;
+ IMD.Modi = I;
+ IMD.Descriptor = Modules.getModuleDescriptor(I);
+ uint16_t SN = IMD.Descriptor.getModuleStreamIndex();
+ if (SN != kInvalidStreamIndex)
+ ModStreams[SN] = IMD;
+ }
+ }
+ if (Info) {
+ for (auto &NSE : Info->named_streams()) {
+ if (NSE.second != kInvalidStreamIndex)
+ NamedStreams[NSE.second] = std::string(NSE.first());
+ }
+ }
+
+ Streams.resize(StreamCount);
+ for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ if (StreamIdx == OldMSFDirectory)
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Old MSF Directory", StreamIdx);
+ else if (StreamIdx == StreamPDB)
+ Streams[StreamIdx] = stream(StreamPurpose::PDB, "PDB Stream", StreamIdx);
+ else if (StreamIdx == StreamDBI)
+ Streams[StreamIdx] = stream(StreamPurpose::DBI, "DBI Stream", StreamIdx);
+ else if (StreamIdx == StreamTPI)
+ Streams[StreamIdx] = stream(StreamPurpose::TPI, "TPI Stream", StreamIdx);
+ else if (StreamIdx == StreamIPI)
+ Streams[StreamIdx] = stream(StreamPurpose::IPI, "IPI Stream", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::GlobalHash, "Global Symbol Hash", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::PublicHash, "Public Symbol Hash", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Symbols, "Symbol Records", StreamIdx);
+ else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::TpiHash, "TPI Hash", StreamIdx);
+ else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "TPI Aux Hash", StreamIdx);
+ else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::IpiHash, "IPI Hash", StreamIdx);
+ else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "IPI Aux Hash", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Exception Data", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Fixup Data", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "FPO Data", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "New FPO Data", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Omap From Source Data", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Omap To Source Data", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "Pdata", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Section Header Data", StreamIdx);
+ else if (Dbi &&
+ StreamIdx ==
+ Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
+ Streams[StreamIdx] = stream(StreamPurpose::Other,
+ "Section Header Original Data", StreamIdx);
+ else if (Dbi &&
+ StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
+ Streams[StreamIdx] =
+ stream(StreamPurpose::Other, "Token Rid Data", StreamIdx);
+ else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "Xdata", StreamIdx);
+ else {
+ auto ModIter = ModStreams.find(StreamIdx);
+ auto NSIter = NamedStreams.find(StreamIdx);
+ if (ModIter != ModStreams.end()) {
+ Streams[StreamIdx] =
+ moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
+ ModIter->second.Modi);
+ } else if (NSIter != NamedStreams.end()) {
+ Streams[StreamIdx] =
+ stream(StreamPurpose::NamedStream, NSIter->second, StreamIdx);
+ } else {
+ Streams[StreamIdx] = stream(StreamPurpose::Other, "???", StreamIdx);
+ }
+ }
+ }
+
+ // Consume errors from missing streams.
+ if (!Dbi)
+ consumeError(Dbi.takeError());
+ if (!Tpi)
+ consumeError(Tpi.takeError());
+ if (!Ipi)
+ consumeError(Ipi.takeError());
+ if (!Info)
+ consumeError(Info.takeError());
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.h b/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.h
new file mode 100644
index 0000000000..f810f7dc15
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/StreamUtil.h
@@ -0,0 +1,63 @@
+//===- Streamutil.h - PDB stream utilities ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+enum class StreamPurpose {
+ NamedStream,
+ ModuleStream,
+ Symbols,
+ PDB,
+ DBI,
+ TPI,
+ IPI,
+ GlobalHash,
+ PublicHash,
+ TpiHash,
+ IpiHash,
+ Other
+};
+
+struct StreamInfo {
+public:
+ StreamInfo() {}
+
+ uint32_t getModuleIndex() const { return *ModuleIndex; }
+ StreamPurpose getPurpose() const { return Purpose; }
+ StringRef getShortName() const { return Name; }
+ uint32_t getStreamIndex() const { return StreamIndex; }
+ std::string getLongName() const;
+
+ static StreamInfo createStream(StreamPurpose Purpose, StringRef Name,
+ uint32_t StreamIndex);
+ static StreamInfo createModuleStream(StringRef Module, uint32_t StreamIndex,
+ uint32_t Modi);
+
+private:
+ StreamPurpose Purpose;
+ uint32_t StreamIndex;
+ std::string Name;
+ Optional<uint32_t> ModuleIndex;
+};
+
+void discoverStreamPurposes(PDBFile &File,
+ SmallVectorImpl<StreamInfo> &Streams);
+}
+}
+
+#endif
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.cpp
new file mode 100644
index 0000000000..f184f02e01
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.cpp
@@ -0,0 +1,160 @@
+//===- TypeReferenceTracker.cpp ------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeReferenceTracker.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+using namespace llvm::codeview;
+
+// LazyRandomTypeCollection doesn't appear to expose the number of records, so
+// just iterate up front to find out.
+static uint32_t getNumRecordsInCollection(LazyRandomTypeCollection &Types) {
+ uint32_t NumTypes = 0;
+ for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI))
+ ++NumTypes;
+ return NumTypes;
+}
+
+TypeReferenceTracker::TypeReferenceTracker(InputFile &File)
+ : File(File), Types(File.types()),
+ Ids(File.isPdb() ? &File.ids() : nullptr) {
+ NumTypeRecords = getNumRecordsInCollection(Types);
+ TypeReferenced.resize(NumTypeRecords, false);
+
+ // If this is a PDB, ids are stored separately, so make a separate bit vector.
+ if (Ids) {
+ NumIdRecords = getNumRecordsInCollection(*Ids);
+ IdReferenced.resize(NumIdRecords, false);
+ }
+
+ // Get the TpiStream pointer for forward decl resolution if this is a pdb.
+ // Build the hash map to enable resolving forward decls.
+ if (File.isPdb()) {
+ Tpi = &cantFail(File.pdb().getPDBTpiStream());
+ Tpi->buildHashMap();
+ }
+}
+
+void TypeReferenceTracker::mark() {
+ // Walk type roots:
+ // - globals
+ // - modi symbols
+ // - LF_UDT_MOD_SRC_LINE? VC always links these in.
+ for (SymbolGroup SG : File.symbol_groups()) {
+ if (File.isObj()) {
+ for (const auto &SS : SG.getDebugSubsections()) {
+ // FIXME: Are there other type-referencing subsections? Inlinees?
+ // Probably for IDs.
+ if (SS.kind() != DebugSubsectionKind::Symbols)
+ continue;
+
+ CVSymbolArray Symbols;
+ BinaryStreamReader Reader(SS.getRecordData());
+ cantFail(Reader.readArray(Symbols, Reader.getLength()));
+ for (const CVSymbol &S : Symbols)
+ addTypeRefsFromSymbol(S);
+ }
+ } else if (SG.hasDebugStream()) {
+ for (const CVSymbol &S : SG.getPdbModuleStream().getSymbolArray())
+ addTypeRefsFromSymbol(S);
+ }
+ }
+
+ // Walk globals and mark types referenced from globals.
+ if (File.isPdb() && File.pdb().hasPDBGlobalsStream()) {
+ SymbolStream &SymStream = cantFail(File.pdb().getPDBSymbolStream());
+ GlobalsStream &GS = cantFail(File.pdb().getPDBGlobalsStream());
+ for (uint32_t PubSymOff : GS.getGlobalsTable()) {
+ CVSymbol Sym = SymStream.readRecord(PubSymOff);
+ addTypeRefsFromSymbol(Sym);
+ }
+ }
+
+ // FIXME: Should we walk Ids?
+}
+
+void TypeReferenceTracker::addOneTypeRef(TiRefKind RefKind, TypeIndex RefTI) {
+ // If it's simple or already seen, no need to add to work list.
+ BitVector &TypeOrIdReferenced =
+ (Ids && RefKind == TiRefKind::IndexRef) ? IdReferenced : TypeReferenced;
+ if (RefTI.isSimple() || TypeOrIdReferenced.test(RefTI.toArrayIndex()))
+ return;
+
+ // Otherwise, mark it seen and add it to the work list.
+ TypeOrIdReferenced.set(RefTI.toArrayIndex());
+ RefWorklist.push_back({RefKind, RefTI});
+}
+
+void TypeReferenceTracker::addTypeRefsFromSymbol(const CVSymbol &Sym) {
+ SmallVector<TiReference, 4> DepList;
+ // FIXME: Check for failure.
+ discoverTypeIndicesInSymbol(Sym, DepList);
+ addReferencedTypes(Sym.content(), DepList);
+ markReferencedTypes();
+}
+
+void TypeReferenceTracker::addReferencedTypes(ArrayRef<uint8_t> RecData,
+ ArrayRef<TiReference> DepList) {
+ for (const auto &Ref : DepList) {
+ // FIXME: Report OOB slice instead of truncating.
+ ArrayRef<uint8_t> ByteSlice =
+ RecData.drop_front(Ref.Offset).take_front(4 * Ref.Count);
+ ArrayRef<TypeIndex> TIs(
+ reinterpret_cast<const TypeIndex *>(ByteSlice.data()),
+ ByteSlice.size() / 4);
+
+ // If this is a PDB and this is an item reference, track it in the IPI
+ // bitvector. Otherwise, it's a type ref, or there is only one stream.
+ for (TypeIndex RefTI : TIs)
+ addOneTypeRef(Ref.Kind, RefTI);
+ }
+}
+
+void TypeReferenceTracker::markReferencedTypes() {
+ while (!RefWorklist.empty()) {
+ TiRefKind RefKind;
+ TypeIndex RefTI;
+ std::tie(RefKind, RefTI) = RefWorklist.pop_back_val();
+ Optional<CVType> Rec = (Ids && RefKind == TiRefKind::IndexRef)
+ ? Ids->tryGetType(RefTI)
+ : Types.tryGetType(RefTI);
+ if (!Rec)
+ continue; // FIXME: Report a reference to a non-existant type.
+
+ SmallVector<TiReference, 4> DepList;
+ // FIXME: Check for failure.
+ discoverTypeIndices(*Rec, DepList);
+ addReferencedTypes(Rec->content(), DepList);
+
+ // If this is a tag kind and this is a PDB input, mark the complete type as
+ // referenced.
+ // FIXME: This limitation makes this feature somewhat useless on object file
+ // inputs.
+ if (Tpi) {
+ switch (Rec->kind()) {
+ default:
+ break;
+ case LF_CLASS:
+ case LF_INTERFACE:
+ case LF_STRUCTURE:
+ case LF_UNION:
+ case LF_ENUM:
+ addOneTypeRef(TiRefKind::TypeRef,
+ cantFail(Tpi->findFullDeclForForwardRef(RefTI)));
+ break;
+ }
+ }
+ }
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.h b/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.h
new file mode 100644
index 0000000000..8861731ab6
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/TypeReferenceTracker.h
@@ -0,0 +1,69 @@
+//===- TypeReferenceTracker.h --------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
+
+#include "InputFile.h"
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+
+class TpiStream;
+
+/// Maintains bitvector to track whether a type was referenced by a symbol
+/// record.
+class TypeReferenceTracker {
+public:
+ TypeReferenceTracker(InputFile &File);
+
+ // Do the work of marking referenced types.
+ void mark();
+
+ // Return true if a symbol record transitively references this type.
+ bool isTypeReferenced(codeview::TypeIndex TI) {
+ return TI.toArrayIndex() <= NumTypeRecords &&
+ TypeReferenced.test(TI.toArrayIndex());
+ }
+
+private:
+ void addTypeRefsFromSymbol(const codeview::CVSymbol &Sym);
+
+ // Mark types on this list as referenced.
+ void addReferencedTypes(ArrayRef<uint8_t> RecData,
+ ArrayRef<codeview::TiReference> Refs);
+
+ // Consume all types on the worklist.
+ void markReferencedTypes();
+
+ void addOneTypeRef(codeview::TiRefKind RefKind, codeview::TypeIndex RefTI);
+
+ InputFile &File;
+ codeview::LazyRandomTypeCollection &Types;
+ codeview::LazyRandomTypeCollection *Ids = nullptr;
+ TpiStream *Tpi = nullptr;
+ BitVector TypeReferenced;
+ BitVector IdReferenced;
+ SmallVector<std::pair<codeview::TiRefKind, codeview::TypeIndex>, 10>
+ RefWorklist;
+ uint32_t NumTypeRecords = 0;
+ uint32_t NumIdRecords = 0;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.cpp
new file mode 100644
index 0000000000..80b76657fa
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.cpp
@@ -0,0 +1,370 @@
+//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "YAMLOutputStyle.h"
+
+#include "PdbYaml.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.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/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static bool checkModuleSubsection(opts::ModuleSubsection MS) {
+ return any_of(opts::pdb2yaml::DumpModuleSubsections,
+ [=](opts::ModuleSubsection M) {
+ return M == MS || M == opts::ModuleSubsection::All;
+ });
+}
+
+YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
+ : File(File), Out(outs()), Obj(File.getAllocator()) {
+ Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal);
+}
+
+Error YAMLOutputStyle::dump() {
+ if (opts::pdb2yaml::StreamDirectory)
+ opts::pdb2yaml::StreamMetadata = true;
+
+ if (auto EC = dumpFileHeaders())
+ return EC;
+
+ if (auto EC = dumpStreamMetadata())
+ return EC;
+
+ if (auto EC = dumpStreamDirectory())
+ return EC;
+
+ if (auto EC = dumpStringTable())
+ return EC;
+
+ if (auto EC = dumpPDBStream())
+ return EC;
+
+ if (auto EC = dumpDbiStream())
+ return EC;
+
+ if (auto EC = dumpTpiStream())
+ return EC;
+
+ if (auto EC = dumpIpiStream())
+ return EC;
+
+ if (auto EC = dumpPublics())
+ return EC;
+
+ flush();
+ return Error::success();
+}
+
+
+Error YAMLOutputStyle::dumpFileHeaders() {
+ if (opts::pdb2yaml::NoFileHeaders)
+ return Error::success();
+
+ yaml::MSFHeaders Headers;
+ Obj.Headers.emplace();
+ Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
+ Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
+ Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();
+ auto Blocks = File.getDirectoryBlockArray();
+ Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());
+ Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks();
+ Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes();
+ Obj.Headers->NumStreams =
+ opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0;
+ Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock();
+ Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1();
+ Obj.Headers->FileSize = File.getFileSize();
+
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStringTable() {
+ bool RequiresStringTable = opts::pdb2yaml::DumpModuleFiles ||
+ !opts::pdb2yaml::DumpModuleSubsections.empty();
+ bool RequestedStringTable = opts::pdb2yaml::StringTable;
+ if (!RequiresStringTable && !RequestedStringTable)
+ return Error::success();
+
+ auto ExpectedST = File.getStringTable();
+ if (!ExpectedST)
+ return ExpectedST.takeError();
+
+ Obj.StringTable.emplace();
+ const auto &ST = ExpectedST.get();
+ for (auto ID : ST.name_ids()) {
+ auto S = ST.getStringForID(ID);
+ if (!S)
+ return S.takeError();
+ if (S->empty())
+ continue;
+ Obj.StringTable->push_back(*S);
+ }
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStreamMetadata() {
+ if (!opts::pdb2yaml::StreamMetadata)
+ return Error::success();
+
+ Obj.StreamSizes.emplace();
+ Obj.StreamSizes->assign(File.getStreamSizes().begin(),
+ File.getStreamSizes().end());
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStreamDirectory() {
+ if (!opts::pdb2yaml::StreamDirectory)
+ return Error::success();
+
+ auto StreamMap = File.getStreamMap();
+ Obj.StreamMap.emplace();
+ for (auto &Stream : StreamMap) {
+ pdb::yaml::StreamBlockList BlockList;
+ BlockList.Blocks.assign(Stream.begin(), Stream.end());
+ Obj.StreamMap->push_back(BlockList);
+ }
+
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpPDBStream() {
+ if (!opts::pdb2yaml::PdbStream)
+ return Error::success();
+
+ auto IS = File.getPDBInfoStream();
+ if (!IS)
+ return IS.takeError();
+
+ auto &InfoS = IS.get();
+ Obj.PdbStream.emplace();
+ Obj.PdbStream->Age = InfoS.getAge();
+ Obj.PdbStream->Guid = InfoS.getGuid();
+ Obj.PdbStream->Signature = InfoS.getSignature();
+ Obj.PdbStream->Version = InfoS.getVersion();
+ Obj.PdbStream->Features = InfoS.getFeatureSignatures();
+
+ return Error::success();
+}
+
+static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) {
+ switch (K) {
+ case DebugSubsectionKind::CrossScopeExports:
+ return opts::ModuleSubsection::CrossScopeExports;
+ case DebugSubsectionKind::CrossScopeImports:
+ return opts::ModuleSubsection::CrossScopeImports;
+ case DebugSubsectionKind::FileChecksums:
+ return opts::ModuleSubsection::FileChecksums;
+ case DebugSubsectionKind::InlineeLines:
+ return opts::ModuleSubsection::InlineeLines;
+ case DebugSubsectionKind::Lines:
+ return opts::ModuleSubsection::Lines;
+ case DebugSubsectionKind::Symbols:
+ return opts::ModuleSubsection::Symbols;
+ case DebugSubsectionKind::StringTable:
+ return opts::ModuleSubsection::StringTable;
+ case DebugSubsectionKind::FrameData:
+ return opts::ModuleSubsection::FrameData;
+ default:
+ return opts::ModuleSubsection::Unknown;
+ }
+ llvm_unreachable("Unreachable!");
+}
+
+Error YAMLOutputStyle::dumpDbiStream() {
+ if (!opts::pdb2yaml::DbiStream)
+ return Error::success();
+
+ if (!File.hasPDBDbiStream())
+ return Error::success();
+
+ auto DbiS = File.getPDBDbiStream();
+ if (!DbiS)
+ return DbiS.takeError();
+
+ auto &DS = DbiS.get();
+ Obj.DbiStream.emplace();
+ Obj.DbiStream->Age = DS.getAge();
+ Obj.DbiStream->BuildNumber = DS.getBuildNumber();
+ Obj.DbiStream->Flags = DS.getFlags();
+ Obj.DbiStream->MachineType = DS.getMachineType();
+ Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
+ Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
+ Obj.DbiStream->VerHeader = DS.getDbiVersion();
+ if (opts::pdb2yaml::DumpModules) {
+ const auto &Modules = DS.modules();
+ for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
+ DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);
+
+ Obj.DbiStream->ModInfos.emplace_back();
+ yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back();
+
+ DMI.Mod = MI.getModuleName();
+ DMI.Obj = MI.getObjFileName();
+ if (opts::pdb2yaml::DumpModuleFiles) {
+ auto Files = Modules.source_files(I);
+ DMI.SourceFiles.assign(Files.begin(), Files.end());
+ }
+
+ uint16_t ModiStream = MI.getModuleStreamIndex();
+ if (ModiStream == kInvalidStreamIndex)
+ continue;
+
+ auto ModStreamData = File.createIndexedStream(ModiStream);
+ pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData));
+ if (auto EC = ModS.reload())
+ return EC;
+
+ auto ExpectedST = File.getStringTable();
+ if (!ExpectedST)
+ return ExpectedST.takeError();
+ if (!opts::pdb2yaml::DumpModuleSubsections.empty() &&
+ ModS.hasDebugSubsections()) {
+ auto ExpectedChecksums = ModS.findChecksumsSubsection();
+ if (!ExpectedChecksums)
+ return ExpectedChecksums.takeError();
+
+ StringsAndChecksumsRef SC(ExpectedST->getStringTable(),
+ *ExpectedChecksums);
+
+ for (const auto &SS : ModS.subsections()) {
+ opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());
+ if (!checkModuleSubsection(OptionKind))
+ continue;
+
+ auto Converted =
+ CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(SC, SS);
+ if (!Converted)
+ return Converted.takeError();
+ DMI.Subsections.push_back(*Converted);
+ }
+ }
+
+ if (opts::pdb2yaml::DumpModuleSyms) {
+ DMI.Modi.emplace();
+
+ DMI.Modi->Signature = ModS.signature();
+ bool HadError = false;
+ for (auto &Sym : ModS.symbols(&HadError)) {
+ auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
+ if (!ES)
+ return ES.takeError();
+
+ DMI.Modi->Symbols.push_back(*ES);
+ }
+ }
+ }
+ }
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpTpiStream() {
+ if (!opts::pdb2yaml::TpiStream)
+ return Error::success();
+
+ auto TpiS = File.getPDBTpiStream();
+ if (!TpiS)
+ return TpiS.takeError();
+
+ auto &TS = TpiS.get();
+ Obj.TpiStream.emplace();
+ Obj.TpiStream->Version = TS.getTpiVersion();
+ for (auto &Record : TS.types(nullptr)) {
+ auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
+ if (!ExpectedRecord)
+ return ExpectedRecord.takeError();
+ Obj.TpiStream->Records.push_back(*ExpectedRecord);
+ }
+
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpIpiStream() {
+ if (!opts::pdb2yaml::IpiStream)
+ return Error::success();
+
+ auto InfoS = File.getPDBInfoStream();
+ if (!InfoS)
+ return InfoS.takeError();
+ if (!InfoS->containsIdStream())
+ return Error::success();
+
+ auto IpiS = File.getPDBIpiStream();
+ if (!IpiS)
+ return IpiS.takeError();
+
+ auto &IS = IpiS.get();
+ Obj.IpiStream.emplace();
+ Obj.IpiStream->Version = IS.getTpiVersion();
+ for (auto &Record : IS.types(nullptr)) {
+ auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
+ if (!ExpectedRecord)
+ return ExpectedRecord.takeError();
+
+ Obj.IpiStream->Records.push_back(*ExpectedRecord);
+ }
+
+ return Error::success();
+}
+
+Error YAMLOutputStyle::dumpPublics() {
+ if (!opts::pdb2yaml::PublicsStream)
+ return Error::success();
+
+ Obj.PublicsStream.emplace();
+ auto ExpectedPublics = File.getPDBPublicsStream();
+ if (!ExpectedPublics) {
+ llvm::consumeError(ExpectedPublics.takeError());
+ return Error::success();
+ }
+
+ PublicsStream &Publics = *ExpectedPublics;
+ const GSIHashTable &PublicsTable = Publics.getPublicsTable();
+
+ auto ExpectedSyms = File.getPDBSymbolStream();
+ if (!ExpectedSyms) {
+ llvm::consumeError(ExpectedSyms.takeError());
+ return Error::success();
+ }
+
+ BinaryStreamRef SymStream =
+ ExpectedSyms->getSymbolArray().getUnderlyingStream();
+ for (uint32_t PubSymOff : PublicsTable) {
+ Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
+ if (!Sym)
+ return Sym.takeError();
+ auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(*Sym);
+ if (!ES)
+ return ES.takeError();
+
+ Obj.PublicsStream->PubSyms.push_back(*ES);
+ }
+
+ return Error::success();
+}
+
+void YAMLOutputStyle::flush() {
+ Out << Obj;
+ outs().flush();
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.h b/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.h
new file mode 100644
index 0000000000..7a50af1abe
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/YAMLOutputStyle.h
@@ -0,0 +1,49 @@
+//===- YAMLOutputStyle.h -------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H
+
+#include "OutputStyle.h"
+#include "PdbYaml.h"
+
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace pdb {
+class ModuleDebugStreamRef;
+
+class YAMLOutputStyle : public OutputStyle {
+public:
+ YAMLOutputStyle(PDBFile &File);
+
+ Error dump() override;
+
+private:
+ Error dumpStringTable();
+ Error dumpFileHeaders();
+ Error dumpStreamMetadata();
+ Error dumpStreamDirectory();
+ Error dumpPDBStream();
+ Error dumpDbiStream();
+ Error dumpTpiStream();
+ Error dumpIpiStream();
+ Error dumpPublics();
+
+ void flush();
+
+ PDBFile &File;
+ llvm::yaml::Output Out;
+
+ yaml::PdbObject Obj;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.cpp b/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.cpp
new file mode 100644
index 0000000000..19f4880ab5
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -0,0 +1,1575 @@
+//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Dumps debug information present in PDB files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-pdbutil.h"
+
+#include "BytesOutputStyle.h"
+#include "DumpOutputStyle.h"
+#include "ExplainOutputStyle.h"
+#include "InputFile.h"
+#include "LinePrinter.h"
+#include "OutputStyle.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyCompilandDumper.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyExternalSymbolDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypeDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "PrettyVariableDumper.h"
+#include "YAMLOutputStyle.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/COM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+namespace opts {
+
+cl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info");
+cl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file");
+
+cl::SubCommand DiaDumpSubcommand("diadump",
+ "Dump debug information using a DIA-like API");
+
+cl::SubCommand
+ PrettySubcommand("pretty",
+ "Dump semantic information about types and symbols");
+
+cl::SubCommand
+ YamlToPdbSubcommand("yaml2pdb",
+ "Generate a PDB file from a YAML description");
+cl::SubCommand
+ PdbToYamlSubcommand("pdb2yaml",
+ "Generate a detailed YAML description of a PDB File");
+
+cl::SubCommand MergeSubcommand("merge",
+ "Merge multiple PDBs into a single PDB");
+
+cl::SubCommand ExplainSubcommand("explain",
+ "Explain the meaning of a file offset");
+
+cl::SubCommand ExportSubcommand("export",
+ "Write binary data from a stream to a file");
+
+cl::OptionCategory TypeCategory("Symbol Type Options");
+cl::OptionCategory FilterCategory("Filtering and Sorting Options");
+cl::OptionCategory OtherOptions("Other Options");
+
+cl::ValuesClass ChunkValues = cl::values(
+ clEnumValN(ModuleSubsection::CrossScopeExports, "cme",
+ "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
+ clEnumValN(ModuleSubsection::CrossScopeImports, "cmi",
+ "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
+ clEnumValN(ModuleSubsection::FileChecksums, "fc",
+ "File checksums (DEBUG_S_CHECKSUMS subsection)"),
+ clEnumValN(ModuleSubsection::InlineeLines, "ilines",
+ "Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
+ clEnumValN(ModuleSubsection::Lines, "lines",
+ "Lines (DEBUG_S_LINES subsection)"),
+ clEnumValN(ModuleSubsection::StringTable, "strings",
+ "String Table (DEBUG_S_STRINGTABLE subsection) (not "
+ "typically present in PDB file)"),
+ clEnumValN(ModuleSubsection::FrameData, "frames",
+ "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
+ clEnumValN(ModuleSubsection::Symbols, "symbols",
+ "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
+ "present in PDB file)"),
+ clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas",
+ "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"),
+ clEnumValN(ModuleSubsection::Unknown, "unknown",
+ "Any subsection not covered by another option"),
+ clEnumValN(ModuleSubsection::All, "all", "All known subsections"));
+
+namespace diadump {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(DiaDumpSubcommand));
+
+cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
+ cl::sub(DiaDumpSubcommand));
+
+static cl::opt<bool>
+ ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> NoSymIndexIds(
+ "no-ids",
+ cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"),
+ cl::sub(DiaDumpSubcommand));
+
+static cl::opt<bool>
+ Recurse("recurse",
+ cl::desc("When dumping a SymIndexId, dump the full details of the "
+ "corresponding record"),
+ cl::sub(DiaDumpSubcommand));
+
+static cl::opt<bool> Enums("enums", cl::desc("Dump enum types"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> Compilands("compilands",
+ cl::desc("Dump compiland information"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> Funcsigs("funcsigs",
+ cl::desc("Dump function signature information"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"),
+ cl::sub(DiaDumpSubcommand));
+static cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"),
+ cl::sub(DiaDumpSubcommand));
+} // namespace diadump
+
+namespace pretty {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(PrettySubcommand));
+
+cl::opt<bool> InjectedSources("injected-sources",
+ cl::desc("Display injected sources"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<bool> ShowInjectedSourceContent(
+ "injected-source-content",
+ cl::desc("When displaying an injected source, display the file content"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+
+cl::list<std::string> WithName(
+ "with-name",
+ cl::desc("Display any symbol or type with the specified exact name"),
+ cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
+
+cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Symbols("module-syms",
+ cl::desc("Display symbols for each compiland"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::list<SymLevel> SymTypes(
+ "sym-types", cl::desc("Type of symbols to dump (default all)"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore,
+ cl::values(
+ clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),
+ clEnumValN(SymLevel::Data, "data", "Display data symbols"),
+ clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),
+ clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));
+
+cl::opt<bool>
+ Types("types",
+ cl::desc("Display all types (implies -classes, -enums, -typedefs)"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Classes("classes", cl::desc("Display class types"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Enums("enums", cl::desc("Display enum types"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Arrays("arrays", cl::desc("Display arrays"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<SymbolSortMode> SymbolOrder(
+ "symbol-order", cl::desc("symbol sort order"),
+ cl::init(SymbolSortMode::None),
+ cl::values(clEnumValN(SymbolSortMode::None, "none",
+ "Undefined / no particular sort order"),
+ clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),
+ clEnumValN(SymbolSortMode::Size, "size",
+ "Sort symbols by size")),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<ClassSortMode> ClassOrder(
+ "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
+ cl::values(
+ clEnumValN(ClassSortMode::None, "none",
+ "Undefined / no particular sort order"),
+ clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
+ clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
+ clEnumValN(ClassSortMode::Padding, "padding",
+ "Sort classes by amount of padding"),
+ clEnumValN(ClassSortMode::PaddingPct, "padding-pct",
+ "Sort classes by percentage of space consumed by padding"),
+ clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",
+ "Sort classes by amount of immediate padding"),
+ clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",
+ "Sort classes by percentage of space consumed by immediate "
+ "padding")),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<ClassDefinitionFormat> ClassFormat(
+ "class-definitions", cl::desc("Class definition format"),
+ cl::init(ClassDefinitionFormat::All),
+ cl::values(
+ clEnumValN(ClassDefinitionFormat::All, "all",
+ "Display all class members including data, constants, "
+ "typedefs, functions, etc"),
+ clEnumValN(ClassDefinitionFormat::Layout, "layout",
+ "Only display members that contribute to class size."),
+ clEnumValN(ClassDefinitionFormat::None, "none",
+ "Don't display class definitions")),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> ClassRecursionDepth(
+ "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),
+ cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
+ cl::sub(PrettySubcommand));
+cl::opt<bool>
+ All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<uint64_t> LoadAddress(
+ "load-address",
+ cl::desc("Assume the module is loaded at the specified address"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<cl::boolOrDefault>
+ ColorOutput("color-output",
+ cl::desc("Override use of color (default = isatty)"),
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeTypes(
+ "exclude-types", cl::desc("Exclude types by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeSymbols(
+ "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeCompilands(
+ "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::list<std::string> IncludeTypes(
+ "include-types",
+ cl::desc("Include only types which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeSymbols(
+ "include-symbols",
+ cl::desc("Include only symbols which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeCompilands(
+ "include-compilands",
+ cl::desc("Include only compilands those which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> SizeThreshold(
+ "min-type-size", cl::desc("Displays only those types which are greater "
+ "than or equal to the specified size."),
+ cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> PaddingThreshold(
+ "min-class-padding", cl::desc("Displays only those classes which have at "
+ "least the specified amount of padding."),
+ cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> ImmediatePaddingThreshold(
+ "min-class-padding-imm",
+ cl::desc("Displays only those classes which have at least the specified "
+ "amount of immediate padding, ignoring padding internal to bases "
+ "and aggregates."),
+ cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> ExcludeCompilerGenerated(
+ "no-compiler-generated",
+ cl::desc("Don't show compiler generated types and symbols"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<bool>
+ ExcludeSystemLibraries("no-system-libs",
+ cl::desc("Don't show symbols from system libraries"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> NoEnumDefs("no-enum-definitions",
+ cl::desc("Don't display full enum definitions"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+}
+
+cl::OptionCategory FileOptions("Module & File Options");
+
+namespace bytes {
+cl::OptionCategory MsfBytes("MSF File Options");
+cl::OptionCategory DbiBytes("Dbi Stream Options");
+cl::OptionCategory PdbBytes("PDB Stream Options");
+cl::OptionCategory Types("Type Options");
+cl::OptionCategory ModuleCategory("Module Options");
+
+llvm::Optional<NumberRange> DumpBlockRange;
+llvm::Optional<NumberRange> DumpByteRange;
+
+cl::opt<std::string> DumpBlockRangeOpt(
+ "block-range", cl::value_desc("start[-end]"),
+ cl::desc("Dump binary data from specified range of blocks."),
+ cl::sub(BytesSubcommand), cl::cat(MsfBytes));
+
+cl::opt<std::string>
+ DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
+ cl::desc("Dump binary data from specified range of bytes"),
+ cl::sub(BytesSubcommand), cl::cat(MsfBytes));
+
+cl::list<std::string>
+ DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
+ cl::desc("Dump binary data from specified streams. Format "
+ "is SN[:Start][@Size]"),
+ cl::sub(BytesSubcommand), cl::cat(MsfBytes));
+
+cl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),
+ cl::sub(BytesSubcommand), cl::cat(PdbBytes));
+cl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"),
+ cl::sub(BytesSubcommand), cl::cat(MsfBytes));
+
+cl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+cl::opt<bool> SectionMap("sm", cl::desc("Dump section map"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+cl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+cl::opt<bool> FileInfo("files", cl::desc("Dump source file info"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+cl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+cl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),
+ cl::sub(BytesSubcommand), cl::cat(DbiBytes));
+
+cl::list<uint32_t>
+ TypeIndex("type",
+ cl::desc("Dump the type record with the given type index"),
+ cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
+ cl::cat(TypeCategory));
+cl::list<uint32_t>
+ IdIndex("id", cl::desc("Dump the id record with the given type index"),
+ cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
+ cl::cat(TypeCategory));
+
+cl::opt<uint32_t> ModuleIndex(
+ "mod",
+ cl::desc(
+ "Limit options in the Modules category to the specified module index"),
+ cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
+cl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"),
+ cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
+cl::opt<bool> ModuleC11("c11-chunks", cl::Hidden,
+ cl::desc("Dump C11 CodeView debug chunks"),
+ cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
+cl::opt<bool> ModuleC13("chunks",
+ cl::desc("Dump C13 CodeView debug chunk subsection"),
+ cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
+cl::opt<bool> SplitChunks(
+ "split-chunks",
+ cl::desc(
+ "When dumping debug chunks, show a different section for each chunk"),
+ cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(BytesSubcommand));
+
+} // namespace bytes
+
+namespace dump {
+
+cl::OptionCategory MsfOptions("MSF Container Options");
+cl::OptionCategory TypeOptions("Type Record Options");
+cl::OptionCategory SymbolOptions("Symbol Options");
+cl::OptionCategory MiscOptions("Miscellaneous Options");
+
+// MSF OPTIONS
+cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpStreams("streams",
+ cl::desc("dump summary of the PDB streams"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpStreamBlocks(
+ "stream-blocks",
+ cl::desc("Add block information to the output of -streams"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSymbolStats(
+ "sym-stats",
+ cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpTypeStats(
+ "type-stats",
+ cl::desc("Dump a detailed breakdown of type usage/size"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpIDStats(
+ "id-stats",
+ cl::desc("Dump a detailed breakdown of IPI types usage/size"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpUdtStats(
+ "udt-stats",
+ cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
+ cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+
+// TYPE OPTIONS
+cl::opt<bool> DumpTypes("types",
+ cl::desc("dump CodeView type records from TPI stream"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpTypeData(
+ "type-data",
+ cl::desc("dump CodeView type record raw bytes from TPI stream"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+ DumpTypeRefStats("type-ref-stats",
+ cl::desc("dump statistics on the number and size of types "
+ "transitively referenced by symbol records"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpTypeExtras("type-extras",
+ cl::desc("dump type hashes and index offsets"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DontResolveForwardRefs(
+ "dont-resolve-forward-refs",
+ cl::desc("When dumping type records for classes, unions, enums, and "
+ "structs, don't try to resolve forward references"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::list<uint32_t> DumpTypeIndex(
+ "type-index", cl::ZeroOrMore, cl::CommaSeparated,
+ cl::desc("only dump types with the specified hexadecimal type index"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpIds("ids",
+ cl::desc("dump CodeView type records from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+ DumpIdData("id-data",
+ cl::desc("dump CodeView type record raw bytes from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpIdExtras("id-extras",
+ cl::desc("dump id hashes and index offsets"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+cl::list<uint32_t> DumpIdIndex(
+ "id-index", cl::ZeroOrMore, cl::CommaSeparated,
+ cl::desc("only dump ids with the specified hexadecimal type index"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpTypeDependents(
+ "dependents",
+ cl::desc("In conjunection with -type-index and -id-index, dumps the entire "
+ "dependency graph for the specified index instead of "
+ "just the single record with the specified index"),
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));
+
+// SYMBOL OPTIONS
+cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::list<std::string> DumpGlobalNames(
+ "global-name",
+ cl::desc(
+ "With -globals, only dump globals whose name matches the given value"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand), cl::ZeroOrMore);
+cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpPublicExtras("public-extras",
+ cl::desc("dump Publics hashes and address maps"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+ DumpGSIRecords("gsi-records",
+ cl::desc("dump public / global common record stream"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool>
+ DumpSymRecordBytes("sym-data",
+ cl::desc("dump CodeView symbol record raw bytes"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+
+// MODULE & FILE OPTIONS
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpModuleFiles(
+ "files",
+ cl::desc("Dump the source files that contribute to each module's."),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpLines(
+ "l",
+ cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpInlineeLines(
+ "il",
+ cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpXmi(
+ "xmi",
+ cl::desc(
+ "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpXme(
+ "xme",
+ cl::desc(
+ "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<uint32_t> DumpModi("modi", cl::Optional,
+ cl::desc("For all options that iterate over "
+ "modules, limit to the specified module"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> JustMyCode("jmc", cl::Optional,
+ cl::desc("For all options that iterate over modules, "
+ "ignore modules from system libraries"),
+ cl::cat(FileOptions), cl::sub(DumpSubcommand));
+
+// MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpNamedStreams("named-streams",
+ cl::desc("dump PDB named stream table"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpStringTableDetails("string-table-details",
+ cl::desc("dump PDB String Table Details"),
+ cl::cat(MiscOptions),
+ cl::sub(DumpSubcommand));
+
+cl::opt<bool> DumpSectionContribs("section-contribs",
+ cl::desc("dump section contributions"),
+ cl::cat(MiscOptions),
+ cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
+ cl::desc("Dump image section headers"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+
+cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(DumpSubcommand));
+}
+
+namespace yaml2pdb {
+cl::opt<std::string>
+ YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+ cl::sub(YamlToPdbSubcommand));
+
+cl::opt<std::string> InputFilename(cl::Positional,
+ cl::desc("<input YAML file>"), cl::Required,
+ cl::sub(YamlToPdbSubcommand));
+}
+
+namespace pdb2yaml {
+cl::opt<bool> All("all",
+ cl::desc("Dump everything we know how to dump."),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> NoFileHeaders("no-file-headers",
+ cl::desc("Do not dump MSF file headers"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> Minimal("minimal",
+ cl::desc("Don't write fields with default values"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> StreamMetadata(
+ "stream-metadata",
+ cl::desc("Dump the number of streams and each stream's size"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> StreamDirectory(
+ "stream-directory",
+ cl::desc("Dump each stream's block map (implies -stream-metadata)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> PdbStream("pdb-stream",
+ cl::desc("Dump the PDB Stream (Stream 1)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> DbiStream("dbi-stream",
+ cl::desc("Dump the DBI Stream Headers (Stream 2)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> TpiStream("tpi-stream",
+ cl::desc("Dump the TPI Stream (Stream 3)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> IpiStream("ipi-stream",
+ cl::desc("Dump the IPI Stream (Stream 5)"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> PublicsStream("publics-stream",
+ cl::desc("Dump the Publics Stream"),
+ cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+// MODULE & FILE OPTIONS
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+ cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
+ cl::cat(FileOptions),
+ cl::sub(PdbToYamlSubcommand));
+cl::list<ModuleSubsection> DumpModuleSubsections(
+ "subsections", cl::ZeroOrMore, cl::CommaSeparated,
+ cl::desc("dump subsections from each module's debug stream"), ChunkValues,
+ cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
+ cl::cat(FileOptions),
+ cl::sub(PdbToYamlSubcommand));
+
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(PdbToYamlSubcommand));
+} // namespace pdb2yaml
+
+namespace merge {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(MergeSubcommand));
+cl::opt<std::string>
+ PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+ cl::sub(MergeSubcommand));
+}
+
+namespace explain {
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(ExplainSubcommand));
+
+cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
+ cl::sub(ExplainSubcommand), cl::OneOrMore);
+
+cl::opt<InputFileType> InputType(
+ "input-type", cl::desc("Specify how to interpret the input file"),
+ cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
+ cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
+ "Treat input as a PDB file (default)"),
+ clEnumValN(InputFileType::PDBStream, "pdb-stream",
+ "Treat input as raw contents of PDB stream"),
+ clEnumValN(InputFileType::DBIStream, "dbi-stream",
+ "Treat input as raw contents of DBI stream"),
+ clEnumValN(InputFileType::Names, "names-stream",
+ "Treat input as raw contents of /names named stream"),
+ clEnumValN(InputFileType::ModuleStream, "mod-stream",
+ "Treat input as raw contents of a module stream")));
+} // namespace explain
+
+namespace exportstream {
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(ExportSubcommand));
+cl::opt<std::string> OutputFile("out",
+ cl::desc("The file to write the stream to"),
+ cl::Required, cl::sub(ExportSubcommand));
+cl::opt<std::string>
+ Stream("stream", cl::Required,
+ cl::desc("The index or name of the stream whose contents to export"),
+ cl::sub(ExportSubcommand));
+cl::opt<bool> ForceName("name",
+ cl::desc("Force the interpretation of -stream as a "
+ "string, even if it is a valid integer"),
+ cl::sub(ExportSubcommand), cl::Optional,
+ cl::init(false));
+} // namespace exportstream
+}
+
+static ExitOnError ExitOnErr;
+
+static void yamlToPdb(StringRef Path) {
+ BumpPtrAllocator Allocator;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
+ MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+ /*RequiresNullTerminator=*/false);
+
+ if (ErrorOrBuffer.getError()) {
+ ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));
+ }
+
+ std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
+
+ llvm::yaml::Input In(Buffer->getBuffer());
+ pdb::yaml::PdbObject YamlObj(Allocator);
+ In >> YamlObj;
+
+ PDBFileBuilder Builder(Allocator);
+
+ uint32_t BlockSize = 4096;
+ if (YamlObj.Headers.hasValue())
+ BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
+ ExitOnErr(Builder.initialize(BlockSize));
+ // Add each of the reserved streams. We ignore stream metadata in the
+ // yaml, because we will reconstruct our own view of the streams. For
+ // example, the YAML may say that there were 20 streams in the original
+ // PDB, but maybe we only dump a subset of those 20 streams, so we will
+ // have fewer, and the ones we do have may end up with different indices
+ // than the ones in the original PDB. So we just start with a clean slate.
+ for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
+ ExitOnErr(Builder.getMsfBuilder().addStream(0));
+
+ StringsAndChecksums Strings;
+ Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
+
+ if (YamlObj.StringTable.hasValue()) {
+ for (auto S : *YamlObj.StringTable)
+ Strings.strings()->insert(S);
+ }
+
+ pdb::yaml::PdbInfoStream DefaultInfoStream;
+ pdb::yaml::PdbDbiStream DefaultDbiStream;
+ pdb::yaml::PdbTpiStream DefaultTpiStream;
+ pdb::yaml::PdbTpiStream DefaultIpiStream;
+
+ const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream);
+
+ auto &InfoBuilder = Builder.getInfoBuilder();
+ InfoBuilder.setAge(Info.Age);
+ InfoBuilder.setGuid(Info.Guid);
+ InfoBuilder.setSignature(Info.Signature);
+ InfoBuilder.setVersion(Info.Version);
+ for (auto F : Info.Features)
+ InfoBuilder.addFeature(F);
+
+ const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
+ auto &DbiBuilder = Builder.getDbiBuilder();
+ DbiBuilder.setAge(Dbi.Age);
+ DbiBuilder.setBuildNumber(Dbi.BuildNumber);
+ DbiBuilder.setFlags(Dbi.Flags);
+ DbiBuilder.setMachineType(Dbi.MachineType);
+ DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
+ DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
+ DbiBuilder.setVersionHeader(Dbi.VerHeader);
+ for (const auto &MI : Dbi.ModInfos) {
+ auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
+ ModiBuilder.setObjFileName(MI.Obj);
+
+ for (auto S : MI.SourceFiles)
+ ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
+ if (MI.Modi.hasValue()) {
+ const auto &ModiStream = *MI.Modi;
+ for (auto Symbol : ModiStream.Symbols) {
+ ModiBuilder.addSymbol(
+ Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
+ }
+ }
+
+ // Each module has its own checksum subsection, so scan for it every time.
+ Strings.setChecksums(nullptr);
+ CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
+
+ auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
+ Allocator, MI.Subsections, Strings));
+ for (auto &SS : CodeViewSubsections) {
+ ModiBuilder.addDebugSubsection(SS);
+ }
+ }
+
+ auto &TpiBuilder = Builder.getTpiBuilder();
+ const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
+ TpiBuilder.setVersionHeader(Tpi.Version);
+ AppendingTypeTableBuilder TS(Allocator);
+ for (const auto &R : Tpi.Records) {
+ CVType Type = R.toCodeViewRecord(TS);
+ TpiBuilder.addTypeRecord(Type.RecordData, None);
+ }
+
+ const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream);
+ auto &IpiBuilder = Builder.getIpiBuilder();
+ IpiBuilder.setVersionHeader(Ipi.Version);
+ for (const auto &R : Ipi.Records) {
+ CVType Type = R.toCodeViewRecord(TS);
+ IpiBuilder.addTypeRecord(Type.RecordData, None);
+ }
+
+ Builder.getStringTableBuilder().setStrings(*Strings.strings());
+
+ codeview::GUID IgnoredOutGuid;
+ ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
+}
+
+static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
+ ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
+
+ NativeSession *NS = static_cast<NativeSession *>(Session.get());
+ return NS->getPDBFile();
+}
+
+static void pdb2Yaml(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+ auto &File = loadPDB(Path, Session);
+
+ auto O = std::make_unique<YAMLOutputStyle>(File);
+ O = std::make_unique<YAMLOutputStyle>(File);
+
+ ExitOnErr(O->dump());
+}
+
+static void dumpRaw(StringRef Path) {
+ InputFile IF = ExitOnErr(InputFile::open(Path));
+
+ auto O = std::make_unique<DumpOutputStyle>(IF);
+ ExitOnErr(O->dump());
+}
+
+static void dumpBytes(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+ auto &File = loadPDB(Path, Session);
+
+ auto O = std::make_unique<BytesOutputStyle>(File);
+
+ ExitOnErr(O->dump());
+}
+
+bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
+ if (SymTypes.empty())
+ return true;
+ if (llvm::is_contained(SymTypes, Search))
+ return true;
+ if (llvm::is_contained(SymTypes, SymLevel::All))
+ return true;
+ return false;
+}
+
+uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
+ auto SymbolType = Symbol.getType();
+ const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
+
+ return RawType.getLength();
+}
+
+bool opts::pretty::compareFunctionSymbols(
+ const std::unique_ptr<PDBSymbolFunc> &F1,
+ const std::unique_ptr<PDBSymbolFunc> &F2) {
+ assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
+
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
+ return F1->getName() < F2->getName();
+
+ // Note that we intentionally sort in descending order on length, since
+ // long functions are more interesting than short functions.
+ return F1->getLength() > F2->getLength();
+}
+
+bool opts::pretty::compareDataSymbols(
+ const std::unique_ptr<PDBSymbolData> &F1,
+ const std::unique_ptr<PDBSymbolData> &F2) {
+ assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
+
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
+ return F1->getName() < F2->getName();
+
+ // Note that we intentionally sort in descending order on length, since
+ // large types are more interesting than short ones.
+ return getTypeLength(*F1) > getTypeLength(*F2);
+}
+
+static std::string stringOr(std::string Str, std::string IfEmpty) {
+ return (Str.empty()) ? IfEmpty : Str;
+}
+
+static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
+ auto Sources = Session.getInjectedSources();
+ if (!Sources || !Sources->getChildCount()) {
+ Printer.printLine("There are no injected sources.");
+ return;
+ }
+
+ while (auto IS = Sources->getNext()) {
+ Printer.NewLine();
+ std::string File = stringOr(IS->getFileName(), "<null>");
+ uint64_t Size = IS->getCodeByteSize();
+ std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
+ std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
+ uint32_t CRC = IS->getCrc32();
+
+ WithColor(Printer, PDB_ColorItem::Path).get() << File;
+ Printer << " (";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
+ Printer << " bytes): ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
+ Printer << "=";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
+ Printer << ", ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
+ Printer << "=";
+ dumpPDBSourceCompression(
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get(),
+ IS->getCompression());
+
+ if (!opts::pretty::ShowInjectedSourceContent)
+ continue;
+
+ // Set the indent level to 0 when printing file content.
+ int Indent = Printer.getIndentLevel();
+ Printer.Unindent(Indent);
+
+ if (IS->getCompression() == PDB_SourceCompression::None)
+ Printer.printLine(IS->getCode());
+ else
+ Printer.formatBinary("Compressed data",
+ arrayRefFromStringRef(IS->getCode()),
+ /*StartOffset=*/0);
+
+ // Re-indent back to the original level.
+ Printer.Indent(Indent);
+ }
+}
+
+template <typename OuterT, typename ChildT>
+void diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,
+ PdbSymbolIdField Recurse) {
+ OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);
+ if (!ConcreteOuter)
+ return;
+
+ auto Children = ConcreteOuter->template findAllChildren<ChildT>();
+ while (auto Child = Children->getNext()) {
+ outs() << " {";
+ Child->defaultDump(outs(), 4, Ids, Recurse);
+ outs() << "\n }\n";
+ }
+}
+
+static void dumpDia(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+
+ const auto ReaderType =
+ opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
+ ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
+
+ auto GlobalScope = Session->getGlobalScope();
+
+ std::vector<PDB_SymType> SymTypes;
+
+ if (opts::diadump::Compilands)
+ SymTypes.push_back(PDB_SymType::Compiland);
+ if (opts::diadump::Enums)
+ SymTypes.push_back(PDB_SymType::Enum);
+ if (opts::diadump::Pointers)
+ SymTypes.push_back(PDB_SymType::PointerType);
+ if (opts::diadump::UDTs)
+ SymTypes.push_back(PDB_SymType::UDT);
+ if (opts::diadump::Funcsigs)
+ SymTypes.push_back(PDB_SymType::FunctionSig);
+ if (opts::diadump::Arrays)
+ SymTypes.push_back(PDB_SymType::ArrayType);
+ if (opts::diadump::VTShapes)
+ SymTypes.push_back(PDB_SymType::VTableShape);
+ if (opts::diadump::Typedefs)
+ SymTypes.push_back(PDB_SymType::Typedef);
+ PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
+ : PdbSymbolIdField::All;
+
+ PdbSymbolIdField Recurse = PdbSymbolIdField::None;
+ if (opts::diadump::Recurse)
+ Recurse = PdbSymbolIdField::All;
+ if (!opts::diadump::ShowClassHierarchy)
+ Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);
+
+ for (PDB_SymType ST : SymTypes) {
+ auto Children = GlobalScope->findAllChildren(ST);
+ while (auto Child = Children->getNext()) {
+ outs() << "{";
+ Child->defaultDump(outs(), 2, Ids, Recurse);
+
+ diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);
+ outs() << "\n}\n";
+ }
+ }
+}
+
+static void dumpPretty(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+
+ const auto ReaderType =
+ opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
+ ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
+
+ if (opts::pretty::LoadAddress)
+ Session->setLoadAddress(opts::pretty::LoadAddress);
+
+ auto &Stream = outs();
+ const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
+ ? Stream.has_colors()
+ : opts::pretty::ColorOutput == cl::BOU_TRUE;
+ LinePrinter Printer(2, UseColor, Stream);
+
+ auto GlobalScope(Session->getGlobalScope());
+ if (!GlobalScope)
+ return;
+ std::string FileName(GlobalScope->getSymbolsFileName());
+
+ WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
+ WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
+ Printer.Indent();
+ uint64_t FileSize = 0;
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
+ if (!sys::fs::file_size(FileName, FileSize)) {
+ Printer << ": " << FileSize << " bytes";
+ } else {
+ Printer << ": (Unable to obtain file size)";
+ }
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
+ Printer << ": " << GlobalScope->getGuid();
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
+ Printer << ": " << GlobalScope->getAge();
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
+ Printer << ": ";
+ if (GlobalScope->hasCTypes())
+ outs() << "HasCTypes ";
+ if (GlobalScope->hasPrivateSymbols())
+ outs() << "HasPrivateSymbols ";
+ Printer.Unindent();
+
+ if (!opts::pretty::WithName.empty()) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---SYMBOLS & TYPES BY NAME---";
+
+ for (StringRef Name : opts::pretty::WithName) {
+ auto Symbols = GlobalScope->findChildren(
+ PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
+ if (!Symbols || Symbols->getChildCount() == 0) {
+ Printer.formatLine("[not found] - {0}", Name);
+ continue;
+ }
+ Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
+ Name);
+
+ AutoIndent Indent(Printer);
+ Printer.NewLine();
+
+ while (auto Symbol = Symbols->getNext()) {
+ switch (Symbol->getSymTag()) {
+ case PDB_SymType::Typedef: {
+ TypedefDumper TD(Printer);
+ std::unique_ptr<PDBSymbolTypeTypedef> T =
+ llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
+ TD.start(*T);
+ break;
+ }
+ case PDB_SymType::Enum: {
+ EnumDumper ED(Printer);
+ std::unique_ptr<PDBSymbolTypeEnum> E =
+ llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
+ ED.start(*E);
+ break;
+ }
+ case PDB_SymType::UDT: {
+ ClassDefinitionDumper CD(Printer);
+ std::unique_ptr<PDBSymbolTypeUDT> C =
+ llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
+ CD.start(*C);
+ break;
+ }
+ case PDB_SymType::BaseClass:
+ case PDB_SymType::Friend: {
+ TypeDumper TD(Printer);
+ Symbol->dump(TD);
+ break;
+ }
+ case PDB_SymType::Function: {
+ FunctionDumper FD(Printer);
+ std::unique_ptr<PDBSymbolFunc> F =
+ llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
+ FD.start(*F, FunctionDumper::PointerType::None);
+ break;
+ }
+ case PDB_SymType::Data: {
+ VariableDumper VD(Printer);
+ std::unique_ptr<PDBSymbolData> D =
+ llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
+ VD.start(*D);
+ break;
+ }
+ case PDB_SymType::PublicSymbol: {
+ ExternalSymbolDumper ED(Printer);
+ std::unique_ptr<PDBSymbolPublicSymbol> PS =
+ llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
+ ED.dump(*PS);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected symbol tag!");
+ }
+ }
+ }
+ llvm::outs().flush();
+ }
+
+ if (opts::pretty::Compilands) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---COMPILANDS---";
+ auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+
+ if (Compilands) {
+ Printer.Indent();
+ CompilandDumper Dumper(Printer);
+ CompilandDumpFlags options = CompilandDumper::Flags::None;
+ if (opts::pretty::Lines)
+ options = options | CompilandDumper::Flags::Lines;
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, options);
+ Printer.Unindent();
+ }
+ }
+
+ if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
+ opts::pretty::Funcsigs || opts::pretty::Pointers ||
+ opts::pretty::Arrays || opts::pretty::VTShapes) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
+ Printer.Indent();
+ TypeDumper Dumper(Printer);
+ Dumper.start(*GlobalScope);
+ Printer.Unindent();
+ }
+
+ if (opts::pretty::Symbols) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
+ if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
+ Printer.Indent();
+ CompilandDumper Dumper(Printer);
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, true);
+ Printer.Unindent();
+ }
+ }
+
+ if (opts::pretty::Globals) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
+ Printer.Indent();
+ if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
+ if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
+ FunctionDumper Dumper(Printer);
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+ while (auto Function = Functions->getNext()) {
+ Printer.NewLine();
+ Dumper.start(*Function, FunctionDumper::PointerType::None);
+ }
+ } else {
+ std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
+ while (auto Func = Functions->getNext())
+ Funcs.push_back(std::move(Func));
+ llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);
+ for (const auto &Func : Funcs) {
+ Printer.NewLine();
+ Dumper.start(*Func, FunctionDumper::PointerType::None);
+ }
+ }
+ }
+ }
+ if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
+ if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
+ VariableDumper Dumper(Printer);
+ if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+ while (auto Var = Vars->getNext())
+ Dumper.start(*Var);
+ } else {
+ std::vector<std::unique_ptr<PDBSymbolData>> Datas;
+ while (auto Var = Vars->getNext())
+ Datas.push_back(std::move(Var));
+ llvm::sort(Datas, opts::pretty::compareDataSymbols);
+ for (const auto &Var : Datas)
+ Dumper.start(*Var);
+ }
+ }
+ }
+ if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
+ if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
+ CompilandDumper Dumper(Printer);
+ while (auto Thunk = Thunks->getNext())
+ Dumper.dump(*Thunk);
+ }
+ }
+ Printer.Unindent();
+ }
+ if (opts::pretty::Externals) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
+ Printer.Indent();
+ ExternalSymbolDumper Dumper(Printer);
+ Dumper.start(*GlobalScope);
+ }
+ if (opts::pretty::Lines) {
+ Printer.NewLine();
+ }
+ if (opts::pretty::InjectedSources) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---INJECTED SOURCES---";
+ AutoIndent Indent1(Printer);
+ dumpInjectedSources(Printer, *Session);
+ }
+
+ Printer.NewLine();
+ outs().flush();
+}
+
+static void mergePdbs() {
+ BumpPtrAllocator Allocator;
+ MergingTypeTableBuilder MergedTpi(Allocator);
+ MergingTypeTableBuilder MergedIpi(Allocator);
+
+ // Create a Tpi and Ipi type table with all types from all input files.
+ for (const auto &Path : opts::merge::InputFilenames) {
+ std::unique_ptr<IPDBSession> Session;
+ auto &File = loadPDB(Path, Session);
+ SmallVector<TypeIndex, 128> TypeMap;
+ SmallVector<TypeIndex, 128> IdMap;
+ if (File.hasPDBTpiStream()) {
+ auto &Tpi = ExitOnErr(File.getPDBTpiStream());
+ ExitOnErr(
+ codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));
+ }
+ if (File.hasPDBIpiStream()) {
+ auto &Ipi = ExitOnErr(File.getPDBIpiStream());
+ ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
+ Ipi.typeArray()));
+ }
+ }
+
+ // Then write the PDB.
+ PDBFileBuilder Builder(Allocator);
+ ExitOnErr(Builder.initialize(4096));
+ // Add each of the reserved streams. We might not put any data in them,
+ // but at least they have to be present.
+ for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
+ ExitOnErr(Builder.getMsfBuilder().addStream(0));
+
+ auto &DestTpi = Builder.getTpiBuilder();
+ auto &DestIpi = Builder.getIpiBuilder();
+ MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
+ DestTpi.addTypeRecord(Type.RecordData, None);
+ });
+ MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
+ DestIpi.addTypeRecord(Type.RecordData, None);
+ });
+ Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
+
+ SmallString<64> OutFile(opts::merge::PdbOutputFile);
+ if (OutFile.empty()) {
+ OutFile = opts::merge::InputFilenames[0];
+ llvm::sys::path::replace_extension(OutFile, "merged.pdb");
+ }
+
+ codeview::GUID IgnoredOutGuid;
+ ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
+}
+
+static void explain() {
+ std::unique_ptr<IPDBSession> Session;
+ InputFile IF =
+ ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
+
+ for (uint64_t Off : opts::explain::Offsets) {
+ auto O = std::make_unique<ExplainOutputStyle>(IF, Off);
+
+ ExitOnErr(O->dump());
+ }
+}
+
+static void exportStream() {
+ std::unique_ptr<IPDBSession> Session;
+ PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
+
+ std::unique_ptr<MappedBlockStream> SourceStream;
+ uint32_t Index = 0;
+ bool Success = false;
+ std::string OutFileName = opts::exportstream::OutputFile;
+
+ if (!opts::exportstream::ForceName) {
+ // First try to parse it as an integer, if it fails fall back to treating it
+ // as a named stream.
+ if (to_integer(opts::exportstream::Stream, Index)) {
+ if (Index >= File.getNumStreams()) {
+ errs() << "Error: " << Index << " is not a valid stream index.\n";
+ exit(1);
+ }
+ Success = true;
+ outs() << "Dumping contents of stream index " << Index << " to file "
+ << OutFileName << ".\n";
+ }
+ }
+
+ if (!Success) {
+ InfoStream &IS = cantFail(File.getPDBInfoStream());
+ Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
+ outs() << "Dumping contents of stream '" << opts::exportstream::Stream
+ << "' (index " << Index << ") to file " << OutFileName << ".\n";
+ }
+
+ SourceStream = File.createIndexedStream(Index);
+ auto OutFile = ExitOnErr(
+ FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
+ FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
+ BinaryStreamWriter Writer(DestStream);
+ ExitOnErr(Writer.writeStreamRef(*SourceStream));
+ ExitOnErr(DestStream.commit());
+}
+
+static bool parseRange(StringRef Str,
+ Optional<opts::bytes::NumberRange> &Parsed) {
+ if (Str.empty())
+ return true;
+
+ llvm::Regex R("^([^-]+)(-([^-]+))?$");
+ llvm::SmallVector<llvm::StringRef, 2> Matches;
+ if (!R.match(Str, &Matches))
+ return false;
+
+ Parsed.emplace();
+ if (!to_integer(Matches[1], Parsed->Min))
+ return false;
+
+ if (!Matches[3].empty()) {
+ Parsed->Max.emplace();
+ if (!to_integer(Matches[3], *Parsed->Max))
+ return false;
+ }
+ return true;
+}
+
+static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
+ // If this list contains "All" plus some other stuff, remove the other stuff
+ // and just keep "All" in the list.
+ if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))
+ return;
+ Chunks.reset();
+ Chunks.push_back(opts::ModuleSubsection::All);
+}
+
+int main(int Argc, const char **Argv) {
+ InitLLVM X(Argc, Argv);
+ ExitOnErr.setBanner("llvm-pdbutil: ");
+
+ cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
+
+ if (opts::BytesSubcommand) {
+ if (!parseRange(opts::bytes::DumpBlockRangeOpt,
+ opts::bytes::DumpBlockRange)) {
+ errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
+ << "' invalid format.\n";
+ errs().flush();
+ exit(1);
+ }
+ if (!parseRange(opts::bytes::DumpByteRangeOpt,
+ opts::bytes::DumpByteRange)) {
+ errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
+ << "' invalid format.\n";
+ errs().flush();
+ exit(1);
+ }
+ }
+
+ if (opts::DumpSubcommand) {
+ if (opts::dump::RawAll) {
+ opts::dump::DumpGlobals = true;
+ opts::dump::DumpFpo = true;
+ opts::dump::DumpInlineeLines = true;
+ opts::dump::DumpIds = true;
+ opts::dump::DumpIdExtras = true;
+ opts::dump::DumpLines = true;
+ opts::dump::DumpModules = true;
+ opts::dump::DumpModuleFiles = true;
+ opts::dump::DumpPublics = true;
+ opts::dump::DumpSectionContribs = true;
+ opts::dump::DumpSectionHeaders = true;
+ opts::dump::DumpSectionMap = true;
+ opts::dump::DumpStreams = true;
+ opts::dump::DumpStreamBlocks = true;
+ opts::dump::DumpStringTable = true;
+ opts::dump::DumpStringTableDetails = true;
+ opts::dump::DumpSummary = true;
+ opts::dump::DumpSymbols = true;
+ opts::dump::DumpSymbolStats = true;
+ opts::dump::DumpTypes = true;
+ opts::dump::DumpTypeExtras = true;
+ opts::dump::DumpUdtStats = true;
+ opts::dump::DumpXme = true;
+ opts::dump::DumpXmi = true;
+ }
+ }
+ if (opts::PdbToYamlSubcommand) {
+ if (opts::pdb2yaml::All) {
+ opts::pdb2yaml::StreamMetadata = true;
+ opts::pdb2yaml::StreamDirectory = true;
+ opts::pdb2yaml::PdbStream = true;
+ opts::pdb2yaml::StringTable = true;
+ opts::pdb2yaml::DbiStream = true;
+ opts::pdb2yaml::TpiStream = true;
+ opts::pdb2yaml::IpiStream = true;
+ opts::pdb2yaml::PublicsStream = true;
+ opts::pdb2yaml::DumpModules = true;
+ opts::pdb2yaml::DumpModuleFiles = true;
+ opts::pdb2yaml::DumpModuleSyms = true;
+ opts::pdb2yaml::DumpModuleSubsections.push_back(
+ opts::ModuleSubsection::All);
+ }
+ simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);
+
+ if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
+ opts::pdb2yaml::DumpModules = true;
+
+ if (opts::pdb2yaml::DumpModules)
+ opts::pdb2yaml::DbiStream = true;
+ }
+
+ llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
+ if (opts::PdbToYamlSubcommand) {
+ pdb2Yaml(opts::pdb2yaml::InputFilename.front());
+ } else if (opts::YamlToPdbSubcommand) {
+ if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
+ SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
+ sys::path::replace_extension(OutputFilename, ".pdb");
+ opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename.str());
+ }
+ yamlToPdb(opts::yaml2pdb::InputFilename);
+ } else if (opts::DiaDumpSubcommand) {
+ llvm::for_each(opts::diadump::InputFilenames, dumpDia);
+ } else if (opts::PrettySubcommand) {
+ if (opts::pretty::Lines)
+ opts::pretty::Compilands = true;
+
+ if (opts::pretty::All) {
+ opts::pretty::Compilands = true;
+ opts::pretty::Symbols = true;
+ opts::pretty::Globals = true;
+ opts::pretty::Types = true;
+ opts::pretty::Externals = true;
+ opts::pretty::Lines = true;
+ }
+
+ if (opts::pretty::Types) {
+ opts::pretty::Classes = true;
+ opts::pretty::Typedefs = true;
+ opts::pretty::Enums = true;
+ opts::pretty::Pointers = true;
+ opts::pretty::Funcsigs = true;
+ }
+
+ // When adding filters for excluded compilands and types, we need to
+ // remember that these are regexes. So special characters such as * and \
+ // need to be escaped in the regex. In the case of a literal \, this means
+ // it needs to be escaped again in the C++. So matching a single \ in the
+ // input requires 4 \es in the C++.
+ if (opts::pretty::ExcludeCompilerGenerated) {
+ opts::pretty::ExcludeTypes.push_back("__vc_attributes");
+ opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
+ }
+ if (opts::pretty::ExcludeSystemLibraries) {
+ opts::pretty::ExcludeCompilands.push_back(
+ "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
+ opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
+ opts::pretty::ExcludeCompilands.push_back(
+ "d:\\\\th.obj.x86fre\\\\minkernel");
+ }
+ llvm::for_each(opts::pretty::InputFilenames, dumpPretty);
+ } else if (opts::DumpSubcommand) {
+ llvm::for_each(opts::dump::InputFilenames, dumpRaw);
+ } else if (opts::BytesSubcommand) {
+ llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
+ } else if (opts::MergeSubcommand) {
+ if (opts::merge::InputFilenames.size() < 2) {
+ errs() << "merge subcommand requires at least 2 input files.\n";
+ exit(1);
+ }
+ mergePdbs();
+ } else if (opts::ExplainSubcommand) {
+ explain();
+ } else if (opts::ExportSubcommand) {
+ exportStream();
+ }
+
+ outs().flush();
+ return 0;
+}
diff --git a/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.h b/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.h
new file mode 100644
index 0000000000..9fe92c2c9d
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -0,0 +1,220 @@
+//===- llvm-pdbutil.h ----------------------------------------- *- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <memory>
+#include <stdint.h>
+
+namespace llvm {
+namespace object {
+class COFFObjectFile;
+}
+namespace pdb {
+class PDBSymbolData;
+class PDBSymbolFunc;
+class PDBFile;
+uint32_t getTypeLength(const PDBSymbolData &Symbol);
+}
+typedef llvm::PointerUnion<object::COFFObjectFile *, pdb::PDBFile *>
+ PdbOrCoffObj;
+}
+
+namespace opts {
+
+enum class DumpLevel { None, Basic, Verbose };
+
+enum class ModuleSubsection {
+ Unknown,
+ Lines,
+ FileChecksums,
+ InlineeLines,
+ CrossScopeImports,
+ CrossScopeExports,
+ StringTable,
+ Symbols,
+ FrameData,
+ CoffSymbolRVAs,
+ All
+};
+
+namespace pretty {
+
+enum class ClassDefinitionFormat { None, Layout, All };
+enum class ClassSortMode {
+ None,
+ Name,
+ Size,
+ Padding,
+ PaddingPct,
+ PaddingImmediate,
+ PaddingPctImmediate
+};
+
+enum class SymbolSortMode { None, Name, Size };
+
+enum class SymLevel { Functions, Data, Thunks, All };
+
+bool shouldDumpSymLevel(SymLevel Level);
+bool compareFunctionSymbols(
+ const std::unique_ptr<llvm::pdb::PDBSymbolFunc> &F1,
+ const std::unique_ptr<llvm::pdb::PDBSymbolFunc> &F2);
+bool compareDataSymbols(const std::unique_ptr<llvm::pdb::PDBSymbolData> &F1,
+ const std::unique_ptr<llvm::pdb::PDBSymbolData> &F2);
+
+extern llvm::cl::list<std::string> WithName;
+
+extern llvm::cl::opt<bool> Compilands;
+extern llvm::cl::opt<bool> Symbols;
+extern llvm::cl::opt<bool> Globals;
+extern llvm::cl::opt<bool> Classes;
+extern llvm::cl::opt<bool> Enums;
+extern llvm::cl::opt<bool> Funcsigs;
+extern llvm::cl::opt<bool> Arrays;
+extern llvm::cl::opt<bool> Typedefs;
+extern llvm::cl::opt<bool> Pointers;
+extern llvm::cl::opt<bool> VTShapes;
+extern llvm::cl::opt<bool> All;
+extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
+
+extern llvm::cl::opt<bool> NoEnumDefs;
+extern llvm::cl::list<std::string> ExcludeTypes;
+extern llvm::cl::list<std::string> ExcludeSymbols;
+extern llvm::cl::list<std::string> ExcludeCompilands;
+extern llvm::cl::list<std::string> IncludeTypes;
+extern llvm::cl::list<std::string> IncludeSymbols;
+extern llvm::cl::list<std::string> IncludeCompilands;
+extern llvm::cl::opt<SymbolSortMode> SymbolOrder;
+extern llvm::cl::opt<ClassSortMode> ClassOrder;
+extern llvm::cl::opt<uint32_t> SizeThreshold;
+extern llvm::cl::opt<uint32_t> PaddingThreshold;
+extern llvm::cl::opt<uint32_t> ImmediatePaddingThreshold;
+extern llvm::cl::opt<ClassDefinitionFormat> ClassFormat;
+extern llvm::cl::opt<uint32_t> ClassRecursionDepth;
+}
+
+namespace bytes {
+struct NumberRange {
+ uint64_t Min;
+ llvm::Optional<uint64_t> Max;
+};
+
+extern llvm::Optional<NumberRange> DumpBlockRange;
+extern llvm::Optional<NumberRange> DumpByteRange;
+extern llvm::cl::list<std::string> DumpStreamData;
+extern llvm::cl::opt<bool> NameMap;
+extern llvm::cl::opt<bool> Fpm;
+
+extern llvm::cl::opt<bool> SectionContributions;
+extern llvm::cl::opt<bool> SectionMap;
+extern llvm::cl::opt<bool> ModuleInfos;
+extern llvm::cl::opt<bool> FileInfo;
+extern llvm::cl::opt<bool> TypeServerMap;
+extern llvm::cl::opt<bool> ECData;
+
+extern llvm::cl::list<uint32_t> TypeIndex;
+extern llvm::cl::list<uint32_t> IdIndex;
+
+extern llvm::cl::opt<uint32_t> ModuleIndex;
+extern llvm::cl::opt<bool> ModuleSyms;
+extern llvm::cl::opt<bool> ModuleC11;
+extern llvm::cl::opt<bool> ModuleC13;
+extern llvm::cl::opt<bool> SplitChunks;
+} // namespace bytes
+
+namespace dump {
+
+extern llvm::cl::opt<bool> DumpSummary;
+extern llvm::cl::opt<bool> DumpFpm;
+extern llvm::cl::opt<bool> DumpStreams;
+extern llvm::cl::opt<bool> DumpSymbolStats;
+extern llvm::cl::opt<bool> DumpTypeStats;
+extern llvm::cl::opt<bool> DumpIDStats;
+extern llvm::cl::opt<bool> DumpUdtStats;
+extern llvm::cl::opt<bool> DumpStreamBlocks;
+
+extern llvm::cl::opt<bool> DumpLines;
+extern llvm::cl::opt<bool> DumpInlineeLines;
+extern llvm::cl::opt<bool> DumpXmi;
+extern llvm::cl::opt<bool> DumpXme;
+extern llvm::cl::opt<bool> DumpNamedStreams;
+extern llvm::cl::opt<bool> DumpStringTable;
+extern llvm::cl::opt<bool> DumpStringTableDetails;
+extern llvm::cl::opt<bool> DumpTypes;
+extern llvm::cl::opt<bool> DumpTypeData;
+extern llvm::cl::opt<bool> DumpTypeExtras;
+extern llvm::cl::list<uint32_t> DumpTypeIndex;
+extern llvm::cl::opt<bool> DumpTypeDependents;
+extern llvm::cl::opt<bool> DumpTypeRefStats;
+extern llvm::cl::opt<bool> DumpSectionHeaders;
+
+extern llvm::cl::opt<bool> DumpIds;
+extern llvm::cl::opt<bool> DumpIdData;
+extern llvm::cl::opt<bool> DumpIdExtras;
+extern llvm::cl::list<uint32_t> DumpIdIndex;
+extern llvm::cl::opt<uint32_t> DumpModi;
+extern llvm::cl::opt<bool> JustMyCode;
+extern llvm::cl::opt<bool> DontResolveForwardRefs;
+extern llvm::cl::opt<bool> DumpSymbols;
+extern llvm::cl::opt<bool> DumpSymRecordBytes;
+extern llvm::cl::opt<bool> DumpGSIRecords;
+extern llvm::cl::opt<bool> DumpGlobals;
+extern llvm::cl::list<std::string> DumpGlobalNames;
+extern llvm::cl::opt<bool> DumpGlobalExtras;
+extern llvm::cl::opt<bool> DumpPublics;
+extern llvm::cl::opt<bool> DumpPublicExtras;
+extern llvm::cl::opt<bool> DumpSectionContribs;
+extern llvm::cl::opt<bool> DumpSectionMap;
+extern llvm::cl::opt<bool> DumpModules;
+extern llvm::cl::opt<bool> DumpModuleFiles;
+extern llvm::cl::opt<bool> DumpFpo;
+extern llvm::cl::opt<bool> RawAll;
+}
+
+namespace pdb2yaml {
+extern llvm::cl::opt<bool> All;
+extern llvm::cl::opt<bool> NoFileHeaders;
+extern llvm::cl::opt<bool> Minimal;
+extern llvm::cl::opt<bool> StreamMetadata;
+extern llvm::cl::opt<bool> StreamDirectory;
+extern llvm::cl::opt<bool> StringTable;
+extern llvm::cl::opt<bool> PdbStream;
+extern llvm::cl::opt<bool> DbiStream;
+extern llvm::cl::opt<bool> TpiStream;
+extern llvm::cl::opt<bool> IpiStream;
+extern llvm::cl::opt<bool> PublicsStream;
+extern llvm::cl::list<std::string> InputFilename;
+extern llvm::cl::opt<bool> DumpModules;
+extern llvm::cl::opt<bool> DumpModuleFiles;
+extern llvm::cl::list<ModuleSubsection> DumpModuleSubsections;
+extern llvm::cl::opt<bool> DumpModuleSyms;
+} // namespace pdb2yaml
+
+namespace explain {
+enum class InputFileType { PDBFile, PDBStream, DBIStream, Names, ModuleStream };
+
+extern llvm::cl::list<std::string> InputFilename;
+extern llvm::cl::list<uint64_t> Offsets;
+extern llvm::cl::opt<InputFileType> InputType;
+} // namespace explain
+
+namespace exportstream {
+extern llvm::cl::opt<std::string> OutputFile;
+extern llvm::cl::opt<std::string> Stream;
+extern llvm::cl::opt<bool> ForceName;
+} // namespace exportstream
+}
+
+#endif