aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-pdbdump/llvm-pdbdump.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /tools/llvm-pdbdump/llvm-pdbdump.cpp
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Diffstat (limited to 'tools/llvm-pdbdump/llvm-pdbdump.cpp')
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.cpp327
1 files changed, 241 insertions, 86 deletions
diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp
index d3495e524abc..06c2afc0bc78 100644
--- a/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -7,13 +7,14 @@
//
//===----------------------------------------------------------------------===//
//
-// Dumps debug information present in PDB files. This utility makes use of
-// the Microsoft Windows SDK, so will not compile or run on non-Windows
-// platforms.
+// Dumps debug information present in PDB files.
//
//===----------------------------------------------------------------------===//
#include "llvm-pdbdump.h"
+
+#include "Analyze.h"
+#include "Diff.h"
#include "LLVMOutputStyle.h"
#include "LinePrinter.h"
#include "OutputStyle.h"
@@ -29,29 +30,31 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.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/ModInfoBuilder.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/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.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/PDBSymbolThunk.h"
-#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
-#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
+#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -78,6 +81,9 @@ cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
cl::SubCommand
PrettySubcommand("pretty",
"Dump semantic information about types and symbols");
+
+cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files");
+
cl::SubCommand
YamlToPdbSubcommand("yaml2pdb",
"Generate a PDB file from a YAML description");
@@ -85,8 +91,12 @@ cl::SubCommand
PdbToYamlSubcommand("pdb2yaml",
"Generate a detailed YAML description of a PDB File");
+cl::SubCommand
+ AnalyzeSubcommand("analyze",
+ "Analyze various aspects of a PDB's structure");
+
cl::OptionCategory TypeCategory("Symbol Type Options");
-cl::OptionCategory FilterCategory("Filtering Options");
+cl::OptionCategory FilterCategory("Filtering and Sorting Options");
cl::OptionCategory OtherOptions("Other Options");
namespace pretty {
@@ -102,8 +112,41 @@ 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::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
- cl::sub(PrettySubcommand));
+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<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")),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<ClassDefinitionFormat> ClassFormat(
+ "class-definitions", cl::desc("Class definition format"),
+ cl::init(ClassDefinitionFormat::Standard),
+ cl::values(
+ clEnumValN(ClassDefinitionFormat::Standard, "all-members",
+ "Display all class members including data, constants, "
+ "typedefs, functions, etc"),
+ clEnumValN(ClassDefinitionFormat::Layout, "layout-members",
+ "Only display members that contribute to class size."),
+ clEnumValN(ClassDefinitionFormat::Graphical, "graphical",
+ "Display graphical representation of each class's layout."),
+ clEnumValN(ClassDefinitionFormat::None, "none",
+ "Don't display class definitions")),
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
cl::sub(PrettySubcommand));
cl::opt<bool>
@@ -114,6 +157,12 @@ 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));
@@ -136,6 +185,14 @@ 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<bool> ExcludeCompilerGenerated(
"no-compiler-generated",
@@ -145,14 +202,23 @@ 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> NoClassDefs("no-class-definitions",
- cl::desc("Don't display full class definitions"),
- 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));
}
+namespace diff {
+cl::opt<bool> Pedantic("pedantic",
+ cl::desc("Finds all differences (even structural ones "
+ "that produce otherwise identical PDBs)"),
+ cl::sub(DiffSubcommand));
+
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<first> <second>"),
+ cl::OneOrMore, cl::sub(DiffSubcommand));
+}
+
namespace raw {
cl::OptionCategory MsfOptions("MSF Container Options");
@@ -187,6 +253,11 @@ cl::list<uint32_t>
// TYPE OPTIONS
cl::opt<bool>
+ CompactRecords("compact-records",
+ cl::desc("Dump type and symbol records with less detail"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool>
DumpTpiRecords("tpi-records",
cl::desc("dump CodeView type records from TPI stream"),
cl::cat(TypeOptions), cl::sub(RawSubcommand));
@@ -227,6 +298,9 @@ cl::opt<bool>
cl::cat(SymbolOptions), cl::sub(RawSubcommand));
// MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
+ cl::cat(MiscOptions), cl::sub(RawSubcommand));
+
cl::opt<bool> DumpSectionContribs("section-contribs",
cl::desc("dump section contributions"),
cl::cat(MiscOptions), cl::sub(RawSubcommand));
@@ -262,6 +336,9 @@ cl::opt<bool>
cl::desc("Do not dump MSF file headers (you will not be able "
"to generate a fresh PDB from the resulting YAML)"),
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",
@@ -274,6 +351,10 @@ cl::opt<bool> StreamDirectory(
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 (Stream 2)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
@@ -305,6 +386,14 @@ cl::list<std::string> InputFilename(cl::Positional,
cl::desc("<input PDB file>"), cl::Required,
cl::sub(PdbToYamlSubcommand));
}
+
+namespace analyze {
+cl::opt<bool> StringTable("hash-collisions", cl::desc("Find hash collisions"),
+ cl::sub(AnalyzeSubcommand), cl::init(false));
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(AnalyzeSubcommand));
+}
}
static ExitOnError ExitOnErr;
@@ -324,13 +413,13 @@ static void yamlToPdb(StringRef Path) {
llvm::yaml::Input In(Buffer->getBuffer());
pdb::yaml::PdbObject YamlObj(Allocator);
In >> YamlObj;
- if (!YamlObj.Headers.hasValue())
- ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
- "Yaml does not contain MSF headers"));
PDBFileBuilder Builder(Allocator);
- ExitOnErr(Builder.initialize(YamlObj.Headers->SuperBlock.BlockSize));
+ 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
@@ -340,56 +429,74 @@ static void yamlToPdb(StringRef Path) {
for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
ExitOnErr(Builder.getMsfBuilder().addStream(0));
- if (YamlObj.PdbStream.hasValue()) {
- auto &InfoBuilder = Builder.getInfoBuilder();
- InfoBuilder.setAge(YamlObj.PdbStream->Age);
- InfoBuilder.setGuid(YamlObj.PdbStream->Guid);
- InfoBuilder.setSignature(YamlObj.PdbStream->Signature);
- InfoBuilder.setVersion(YamlObj.PdbStream->Version);
- for (auto &NM : YamlObj.PdbStream->NamedStreams)
- InfoBuilder.getNamedStreamsBuilder().addMapping(NM.StreamName,
- NM.StreamNumber);
+ if (YamlObj.StringTable.hasValue()) {
+ auto &Strings = Builder.getStringTableBuilder();
+ for (auto S : *YamlObj.StringTable)
+ Strings.insert(S);
}
- if (YamlObj.DbiStream.hasValue()) {
- auto &DbiBuilder = Builder.getDbiBuilder();
- DbiBuilder.setAge(YamlObj.DbiStream->Age);
- DbiBuilder.setBuildNumber(YamlObj.DbiStream->BuildNumber);
- DbiBuilder.setFlags(YamlObj.DbiStream->Flags);
- DbiBuilder.setMachineType(YamlObj.DbiStream->MachineType);
- DbiBuilder.setPdbDllRbld(YamlObj.DbiStream->PdbDllRbld);
- DbiBuilder.setPdbDllVersion(YamlObj.DbiStream->PdbDllVersion);
- DbiBuilder.setVersionHeader(YamlObj.DbiStream->VerHeader);
- for (const auto &MI : YamlObj.DbiStream->ModInfos) {
- ExitOnErr(DbiBuilder.addModuleInfo(MI.Obj, MI.Mod));
- for (auto S : MI.SourceFiles)
- ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S));
+ pdb::yaml::PdbInfoStream DefaultInfoStream;
+ pdb::yaml::PdbDbiStream DefaultDbiStream;
+ pdb::yaml::PdbTpiStream DefaultTpiStream;
+
+ 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));
+
+ for (auto S : MI.SourceFiles)
+ ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S));
+ if (MI.Modi.hasValue()) {
+ const auto &ModiStream = *MI.Modi;
+ ModiBuilder.setObjFileName(MI.Obj);
+ for (auto Symbol : ModiStream.Symbols)
+ ModiBuilder.addSymbol(Symbol.Record);
}
}
- if (YamlObj.TpiStream.hasValue()) {
- auto &TpiBuilder = Builder.getTpiBuilder();
- TpiBuilder.setVersionHeader(YamlObj.TpiStream->Version);
- for (const auto &R : YamlObj.TpiStream->Records)
- TpiBuilder.addTypeRecord(R.Record);
- }
+ auto &TpiBuilder = Builder.getTpiBuilder();
+ const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
+ TpiBuilder.setVersionHeader(Tpi.Version);
+ for (const auto &R : Tpi.Records)
+ TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
- if (YamlObj.IpiStream.hasValue()) {
- auto &IpiBuilder = Builder.getIpiBuilder();
- IpiBuilder.setVersionHeader(YamlObj.IpiStream->Version);
- for (const auto &R : YamlObj.IpiStream->Records)
- IpiBuilder.addTypeRecord(R.Record);
- }
+ const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultTpiStream);
+ auto &IpiBuilder = Builder.getIpiBuilder();
+ IpiBuilder.setVersionHeader(Ipi.Version);
+ for (const auto &R : Ipi.Records)
+ TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
}
+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;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
+ auto &File = loadPDB(Path, Session);
- RawSession *RS = static_cast<RawSession *>(Session.get());
- PDBFile &File = RS->getPDBFile();
auto O = llvm::make_unique<YAMLOutputStyle>(File);
O = llvm::make_unique<YAMLOutputStyle>(File);
@@ -398,24 +505,48 @@ static void pdb2Yaml(StringRef Path) {
static void dumpRaw(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
+ auto &File = loadPDB(Path, Session);
- RawSession *RS = static_cast<RawSession *>(Session.get());
- PDBFile &File = RS->getPDBFile();
auto O = llvm::make_unique<LLVMOutputStyle>(File);
ExitOnErr(O->dump());
}
+static void dumpAnalysis(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+ auto &File = loadPDB(Path, Session);
+ auto O = llvm::make_unique<AnalysisStyle>(File);
+
+ ExitOnErr(O->dump());
+}
+
+static void diff(StringRef Path1, StringRef Path2) {
+ std::unique_ptr<IPDBSession> Session1;
+ std::unique_ptr<IPDBSession> Session2;
+
+ auto &File1 = loadPDB(Path1, Session1);
+ auto &File2 = loadPDB(Path2, Session2);
+
+ auto O = llvm::make_unique<DiffStyle>(File1, File2);
+
+ ExitOnErr(O->dump());
+}
+
static void dumpPretty(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, 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);
- LinePrinter Printer(2, outs());
+ 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());
std::string FileName(GlobalScope->getSymbolsFileName());
@@ -465,7 +596,7 @@ static void dumpPretty(StringRef Path) {
Printer.Unindent();
}
- if (opts::pretty::Types) {
+ if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
Printer.Indent();
@@ -556,24 +687,34 @@ int main(int argc_, const char *argv_[]) {
}
}
- if (opts::RawSubcommand && opts::raw::RawAll) {
- opts::raw::DumpHeaders = true;
- opts::raw::DumpModules = true;
- opts::raw::DumpModuleFiles = true;
- opts::raw::DumpModuleSyms = true;
- opts::raw::DumpGlobals = true;
- opts::raw::DumpPublics = true;
- opts::raw::DumpSectionHeaders = true;
- opts::raw::DumpStreamSummary = true;
- opts::raw::DumpPageStats = true;
- opts::raw::DumpStreamBlocks = true;
- opts::raw::DumpTpiRecords = true;
- opts::raw::DumpTpiHash = true;
- opts::raw::DumpIpiRecords = true;
- opts::raw::DumpSectionMap = true;
- opts::raw::DumpSectionContribs = true;
- opts::raw::DumpLineInfo = true;
- opts::raw::DumpFpo = true;
+ if (opts::RawSubcommand) {
+ if (opts::raw::RawAll) {
+ opts::raw::DumpHeaders = true;
+ opts::raw::DumpModules = true;
+ opts::raw::DumpModuleFiles = true;
+ opts::raw::DumpModuleSyms = true;
+ opts::raw::DumpGlobals = true;
+ opts::raw::DumpPublics = true;
+ opts::raw::DumpSectionHeaders = true;
+ opts::raw::DumpStreamSummary = true;
+ opts::raw::DumpPageStats = true;
+ opts::raw::DumpStreamBlocks = true;
+ opts::raw::DumpTpiRecords = true;
+ opts::raw::DumpTpiHash = true;
+ opts::raw::DumpIpiRecords = true;
+ opts::raw::DumpSectionMap = true;
+ opts::raw::DumpSectionContribs = true;
+ opts::raw::DumpLineInfo = true;
+ opts::raw::DumpFpo = true;
+ opts::raw::DumpStringTable = true;
+ }
+
+ if (opts::raw::CompactRecords &&
+ (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) {
+ errs() << "-compact-records is incompatible with -tpi-record-bytes and "
+ "-ipi-record-bytes.\n";
+ exit(1);
+ }
}
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
@@ -582,6 +723,8 @@ int main(int argc_, const char *argv_[]) {
pdb2Yaml(opts::pdb2yaml::InputFilename.front());
} else if (opts::YamlToPdbSubcommand) {
yamlToPdb(opts::yaml2pdb::InputFilename.front());
+ } else if (opts::AnalyzeSubcommand) {
+ dumpAnalysis(opts::analyze::InputFilename.front());
} else if (opts::PrettySubcommand) {
if (opts::pretty::Lines)
opts::pretty::Compilands = true;
@@ -595,6 +738,12 @@ int main(int argc_, const char *argv_[]) {
opts::pretty::Lines = true;
}
+ if (opts::pretty::Types) {
+ opts::pretty::Classes = true;
+ opts::pretty::Typedefs = true;
+ opts::pretty::Enums = 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
@@ -616,6 +765,12 @@ int main(int argc_, const char *argv_[]) {
} else if (opts::RawSubcommand) {
std::for_each(opts::raw::InputFilenames.begin(),
opts::raw::InputFilenames.end(), dumpRaw);
+ } else if (opts::DiffSubcommand) {
+ if (opts::diff::InputFilenames.size() != 2) {
+ errs() << "diff subcommand expects exactly 2 arguments.\n";
+ exit(1);
+ }
+ diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]);
}
outs().flush();