xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10b57cec5SDimitry Andric //===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Dumps debug information present in PDB files.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm-pdbutil.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "BytesOutputStyle.h"
160b57cec5SDimitry Andric #include "DumpOutputStyle.h"
170b57cec5SDimitry Andric #include "ExplainOutputStyle.h"
180b57cec5SDimitry Andric #include "OutputStyle.h"
190b57cec5SDimitry Andric #include "PrettyClassDefinitionDumper.h"
200b57cec5SDimitry Andric #include "PrettyCompilandDumper.h"
210b57cec5SDimitry Andric #include "PrettyEnumDumper.h"
220b57cec5SDimitry Andric #include "PrettyExternalSymbolDumper.h"
230b57cec5SDimitry Andric #include "PrettyFunctionDumper.h"
240b57cec5SDimitry Andric #include "PrettyTypeDumper.h"
250b57cec5SDimitry Andric #include "PrettyTypedefDumper.h"
260b57cec5SDimitry Andric #include "PrettyVariableDumper.h"
270b57cec5SDimitry Andric #include "YAMLOutputStyle.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
300b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
310b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
320b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
330b57cec5SDimitry Andric #include "llvm/Config/config.h"
340b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
350b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
360b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
370b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
380b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
390b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
400b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
410b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
420b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MSFBuilder.h"
4381ad6265SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
4481ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
450b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
460b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
4781ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
480b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
490b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h"
500b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
510b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
520b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
530b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
5481ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InputFile.h"
550b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
560b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
570b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
580b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
590b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
600b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
610b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
620b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
630b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
640b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
650b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
660b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
670b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
680b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
690b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
7081ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
710b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
720b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
730b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
740b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
750b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
760b57cec5SDimitry Andric #include "llvm/Support/BinaryByteStream.h"
770b57cec5SDimitry Andric #include "llvm/Support/COM.h"
780b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
790b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
800b57cec5SDimitry Andric #include "llvm/Support/FileOutputBuffer.h"
810b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
820b57cec5SDimitry Andric #include "llvm/Support/Format.h"
830b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
840b57cec5SDimitry Andric #include "llvm/Support/LineIterator.h"
850b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
860b57cec5SDimitry Andric #include "llvm/Support/Path.h"
870b57cec5SDimitry Andric #include "llvm/Support/PrettyStackTrace.h"
880b57cec5SDimitry Andric #include "llvm/Support/Process.h"
890b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
900b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
910b57cec5SDimitry Andric #include "llvm/Support/Signals.h"
920b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric using namespace llvm;
950b57cec5SDimitry Andric using namespace llvm::codeview;
960b57cec5SDimitry Andric using namespace llvm::msf;
970b57cec5SDimitry Andric using namespace llvm::pdb;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric namespace opts {
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric cl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info");
1020b57cec5SDimitry Andric cl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file");
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric cl::SubCommand DiaDumpSubcommand("diadump",
1050b57cec5SDimitry Andric                                  "Dump debug information using a DIA-like API");
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric cl::SubCommand
1080b57cec5SDimitry Andric     PrettySubcommand("pretty",
1090b57cec5SDimitry Andric                      "Dump semantic information about types and symbols");
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric cl::SubCommand
1120b57cec5SDimitry Andric     YamlToPdbSubcommand("yaml2pdb",
1130b57cec5SDimitry Andric                         "Generate a PDB file from a YAML description");
1140b57cec5SDimitry Andric cl::SubCommand
1150b57cec5SDimitry Andric     PdbToYamlSubcommand("pdb2yaml",
1160b57cec5SDimitry Andric                         "Generate a detailed YAML description of a PDB File");
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric cl::SubCommand MergeSubcommand("merge",
1190b57cec5SDimitry Andric                                "Merge multiple PDBs into a single PDB");
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric cl::SubCommand ExplainSubcommand("explain",
1220b57cec5SDimitry Andric                                  "Explain the meaning of a file offset");
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric cl::SubCommand ExportSubcommand("export",
1250b57cec5SDimitry Andric                                 "Write binary data from a stream to a file");
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric cl::OptionCategory TypeCategory("Symbol Type Options");
1280b57cec5SDimitry Andric cl::OptionCategory FilterCategory("Filtering and Sorting Options");
1290b57cec5SDimitry Andric cl::OptionCategory OtherOptions("Other Options");
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric cl::ValuesClass ChunkValues = cl::values(
1320b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::CrossScopeExports, "cme",
1330b57cec5SDimitry Andric                "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
1340b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::CrossScopeImports, "cmi",
1350b57cec5SDimitry Andric                "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
1360b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::FileChecksums, "fc",
1370b57cec5SDimitry Andric                "File checksums (DEBUG_S_CHECKSUMS subsection)"),
1380b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::InlineeLines, "ilines",
1390b57cec5SDimitry Andric                "Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
1400b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::Lines, "lines",
1410b57cec5SDimitry Andric                "Lines (DEBUG_S_LINES subsection)"),
1420b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::StringTable, "strings",
1430b57cec5SDimitry Andric                "String Table (DEBUG_S_STRINGTABLE subsection) (not "
1440b57cec5SDimitry Andric                "typically present in PDB file)"),
1450b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::FrameData, "frames",
1460b57cec5SDimitry Andric                "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
1470b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::Symbols, "symbols",
1480b57cec5SDimitry Andric                "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
1490b57cec5SDimitry Andric                "present in PDB file)"),
1500b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas",
1510b57cec5SDimitry Andric                "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"),
1520b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::Unknown, "unknown",
1530b57cec5SDimitry Andric                "Any subsection not covered by another option"),
1540b57cec5SDimitry Andric     clEnumValN(ModuleSubsection::All, "all", "All known subsections"));
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric namespace diadump {
1570b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional,
1580b57cec5SDimitry Andric                                      cl::desc("<input PDB files>"),
1590b57cec5SDimitry Andric                                      cl::OneOrMore, cl::sub(DiaDumpSubcommand));
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
1620b57cec5SDimitry Andric                      cl::sub(DiaDumpSubcommand));
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric static cl::opt<bool>
1650b57cec5SDimitry Andric     ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"),
1660b57cec5SDimitry Andric                        cl::sub(DiaDumpSubcommand));
1670b57cec5SDimitry Andric static cl::opt<bool> NoSymIndexIds(
1680b57cec5SDimitry Andric     "no-ids",
1690b57cec5SDimitry Andric     cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"),
1700b57cec5SDimitry Andric     cl::sub(DiaDumpSubcommand));
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric static cl::opt<bool>
1730b57cec5SDimitry Andric     Recurse("recurse",
1740b57cec5SDimitry Andric             cl::desc("When dumping a SymIndexId, dump the full details of the "
1750b57cec5SDimitry Andric                      "corresponding record"),
1760b57cec5SDimitry Andric             cl::sub(DiaDumpSubcommand));
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric static cl::opt<bool> Enums("enums", cl::desc("Dump enum types"),
1790b57cec5SDimitry Andric                            cl::sub(DiaDumpSubcommand));
1800b57cec5SDimitry Andric static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),
1810b57cec5SDimitry Andric                               cl::sub(DiaDumpSubcommand));
1820b57cec5SDimitry Andric static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),
1830b57cec5SDimitry Andric                           cl::sub(DiaDumpSubcommand));
1840b57cec5SDimitry Andric static cl::opt<bool> Compilands("compilands",
1850b57cec5SDimitry Andric                                 cl::desc("Dump compiland information"),
1860b57cec5SDimitry Andric                                 cl::sub(DiaDumpSubcommand));
1870b57cec5SDimitry Andric static cl::opt<bool> Funcsigs("funcsigs",
1880b57cec5SDimitry Andric                               cl::desc("Dump function signature information"),
1890b57cec5SDimitry Andric                               cl::sub(DiaDumpSubcommand));
1900b57cec5SDimitry Andric static cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"),
1910b57cec5SDimitry Andric                             cl::sub(DiaDumpSubcommand));
1920b57cec5SDimitry Andric static cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"),
1930b57cec5SDimitry Andric                               cl::sub(DiaDumpSubcommand));
1940b57cec5SDimitry Andric static cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"),
1950b57cec5SDimitry Andric                               cl::sub(DiaDumpSubcommand));
1960b57cec5SDimitry Andric } // namespace diadump
1970b57cec5SDimitry Andric 
19881ad6265SDimitry Andric FilterOptions Filters;
19981ad6265SDimitry Andric 
2000b57cec5SDimitry Andric namespace pretty {
2010b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional,
2020b57cec5SDimitry Andric                                      cl::desc("<input PDB files>"),
2030b57cec5SDimitry Andric                                      cl::OneOrMore, cl::sub(PrettySubcommand));
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric cl::opt<bool> InjectedSources("injected-sources",
2060b57cec5SDimitry Andric                               cl::desc("Display injected sources"),
2070b57cec5SDimitry Andric                               cl::cat(OtherOptions), cl::sub(PrettySubcommand));
2080b57cec5SDimitry Andric cl::opt<bool> ShowInjectedSourceContent(
2090b57cec5SDimitry Andric     "injected-source-content",
2100b57cec5SDimitry Andric     cl::desc("When displaying an injected source, display the file content"),
2110b57cec5SDimitry Andric     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric cl::list<std::string> WithName(
2140b57cec5SDimitry Andric     "with-name",
2150b57cec5SDimitry Andric     cl::desc("Display any symbol or type with the specified exact name"),
21681ad6265SDimitry Andric     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
2190b57cec5SDimitry Andric                          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2200b57cec5SDimitry Andric cl::opt<bool> Symbols("module-syms",
2210b57cec5SDimitry Andric                       cl::desc("Display symbols for each compiland"),
2220b57cec5SDimitry Andric                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2230b57cec5SDimitry Andric cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
2240b57cec5SDimitry Andric                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2250b57cec5SDimitry Andric cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
2260b57cec5SDimitry Andric                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2270b57cec5SDimitry Andric cl::list<SymLevel> SymTypes(
2280b57cec5SDimitry Andric     "sym-types", cl::desc("Type of symbols to dump (default all)"),
22981ad6265SDimitry Andric     cl::cat(TypeCategory), cl::sub(PrettySubcommand),
2300b57cec5SDimitry Andric     cl::values(
2310b57cec5SDimitry Andric         clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),
2320b57cec5SDimitry Andric         clEnumValN(SymLevel::Data, "data", "Display data symbols"),
2330b57cec5SDimitry Andric         clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),
2340b57cec5SDimitry Andric         clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric cl::opt<bool>
2370b57cec5SDimitry Andric     Types("types",
2380b57cec5SDimitry Andric           cl::desc("Display all types (implies -classes, -enums, -typedefs)"),
2390b57cec5SDimitry Andric           cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2400b57cec5SDimitry Andric cl::opt<bool> Classes("classes", cl::desc("Display class types"),
2410b57cec5SDimitry Andric                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2420b57cec5SDimitry Andric cl::opt<bool> Enums("enums", cl::desc("Display enum types"),
2430b57cec5SDimitry Andric                     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2440b57cec5SDimitry Andric cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
2450b57cec5SDimitry Andric                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2460b57cec5SDimitry Andric cl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"),
2470b57cec5SDimitry Andric                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2480b57cec5SDimitry Andric cl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"),
2490b57cec5SDimitry Andric                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2500b57cec5SDimitry Andric cl::opt<bool> Arrays("arrays", cl::desc("Display arrays"),
2510b57cec5SDimitry Andric                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2520b57cec5SDimitry Andric cl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"),
2530b57cec5SDimitry Andric                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric cl::opt<SymbolSortMode> SymbolOrder(
2560b57cec5SDimitry Andric     "symbol-order", cl::desc("symbol sort order"),
2570b57cec5SDimitry Andric     cl::init(SymbolSortMode::None),
2580b57cec5SDimitry Andric     cl::values(clEnumValN(SymbolSortMode::None, "none",
2590b57cec5SDimitry Andric                           "Undefined / no particular sort order"),
2600b57cec5SDimitry Andric                clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),
2610b57cec5SDimitry Andric                clEnumValN(SymbolSortMode::Size, "size",
2620b57cec5SDimitry Andric                           "Sort symbols by size")),
2630b57cec5SDimitry Andric     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric cl::opt<ClassSortMode> ClassOrder(
2660b57cec5SDimitry Andric     "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
2670b57cec5SDimitry Andric     cl::values(
2680b57cec5SDimitry Andric         clEnumValN(ClassSortMode::None, "none",
2690b57cec5SDimitry Andric                    "Undefined / no particular sort order"),
2700b57cec5SDimitry Andric         clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
2710b57cec5SDimitry Andric         clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
2720b57cec5SDimitry Andric         clEnumValN(ClassSortMode::Padding, "padding",
2730b57cec5SDimitry Andric                    "Sort classes by amount of padding"),
2740b57cec5SDimitry Andric         clEnumValN(ClassSortMode::PaddingPct, "padding-pct",
2750b57cec5SDimitry Andric                    "Sort classes by percentage of space consumed by padding"),
2760b57cec5SDimitry Andric         clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",
2770b57cec5SDimitry Andric                    "Sort classes by amount of immediate padding"),
2780b57cec5SDimitry Andric         clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",
2790b57cec5SDimitry Andric                    "Sort classes by percentage of space consumed by immediate "
2800b57cec5SDimitry Andric                    "padding")),
2810b57cec5SDimitry Andric     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric cl::opt<ClassDefinitionFormat> ClassFormat(
2840b57cec5SDimitry Andric     "class-definitions", cl::desc("Class definition format"),
2850b57cec5SDimitry Andric     cl::init(ClassDefinitionFormat::All),
2860b57cec5SDimitry Andric     cl::values(
2870b57cec5SDimitry Andric         clEnumValN(ClassDefinitionFormat::All, "all",
2880b57cec5SDimitry Andric                    "Display all class members including data, constants, "
2890b57cec5SDimitry Andric                    "typedefs, functions, etc"),
2900b57cec5SDimitry Andric         clEnumValN(ClassDefinitionFormat::Layout, "layout",
2910b57cec5SDimitry Andric                    "Only display members that contribute to class size."),
2920b57cec5SDimitry Andric         clEnumValN(ClassDefinitionFormat::None, "none",
2930b57cec5SDimitry Andric                    "Don't display class definitions")),
2940b57cec5SDimitry Andric     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2950b57cec5SDimitry Andric cl::opt<uint32_t> ClassRecursionDepth(
2960b57cec5SDimitry Andric     "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),
2970b57cec5SDimitry Andric     cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
3000b57cec5SDimitry Andric                     cl::sub(PrettySubcommand));
3010b57cec5SDimitry Andric cl::opt<bool>
3020b57cec5SDimitry Andric     All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
3030b57cec5SDimitry Andric         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric cl::opt<uint64_t> LoadAddress(
3060b57cec5SDimitry Andric     "load-address",
3070b57cec5SDimitry Andric     cl::desc("Assume the module is loaded at the specified address"),
3080b57cec5SDimitry Andric     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
3090b57cec5SDimitry Andric cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
3100b57cec5SDimitry Andric                      cl::cat(OtherOptions), cl::sub(PrettySubcommand));
3110b57cec5SDimitry Andric cl::opt<cl::boolOrDefault>
3120b57cec5SDimitry Andric     ColorOutput("color-output",
3130b57cec5SDimitry Andric                 cl::desc("Override use of color (default = isatty)"),
3140b57cec5SDimitry Andric                 cl::cat(OtherOptions), cl::sub(PrettySubcommand));
31581ad6265SDimitry Andric cl::list<std::string>
31681ad6265SDimitry Andric     ExcludeTypes("exclude-types",
31781ad6265SDimitry Andric                  cl::desc("Exclude types by regular expression"),
31881ad6265SDimitry Andric                  cl::cat(FilterCategory), cl::sub(PrettySubcommand));
31981ad6265SDimitry Andric cl::list<std::string>
32081ad6265SDimitry Andric     ExcludeSymbols("exclude-symbols",
32181ad6265SDimitry Andric                    cl::desc("Exclude symbols by regular expression"),
32281ad6265SDimitry Andric                    cl::cat(FilterCategory), cl::sub(PrettySubcommand));
32381ad6265SDimitry Andric cl::list<std::string>
32481ad6265SDimitry Andric     ExcludeCompilands("exclude-compilands",
32581ad6265SDimitry Andric                       cl::desc("Exclude compilands by regular expression"),
32681ad6265SDimitry Andric                       cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric cl::list<std::string> IncludeTypes(
3290b57cec5SDimitry Andric     "include-types",
3300b57cec5SDimitry Andric     cl::desc("Include only types which match a regular expression"),
33181ad6265SDimitry Andric     cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3320b57cec5SDimitry Andric cl::list<std::string> IncludeSymbols(
3330b57cec5SDimitry Andric     "include-symbols",
3340b57cec5SDimitry Andric     cl::desc("Include only symbols which match a regular expression"),
33581ad6265SDimitry Andric     cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3360b57cec5SDimitry Andric cl::list<std::string> IncludeCompilands(
3370b57cec5SDimitry Andric     "include-compilands",
3380b57cec5SDimitry Andric     cl::desc("Include only compilands those which match a regular expression"),
33981ad6265SDimitry Andric     cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3400b57cec5SDimitry Andric cl::opt<uint32_t> SizeThreshold(
3410b57cec5SDimitry Andric     "min-type-size", cl::desc("Displays only those types which are greater "
3420b57cec5SDimitry Andric                               "than or equal to the specified size."),
3430b57cec5SDimitry Andric     cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3440b57cec5SDimitry Andric cl::opt<uint32_t> PaddingThreshold(
3450b57cec5SDimitry Andric     "min-class-padding", cl::desc("Displays only those classes which have at "
3460b57cec5SDimitry Andric                                   "least the specified amount of padding."),
3470b57cec5SDimitry Andric     cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3480b57cec5SDimitry Andric cl::opt<uint32_t> ImmediatePaddingThreshold(
3490b57cec5SDimitry Andric     "min-class-padding-imm",
3500b57cec5SDimitry Andric     cl::desc("Displays only those classes which have at least the specified "
3510b57cec5SDimitry Andric              "amount of immediate padding, ignoring padding internal to bases "
3520b57cec5SDimitry Andric              "and aggregates."),
3530b57cec5SDimitry Andric     cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric cl::opt<bool> ExcludeCompilerGenerated(
3560b57cec5SDimitry Andric     "no-compiler-generated",
3570b57cec5SDimitry Andric     cl::desc("Don't show compiler generated types and symbols"),
3580b57cec5SDimitry Andric     cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3590b57cec5SDimitry Andric cl::opt<bool>
3600b57cec5SDimitry Andric     ExcludeSystemLibraries("no-system-libs",
3610b57cec5SDimitry Andric                            cl::desc("Don't show symbols from system libraries"),
3620b57cec5SDimitry Andric                            cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric cl::opt<bool> NoEnumDefs("no-enum-definitions",
3650b57cec5SDimitry Andric                          cl::desc("Don't display full enum definitions"),
3660b57cec5SDimitry Andric                          cl::cat(FilterCategory), cl::sub(PrettySubcommand));
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric cl::OptionCategory FileOptions("Module & File Options");
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric namespace bytes {
3720b57cec5SDimitry Andric cl::OptionCategory MsfBytes("MSF File Options");
3730b57cec5SDimitry Andric cl::OptionCategory DbiBytes("Dbi Stream Options");
3740b57cec5SDimitry Andric cl::OptionCategory PdbBytes("PDB Stream Options");
3750b57cec5SDimitry Andric cl::OptionCategory Types("Type Options");
3760b57cec5SDimitry Andric cl::OptionCategory ModuleCategory("Module Options");
3770b57cec5SDimitry Andric 
378bdd1243dSDimitry Andric std::optional<NumberRange> DumpBlockRange;
379bdd1243dSDimitry Andric std::optional<NumberRange> DumpByteRange;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric cl::opt<std::string> DumpBlockRangeOpt(
3820b57cec5SDimitry Andric     "block-range", cl::value_desc("start[-end]"),
3830b57cec5SDimitry Andric     cl::desc("Dump binary data from specified range of blocks."),
3840b57cec5SDimitry Andric     cl::sub(BytesSubcommand), cl::cat(MsfBytes));
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric cl::opt<std::string>
3870b57cec5SDimitry Andric     DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
3880b57cec5SDimitry Andric                      cl::desc("Dump binary data from specified range of bytes"),
3890b57cec5SDimitry Andric                      cl::sub(BytesSubcommand), cl::cat(MsfBytes));
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric cl::list<std::string>
39281ad6265SDimitry Andric     DumpStreamData("stream-data", cl::CommaSeparated,
3930b57cec5SDimitry Andric                    cl::desc("Dump binary data from specified streams.  Format "
3940b57cec5SDimitry Andric                             "is SN[:Start][@Size]"),
3950b57cec5SDimitry Andric                    cl::sub(BytesSubcommand), cl::cat(MsfBytes));
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric cl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),
3980b57cec5SDimitry Andric                       cl::sub(BytesSubcommand), cl::cat(PdbBytes));
3990b57cec5SDimitry Andric cl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"),
4000b57cec5SDimitry Andric                   cl::sub(BytesSubcommand), cl::cat(MsfBytes));
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric cl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"),
4030b57cec5SDimitry Andric                                    cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4040b57cec5SDimitry Andric cl::opt<bool> SectionMap("sm", cl::desc("Dump section map"),
4050b57cec5SDimitry Andric                          cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4060b57cec5SDimitry Andric cl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"),
4070b57cec5SDimitry Andric                           cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4080b57cec5SDimitry Andric cl::opt<bool> FileInfo("files", cl::desc("Dump source file info"),
4090b57cec5SDimitry Andric                        cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4100b57cec5SDimitry Andric cl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),
4110b57cec5SDimitry Andric                             cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4120b57cec5SDimitry Andric cl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),
4130b57cec5SDimitry Andric                      cl::sub(BytesSubcommand), cl::cat(DbiBytes));
4140b57cec5SDimitry Andric 
41581ad6265SDimitry Andric cl::list<uint32_t> TypeIndex(
41681ad6265SDimitry Andric     "type", cl::desc("Dump the type record with the given type index"),
41781ad6265SDimitry Andric     cl::CommaSeparated, cl::sub(BytesSubcommand), cl::cat(TypeCategory));
4180b57cec5SDimitry Andric cl::list<uint32_t>
4190b57cec5SDimitry Andric     IdIndex("id", cl::desc("Dump the id record with the given type index"),
42081ad6265SDimitry Andric             cl::CommaSeparated, cl::sub(BytesSubcommand),
4210b57cec5SDimitry Andric             cl::cat(TypeCategory));
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric cl::opt<uint32_t> ModuleIndex(
4240b57cec5SDimitry Andric     "mod",
4250b57cec5SDimitry Andric     cl::desc(
4260b57cec5SDimitry Andric         "Limit options in the Modules category to the specified module index"),
4270b57cec5SDimitry Andric     cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
4280b57cec5SDimitry Andric cl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"),
4290b57cec5SDimitry Andric                          cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
4300b57cec5SDimitry Andric cl::opt<bool> ModuleC11("c11-chunks", cl::Hidden,
4310b57cec5SDimitry Andric                         cl::desc("Dump C11 CodeView debug chunks"),
4320b57cec5SDimitry Andric                         cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
4330b57cec5SDimitry Andric cl::opt<bool> ModuleC13("chunks",
4340b57cec5SDimitry Andric                         cl::desc("Dump C13 CodeView debug chunk subsection"),
4350b57cec5SDimitry Andric                         cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
4360b57cec5SDimitry Andric cl::opt<bool> SplitChunks(
4370b57cec5SDimitry Andric     "split-chunks",
4380b57cec5SDimitry Andric     cl::desc(
4390b57cec5SDimitry Andric         "When dumping debug chunks, show a different section for each chunk"),
4400b57cec5SDimitry Andric     cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
4410b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional,
4420b57cec5SDimitry Andric                                      cl::desc("<input PDB files>"),
4430b57cec5SDimitry Andric                                      cl::OneOrMore, cl::sub(BytesSubcommand));
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric } // namespace bytes
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric namespace dump {
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric cl::OptionCategory MsfOptions("MSF Container Options");
4500b57cec5SDimitry Andric cl::OptionCategory TypeOptions("Type Record Options");
4510b57cec5SDimitry Andric cl::OptionCategory SymbolOptions("Symbol Options");
4520b57cec5SDimitry Andric cl::OptionCategory MiscOptions("Miscellaneous Options");
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric // MSF OPTIONS
4550b57cec5SDimitry Andric cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),
4560b57cec5SDimitry Andric                           cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4570b57cec5SDimitry Andric cl::opt<bool> DumpStreams("streams",
4580b57cec5SDimitry Andric                           cl::desc("dump summary of the PDB streams"),
4590b57cec5SDimitry Andric                           cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4600b57cec5SDimitry Andric cl::opt<bool> DumpStreamBlocks(
4610b57cec5SDimitry Andric     "stream-blocks",
4620b57cec5SDimitry Andric     cl::desc("Add block information to the output of -streams"),
4630b57cec5SDimitry Andric     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4640b57cec5SDimitry Andric cl::opt<bool> DumpSymbolStats(
4650b57cec5SDimitry Andric     "sym-stats",
4660b57cec5SDimitry Andric     cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),
4670b57cec5SDimitry Andric     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4680b57cec5SDimitry Andric cl::opt<bool> DumpTypeStats(
4690b57cec5SDimitry Andric     "type-stats",
4700b57cec5SDimitry Andric     cl::desc("Dump a detailed breakdown of type usage/size"),
4710b57cec5SDimitry Andric     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4725ffd83dbSDimitry Andric cl::opt<bool> DumpIDStats(
4735ffd83dbSDimitry Andric     "id-stats",
4745ffd83dbSDimitry Andric     cl::desc("Dump a detailed breakdown of IPI types usage/size"),
4755ffd83dbSDimitry Andric     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4760b57cec5SDimitry Andric cl::opt<bool> DumpUdtStats(
4770b57cec5SDimitry Andric     "udt-stats",
4780b57cec5SDimitry Andric     cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
4790b57cec5SDimitry Andric     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric // TYPE OPTIONS
4820b57cec5SDimitry Andric cl::opt<bool> DumpTypes("types",
4830b57cec5SDimitry Andric                         cl::desc("dump CodeView type records from TPI stream"),
4840b57cec5SDimitry Andric                         cl::cat(TypeOptions), cl::sub(DumpSubcommand));
4850b57cec5SDimitry Andric cl::opt<bool> DumpTypeData(
4860b57cec5SDimitry Andric     "type-data",
4870b57cec5SDimitry Andric     cl::desc("dump CodeView type record raw bytes from TPI stream"),
4880b57cec5SDimitry Andric     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
4890b57cec5SDimitry Andric cl::opt<bool>
4900b57cec5SDimitry Andric     DumpTypeRefStats("type-ref-stats",
4910b57cec5SDimitry Andric                      cl::desc("dump statistics on the number and size of types "
4920b57cec5SDimitry Andric                               "transitively referenced by symbol records"),
4930b57cec5SDimitry Andric                      cl::cat(TypeOptions), cl::sub(DumpSubcommand));
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric cl::opt<bool> DumpTypeExtras("type-extras",
4960b57cec5SDimitry Andric                              cl::desc("dump type hashes and index offsets"),
4970b57cec5SDimitry Andric                              cl::cat(TypeOptions), cl::sub(DumpSubcommand));
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric cl::opt<bool> DontResolveForwardRefs(
5000b57cec5SDimitry Andric     "dont-resolve-forward-refs",
5010b57cec5SDimitry Andric     cl::desc("When dumping type records for classes, unions, enums, and "
5020b57cec5SDimitry Andric              "structs, don't try to resolve forward references"),
5030b57cec5SDimitry Andric     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric cl::list<uint32_t> DumpTypeIndex(
50681ad6265SDimitry Andric     "type-index", cl::CommaSeparated,
5070b57cec5SDimitry Andric     cl::desc("only dump types with the specified hexadecimal type index"),
5080b57cec5SDimitry Andric     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric cl::opt<bool> DumpIds("ids",
5110b57cec5SDimitry Andric                       cl::desc("dump CodeView type records from IPI stream"),
5120b57cec5SDimitry Andric                       cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5130b57cec5SDimitry Andric cl::opt<bool>
5140b57cec5SDimitry Andric     DumpIdData("id-data",
5150b57cec5SDimitry Andric                cl::desc("dump CodeView type record raw bytes from IPI stream"),
5160b57cec5SDimitry Andric                cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric cl::opt<bool> DumpIdExtras("id-extras",
5190b57cec5SDimitry Andric                            cl::desc("dump id hashes and index offsets"),
5200b57cec5SDimitry Andric                            cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5210b57cec5SDimitry Andric cl::list<uint32_t> DumpIdIndex(
52281ad6265SDimitry Andric     "id-index", cl::CommaSeparated,
5230b57cec5SDimitry Andric     cl::desc("only dump ids with the specified hexadecimal type index"),
5240b57cec5SDimitry Andric     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric cl::opt<bool> DumpTypeDependents(
5270b57cec5SDimitry Andric     "dependents",
5280b57cec5SDimitry Andric     cl::desc("In conjunection with -type-index and -id-index, dumps the entire "
5290b57cec5SDimitry Andric              "dependency graph for the specified index instead of "
5300b57cec5SDimitry Andric              "just the single record with the specified index"),
5310b57cec5SDimitry Andric     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric // SYMBOL OPTIONS
5340b57cec5SDimitry Andric cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
5350b57cec5SDimitry Andric                           cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5360b57cec5SDimitry Andric cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
5370b57cec5SDimitry Andric                                cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5380b57cec5SDimitry Andric cl::list<std::string> DumpGlobalNames(
5390b57cec5SDimitry Andric     "global-name",
5400b57cec5SDimitry Andric     cl::desc(
5410b57cec5SDimitry Andric         "With -globals, only dump globals whose name matches the given value"),
54281ad6265SDimitry Andric     cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5430b57cec5SDimitry Andric cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
5440b57cec5SDimitry Andric                           cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5450b57cec5SDimitry Andric cl::opt<bool> DumpPublicExtras("public-extras",
5460b57cec5SDimitry Andric                                cl::desc("dump Publics hashes and address maps"),
5470b57cec5SDimitry Andric                                cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5480b57cec5SDimitry Andric cl::opt<bool>
5490b57cec5SDimitry Andric     DumpGSIRecords("gsi-records",
5500b57cec5SDimitry Andric                    cl::desc("dump public / global common record stream"),
5510b57cec5SDimitry Andric                    cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5520b57cec5SDimitry Andric cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
5530b57cec5SDimitry Andric                           cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric cl::opt<bool>
5560b57cec5SDimitry Andric     DumpSymRecordBytes("sym-data",
5570b57cec5SDimitry Andric                        cl::desc("dump CodeView symbol record raw bytes"),
5580b57cec5SDimitry Andric                        cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
5610b57cec5SDimitry Andric                       cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
5620b57cec5SDimitry Andric 
56381ad6265SDimitry Andric cl::opt<uint32_t> DumpSymbolOffset(
56481ad6265SDimitry Andric     "symbol-offset", cl::Optional,
56581ad6265SDimitry Andric     cl::desc("only dump symbol record with the specified symbol offset"),
56681ad6265SDimitry Andric     cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
56781ad6265SDimitry Andric cl::opt<bool> DumpParents("show-parents",
56881ad6265SDimitry Andric                           cl::desc("dump the symbols record's all parents."),
56981ad6265SDimitry Andric                           cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
57081ad6265SDimitry Andric cl::opt<uint32_t>
57181ad6265SDimitry Andric     DumpParentDepth("parent-recurse-depth", cl::Optional, cl::init(-1U),
57281ad6265SDimitry Andric                     cl::desc("only recurse to a depth of N when displaying "
57381ad6265SDimitry Andric                              "parents of a symbol record."),
57481ad6265SDimitry Andric                     cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
57581ad6265SDimitry Andric cl::opt<bool> DumpChildren("show-children",
57681ad6265SDimitry Andric                            cl::desc("dump the symbols record's all children."),
57781ad6265SDimitry Andric                            cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
57881ad6265SDimitry Andric cl::opt<uint32_t>
57981ad6265SDimitry Andric     DumpChildrenDepth("children-recurse-depth", cl::Optional, cl::init(-1U),
58081ad6265SDimitry Andric                       cl::desc("only recurse to a depth of N when displaying "
58181ad6265SDimitry Andric                                "children of a symbol record."),
58281ad6265SDimitry Andric                       cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
58381ad6265SDimitry Andric 
5840b57cec5SDimitry Andric // MODULE & FILE OPTIONS
5850b57cec5SDimitry Andric cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
5860b57cec5SDimitry Andric                           cl::cat(FileOptions), cl::sub(DumpSubcommand));
5870b57cec5SDimitry Andric cl::opt<bool> DumpModuleFiles(
5880b57cec5SDimitry Andric     "files",
5890b57cec5SDimitry Andric     cl::desc("Dump the source files that contribute to each module's."),
5900b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(DumpSubcommand));
5910b57cec5SDimitry Andric cl::opt<bool> DumpLines(
5920b57cec5SDimitry Andric     "l",
5930b57cec5SDimitry Andric     cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
5940b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(DumpSubcommand));
5950b57cec5SDimitry Andric cl::opt<bool> DumpInlineeLines(
5960b57cec5SDimitry Andric     "il",
5970b57cec5SDimitry Andric     cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
5980b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(DumpSubcommand));
5990b57cec5SDimitry Andric cl::opt<bool> DumpXmi(
6000b57cec5SDimitry Andric     "xmi",
6010b57cec5SDimitry Andric     cl::desc(
6020b57cec5SDimitry Andric         "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
6030b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(DumpSubcommand));
6040b57cec5SDimitry Andric cl::opt<bool> DumpXme(
6050b57cec5SDimitry Andric     "xme",
6060b57cec5SDimitry Andric     cl::desc(
6070b57cec5SDimitry Andric         "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
6080b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(DumpSubcommand));
6090b57cec5SDimitry Andric cl::opt<uint32_t> DumpModi("modi", cl::Optional,
6100b57cec5SDimitry Andric                            cl::desc("For all options that iterate over "
6110b57cec5SDimitry Andric                                     "modules, limit to the specified module"),
6120b57cec5SDimitry Andric                            cl::cat(FileOptions), cl::sub(DumpSubcommand));
6130b57cec5SDimitry Andric cl::opt<bool> JustMyCode("jmc", cl::Optional,
6140b57cec5SDimitry Andric                          cl::desc("For all options that iterate over modules, "
6150b57cec5SDimitry Andric                                   "ignore modules from system libraries"),
6160b57cec5SDimitry Andric                          cl::cat(FileOptions), cl::sub(DumpSubcommand));
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric // MISCELLANEOUS OPTIONS
6190b57cec5SDimitry Andric cl::opt<bool> DumpNamedStreams("named-streams",
6200b57cec5SDimitry Andric                                cl::desc("dump PDB named stream table"),
6210b57cec5SDimitry Andric                                cl::cat(MiscOptions), cl::sub(DumpSubcommand));
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
6240b57cec5SDimitry Andric                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
6250b57cec5SDimitry Andric cl::opt<bool> DumpStringTableDetails("string-table-details",
6260b57cec5SDimitry Andric                                      cl::desc("dump PDB String Table Details"),
6270b57cec5SDimitry Andric                                      cl::cat(MiscOptions),
6280b57cec5SDimitry Andric                                      cl::sub(DumpSubcommand));
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric cl::opt<bool> DumpSectionContribs("section-contribs",
6310b57cec5SDimitry Andric                                   cl::desc("dump section contributions"),
6320b57cec5SDimitry Andric                                   cl::cat(MiscOptions),
6330b57cec5SDimitry Andric                                   cl::sub(DumpSubcommand));
6340b57cec5SDimitry Andric cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
6350b57cec5SDimitry Andric                              cl::cat(MiscOptions), cl::sub(DumpSubcommand));
6360b57cec5SDimitry Andric cl::opt<bool> DumpSectionHeaders("section-headers",
6370b57cec5SDimitry Andric                                  cl::desc("Dump image section headers"),
6380b57cec5SDimitry Andric                                  cl::cat(MiscOptions), cl::sub(DumpSubcommand));
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
6410b57cec5SDimitry Andric                      cl::cat(MiscOptions), cl::sub(DumpSubcommand));
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional,
6440b57cec5SDimitry Andric                                      cl::desc("<input PDB files>"),
6450b57cec5SDimitry Andric                                      cl::OneOrMore, cl::sub(DumpSubcommand));
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric namespace yaml2pdb {
6490b57cec5SDimitry Andric cl::opt<std::string>
6500b57cec5SDimitry Andric     YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
6510b57cec5SDimitry Andric                       cl::sub(YamlToPdbSubcommand));
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric cl::opt<std::string> InputFilename(cl::Positional,
6540b57cec5SDimitry Andric                                    cl::desc("<input YAML file>"), cl::Required,
6550b57cec5SDimitry Andric                                    cl::sub(YamlToPdbSubcommand));
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric namespace pdb2yaml {
6590b57cec5SDimitry Andric cl::opt<bool> All("all",
6600b57cec5SDimitry Andric                   cl::desc("Dump everything we know how to dump."),
6610b57cec5SDimitry Andric                   cl::sub(PdbToYamlSubcommand), cl::init(false));
6620b57cec5SDimitry Andric cl::opt<bool> NoFileHeaders("no-file-headers",
6630b57cec5SDimitry Andric                             cl::desc("Do not dump MSF file headers"),
6640b57cec5SDimitry Andric                             cl::sub(PdbToYamlSubcommand), cl::init(false));
6650b57cec5SDimitry Andric cl::opt<bool> Minimal("minimal",
6660b57cec5SDimitry Andric                       cl::desc("Don't write fields with default values"),
6670b57cec5SDimitry Andric                       cl::sub(PdbToYamlSubcommand), cl::init(false));
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric cl::opt<bool> StreamMetadata(
6700b57cec5SDimitry Andric     "stream-metadata",
6710b57cec5SDimitry Andric     cl::desc("Dump the number of streams and each stream's size"),
6720b57cec5SDimitry Andric     cl::sub(PdbToYamlSubcommand), cl::init(false));
6730b57cec5SDimitry Andric cl::opt<bool> StreamDirectory(
6740b57cec5SDimitry Andric     "stream-directory",
6750b57cec5SDimitry Andric     cl::desc("Dump each stream's block map (implies -stream-metadata)"),
6760b57cec5SDimitry Andric     cl::sub(PdbToYamlSubcommand), cl::init(false));
6770b57cec5SDimitry Andric cl::opt<bool> PdbStream("pdb-stream",
6780b57cec5SDimitry Andric                         cl::desc("Dump the PDB Stream (Stream 1)"),
6790b57cec5SDimitry Andric                         cl::sub(PdbToYamlSubcommand), cl::init(false));
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
6820b57cec5SDimitry Andric                           cl::sub(PdbToYamlSubcommand), cl::init(false));
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric cl::opt<bool> DbiStream("dbi-stream",
6850b57cec5SDimitry Andric                         cl::desc("Dump the DBI Stream Headers (Stream 2)"),
6860b57cec5SDimitry Andric                         cl::sub(PdbToYamlSubcommand), cl::init(false));
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric cl::opt<bool> TpiStream("tpi-stream",
6890b57cec5SDimitry Andric                         cl::desc("Dump the TPI Stream (Stream 3)"),
6900b57cec5SDimitry Andric                         cl::sub(PdbToYamlSubcommand), cl::init(false));
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric cl::opt<bool> IpiStream("ipi-stream",
6930b57cec5SDimitry Andric                         cl::desc("Dump the IPI Stream (Stream 5)"),
6940b57cec5SDimitry Andric                         cl::sub(PdbToYamlSubcommand), cl::init(false));
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric cl::opt<bool> PublicsStream("publics-stream",
6970b57cec5SDimitry Andric                             cl::desc("Dump the Publics Stream"),
6980b57cec5SDimitry Andric                             cl::sub(PdbToYamlSubcommand), cl::init(false));
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric // MODULE & FILE OPTIONS
7010b57cec5SDimitry Andric cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
7020b57cec5SDimitry Andric                           cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
7030b57cec5SDimitry Andric cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
7040b57cec5SDimitry Andric                               cl::cat(FileOptions),
7050b57cec5SDimitry Andric                               cl::sub(PdbToYamlSubcommand));
7060b57cec5SDimitry Andric cl::list<ModuleSubsection> DumpModuleSubsections(
70781ad6265SDimitry Andric     "subsections", cl::CommaSeparated,
7080b57cec5SDimitry Andric     cl::desc("dump subsections from each module's debug stream"), ChunkValues,
7090b57cec5SDimitry Andric     cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
7100b57cec5SDimitry Andric cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
7110b57cec5SDimitry Andric                              cl::cat(FileOptions),
7120b57cec5SDimitry Andric                              cl::sub(PdbToYamlSubcommand));
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric cl::list<std::string> InputFilename(cl::Positional,
7150b57cec5SDimitry Andric                                     cl::desc("<input PDB file>"), cl::Required,
7160b57cec5SDimitry Andric                                     cl::sub(PdbToYamlSubcommand));
7170b57cec5SDimitry Andric } // namespace pdb2yaml
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric namespace merge {
7200b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional,
7210b57cec5SDimitry Andric                                      cl::desc("<input PDB files>"),
7220b57cec5SDimitry Andric                                      cl::OneOrMore, cl::sub(MergeSubcommand));
7230b57cec5SDimitry Andric cl::opt<std::string>
7240b57cec5SDimitry Andric     PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
7250b57cec5SDimitry Andric                   cl::sub(MergeSubcommand));
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric namespace explain {
7290b57cec5SDimitry Andric cl::list<std::string> InputFilename(cl::Positional,
7300b57cec5SDimitry Andric                                     cl::desc("<input PDB file>"), cl::Required,
7310b57cec5SDimitry Andric                                     cl::sub(ExplainSubcommand));
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
7340b57cec5SDimitry Andric                            cl::sub(ExplainSubcommand), cl::OneOrMore);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric cl::opt<InputFileType> InputType(
7370b57cec5SDimitry Andric     "input-type", cl::desc("Specify how to interpret the input file"),
7380b57cec5SDimitry Andric     cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
7390b57cec5SDimitry Andric     cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
7400b57cec5SDimitry Andric                           "Treat input as a PDB file (default)"),
7410b57cec5SDimitry Andric                clEnumValN(InputFileType::PDBStream, "pdb-stream",
7420b57cec5SDimitry Andric                           "Treat input as raw contents of PDB stream"),
7430b57cec5SDimitry Andric                clEnumValN(InputFileType::DBIStream, "dbi-stream",
7440b57cec5SDimitry Andric                           "Treat input as raw contents of DBI stream"),
7450b57cec5SDimitry Andric                clEnumValN(InputFileType::Names, "names-stream",
7460b57cec5SDimitry Andric                           "Treat input as raw contents of /names named stream"),
7470b57cec5SDimitry Andric                clEnumValN(InputFileType::ModuleStream, "mod-stream",
7480b57cec5SDimitry Andric                           "Treat input as raw contents of a module stream")));
7490b57cec5SDimitry Andric } // namespace explain
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric namespace exportstream {
7520b57cec5SDimitry Andric cl::list<std::string> InputFilename(cl::Positional,
7530b57cec5SDimitry Andric                                     cl::desc("<input PDB file>"), cl::Required,
7540b57cec5SDimitry Andric                                     cl::sub(ExportSubcommand));
7550b57cec5SDimitry Andric cl::opt<std::string> OutputFile("out",
7560b57cec5SDimitry Andric                                 cl::desc("The file to write the stream to"),
7570b57cec5SDimitry Andric                                 cl::Required, cl::sub(ExportSubcommand));
7580b57cec5SDimitry Andric cl::opt<std::string>
7590b57cec5SDimitry Andric     Stream("stream", cl::Required,
7600b57cec5SDimitry Andric            cl::desc("The index or name of the stream whose contents to export"),
7610b57cec5SDimitry Andric            cl::sub(ExportSubcommand));
7620b57cec5SDimitry Andric cl::opt<bool> ForceName("name",
7630b57cec5SDimitry Andric                         cl::desc("Force the interpretation of -stream as a "
7640b57cec5SDimitry Andric                                  "string, even if it is a valid integer"),
7650b57cec5SDimitry Andric                         cl::sub(ExportSubcommand), cl::Optional,
7660b57cec5SDimitry Andric                         cl::init(false));
7670b57cec5SDimitry Andric } // namespace exportstream
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric static ExitOnError ExitOnErr;
7710b57cec5SDimitry Andric 
yamlToPdb(StringRef Path)7720b57cec5SDimitry Andric static void yamlToPdb(StringRef Path) {
7730b57cec5SDimitry Andric   BumpPtrAllocator Allocator;
7740b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
775fe6060f1SDimitry Andric       MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/false,
7760b57cec5SDimitry Andric                                    /*RequiresNullTerminator=*/false);
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   if (ErrorOrBuffer.getError()) {
7790b57cec5SDimitry Andric     ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   llvm::yaml::Input In(Buffer->getBuffer());
7850b57cec5SDimitry Andric   pdb::yaml::PdbObject YamlObj(Allocator);
7860b57cec5SDimitry Andric   In >> YamlObj;
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   PDBFileBuilder Builder(Allocator);
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric   uint32_t BlockSize = 4096;
79181ad6265SDimitry Andric   if (YamlObj.Headers)
7920b57cec5SDimitry Andric     BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
7930b57cec5SDimitry Andric   ExitOnErr(Builder.initialize(BlockSize));
7940b57cec5SDimitry Andric   // Add each of the reserved streams.  We ignore stream metadata in the
7950b57cec5SDimitry Andric   // yaml, because we will reconstruct our own view of the streams.  For
7960b57cec5SDimitry Andric   // example, the YAML may say that there were 20 streams in the original
7970b57cec5SDimitry Andric   // PDB, but maybe we only dump a subset of those 20 streams, so we will
7980b57cec5SDimitry Andric   // have fewer, and the ones we do have may end up with different indices
7990b57cec5SDimitry Andric   // than the ones in the original PDB.  So we just start with a clean slate.
8000b57cec5SDimitry Andric   for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
8010b57cec5SDimitry Andric     ExitOnErr(Builder.getMsfBuilder().addStream(0));
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   StringsAndChecksums Strings;
8040b57cec5SDimitry Andric   Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
8050b57cec5SDimitry Andric 
80681ad6265SDimitry Andric   if (YamlObj.StringTable) {
8070b57cec5SDimitry Andric     for (auto S : *YamlObj.StringTable)
8080b57cec5SDimitry Andric       Strings.strings()->insert(S);
8090b57cec5SDimitry Andric   }
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric   pdb::yaml::PdbInfoStream DefaultInfoStream;
8120b57cec5SDimitry Andric   pdb::yaml::PdbDbiStream DefaultDbiStream;
8130b57cec5SDimitry Andric   pdb::yaml::PdbTpiStream DefaultTpiStream;
8140b57cec5SDimitry Andric   pdb::yaml::PdbTpiStream DefaultIpiStream;
8150b57cec5SDimitry Andric 
81681ad6265SDimitry Andric   const auto &Info = YamlObj.PdbStream.value_or(DefaultInfoStream);
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   auto &InfoBuilder = Builder.getInfoBuilder();
8190b57cec5SDimitry Andric   InfoBuilder.setAge(Info.Age);
8200b57cec5SDimitry Andric   InfoBuilder.setGuid(Info.Guid);
8210b57cec5SDimitry Andric   InfoBuilder.setSignature(Info.Signature);
8220b57cec5SDimitry Andric   InfoBuilder.setVersion(Info.Version);
8230b57cec5SDimitry Andric   for (auto F : Info.Features)
8240b57cec5SDimitry Andric     InfoBuilder.addFeature(F);
8250b57cec5SDimitry Andric 
82681ad6265SDimitry Andric   const auto &Dbi = YamlObj.DbiStream.value_or(DefaultDbiStream);
8270b57cec5SDimitry Andric   auto &DbiBuilder = Builder.getDbiBuilder();
8280b57cec5SDimitry Andric   DbiBuilder.setAge(Dbi.Age);
8290b57cec5SDimitry Andric   DbiBuilder.setBuildNumber(Dbi.BuildNumber);
8300b57cec5SDimitry Andric   DbiBuilder.setFlags(Dbi.Flags);
8310b57cec5SDimitry Andric   DbiBuilder.setMachineType(Dbi.MachineType);
8320b57cec5SDimitry Andric   DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
8330b57cec5SDimitry Andric   DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
8340b57cec5SDimitry Andric   DbiBuilder.setVersionHeader(Dbi.VerHeader);
8350b57cec5SDimitry Andric   for (const auto &MI : Dbi.ModInfos) {
8360b57cec5SDimitry Andric     auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
8370b57cec5SDimitry Andric     ModiBuilder.setObjFileName(MI.Obj);
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric     for (auto S : MI.SourceFiles)
8400b57cec5SDimitry Andric       ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
84181ad6265SDimitry Andric     if (MI.Modi) {
8420b57cec5SDimitry Andric       const auto &ModiStream = *MI.Modi;
8435f757f3fSDimitry Andric       for (const auto &Symbol : ModiStream.Symbols) {
8440b57cec5SDimitry Andric         ModiBuilder.addSymbol(
8450b57cec5SDimitry Andric             Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric     }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric     // Each module has its own checksum subsection, so scan for it every time.
8500b57cec5SDimitry Andric     Strings.setChecksums(nullptr);
8510b57cec5SDimitry Andric     CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric     auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
8540b57cec5SDimitry Andric         Allocator, MI.Subsections, Strings));
8550b57cec5SDimitry Andric     for (auto &SS : CodeViewSubsections) {
8560b57cec5SDimitry Andric       ModiBuilder.addDebugSubsection(SS);
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   auto &TpiBuilder = Builder.getTpiBuilder();
86181ad6265SDimitry Andric   const auto &Tpi = YamlObj.TpiStream.value_or(DefaultTpiStream);
8620b57cec5SDimitry Andric   TpiBuilder.setVersionHeader(Tpi.Version);
8630b57cec5SDimitry Andric   AppendingTypeTableBuilder TS(Allocator);
8640b57cec5SDimitry Andric   for (const auto &R : Tpi.Records) {
8650b57cec5SDimitry Andric     CVType Type = R.toCodeViewRecord(TS);
866bdd1243dSDimitry Andric     TpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric 
86981ad6265SDimitry Andric   const auto &Ipi = YamlObj.IpiStream.value_or(DefaultIpiStream);
8700b57cec5SDimitry Andric   auto &IpiBuilder = Builder.getIpiBuilder();
8710b57cec5SDimitry Andric   IpiBuilder.setVersionHeader(Ipi.Version);
8720b57cec5SDimitry Andric   for (const auto &R : Ipi.Records) {
8730b57cec5SDimitry Andric     CVType Type = R.toCodeViewRecord(TS);
874bdd1243dSDimitry Andric     IpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
8750b57cec5SDimitry Andric   }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   Builder.getStringTableBuilder().setStrings(*Strings.strings());
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric   codeview::GUID IgnoredOutGuid;
8800b57cec5SDimitry Andric   ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric 
loadPDB(StringRef Path,std::unique_ptr<IPDBSession> & Session)8830b57cec5SDimitry Andric static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
8840b57cec5SDimitry Andric   ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric   NativeSession *NS = static_cast<NativeSession *>(Session.get());
8870b57cec5SDimitry Andric   return NS->getPDBFile();
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
pdb2Yaml(StringRef Path)8900b57cec5SDimitry Andric static void pdb2Yaml(StringRef Path) {
8910b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
8920b57cec5SDimitry Andric   auto &File = loadPDB(Path, Session);
8930b57cec5SDimitry Andric 
8948bcb0991SDimitry Andric   auto O = std::make_unique<YAMLOutputStyle>(File);
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   ExitOnErr(O->dump());
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric 
dumpRaw(StringRef Path)8990b57cec5SDimitry Andric static void dumpRaw(StringRef Path) {
9000b57cec5SDimitry Andric   InputFile IF = ExitOnErr(InputFile::open(Path));
9010b57cec5SDimitry Andric 
9028bcb0991SDimitry Andric   auto O = std::make_unique<DumpOutputStyle>(IF);
9030b57cec5SDimitry Andric   ExitOnErr(O->dump());
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric 
dumpBytes(StringRef Path)9060b57cec5SDimitry Andric static void dumpBytes(StringRef Path) {
9070b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
9080b57cec5SDimitry Andric   auto &File = loadPDB(Path, Session);
9090b57cec5SDimitry Andric 
9108bcb0991SDimitry Andric   auto O = std::make_unique<BytesOutputStyle>(File);
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   ExitOnErr(O->dump());
9130b57cec5SDimitry Andric }
9140b57cec5SDimitry Andric 
shouldDumpSymLevel(SymLevel Search)9150b57cec5SDimitry Andric bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
9160b57cec5SDimitry Andric   if (SymTypes.empty())
9170b57cec5SDimitry Andric     return true;
918e8d8bef9SDimitry Andric   if (llvm::is_contained(SymTypes, Search))
9190b57cec5SDimitry Andric     return true;
920e8d8bef9SDimitry Andric   if (llvm::is_contained(SymTypes, SymLevel::All))
9210b57cec5SDimitry Andric     return true;
9220b57cec5SDimitry Andric   return false;
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric 
getTypeLength(const PDBSymbolData & Symbol)9250b57cec5SDimitry Andric uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
9260b57cec5SDimitry Andric   auto SymbolType = Symbol.getType();
9270b57cec5SDimitry Andric   const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   return RawType.getLength();
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
compareFunctionSymbols(const std::unique_ptr<PDBSymbolFunc> & F1,const std::unique_ptr<PDBSymbolFunc> & F2)9320b57cec5SDimitry Andric bool opts::pretty::compareFunctionSymbols(
9330b57cec5SDimitry Andric     const std::unique_ptr<PDBSymbolFunc> &F1,
9340b57cec5SDimitry Andric     const std::unique_ptr<PDBSymbolFunc> &F2) {
9350b57cec5SDimitry Andric   assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric   if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
9380b57cec5SDimitry Andric     return F1->getName() < F2->getName();
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   // Note that we intentionally sort in descending order on length, since
9410b57cec5SDimitry Andric   // long functions are more interesting than short functions.
9420b57cec5SDimitry Andric   return F1->getLength() > F2->getLength();
9430b57cec5SDimitry Andric }
9440b57cec5SDimitry Andric 
compareDataSymbols(const std::unique_ptr<PDBSymbolData> & F1,const std::unique_ptr<PDBSymbolData> & F2)9450b57cec5SDimitry Andric bool opts::pretty::compareDataSymbols(
9460b57cec5SDimitry Andric     const std::unique_ptr<PDBSymbolData> &F1,
9470b57cec5SDimitry Andric     const std::unique_ptr<PDBSymbolData> &F2) {
9480b57cec5SDimitry Andric   assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric   if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
9510b57cec5SDimitry Andric     return F1->getName() < F2->getName();
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   // Note that we intentionally sort in descending order on length, since
9540b57cec5SDimitry Andric   // large types are more interesting than short ones.
9550b57cec5SDimitry Andric   return getTypeLength(*F1) > getTypeLength(*F2);
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric 
stringOr(std::string Str,std::string IfEmpty)9580b57cec5SDimitry Andric static std::string stringOr(std::string Str, std::string IfEmpty) {
9590b57cec5SDimitry Andric   return (Str.empty()) ? IfEmpty : Str;
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric 
dumpInjectedSources(LinePrinter & Printer,IPDBSession & Session)9620b57cec5SDimitry Andric static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
9630b57cec5SDimitry Andric   auto Sources = Session.getInjectedSources();
9640b57cec5SDimitry Andric   if (!Sources || !Sources->getChildCount()) {
9650b57cec5SDimitry Andric     Printer.printLine("There are no injected sources.");
9660b57cec5SDimitry Andric     return;
9670b57cec5SDimitry Andric   }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   while (auto IS = Sources->getNext()) {
9700b57cec5SDimitry Andric     Printer.NewLine();
9710b57cec5SDimitry Andric     std::string File = stringOr(IS->getFileName(), "<null>");
9720b57cec5SDimitry Andric     uint64_t Size = IS->getCodeByteSize();
9730b57cec5SDimitry Andric     std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
9740b57cec5SDimitry Andric     std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
9750b57cec5SDimitry Andric     uint32_t CRC = IS->getCrc32();
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Path).get() << File;
9780b57cec5SDimitry Andric     Printer << " (";
9790b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
9800b57cec5SDimitry Andric     Printer << " bytes): ";
9810b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
9820b57cec5SDimitry Andric     Printer << "=";
9830b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
9840b57cec5SDimitry Andric     Printer << ", ";
9850b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
9860b57cec5SDimitry Andric     Printer << "=";
9870b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
9880b57cec5SDimitry Andric     Printer << ", ";
9890b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
9900b57cec5SDimitry Andric     Printer << "=";
9910b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
9920b57cec5SDimitry Andric     Printer << ", ";
9930b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
9940b57cec5SDimitry Andric     Printer << "=";
9950b57cec5SDimitry Andric     dumpPDBSourceCompression(
9960b57cec5SDimitry Andric         WithColor(Printer, PDB_ColorItem::LiteralValue).get(),
9970b57cec5SDimitry Andric         IS->getCompression());
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric     if (!opts::pretty::ShowInjectedSourceContent)
10000b57cec5SDimitry Andric       continue;
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric     // Set the indent level to 0 when printing file content.
10030b57cec5SDimitry Andric     int Indent = Printer.getIndentLevel();
10040b57cec5SDimitry Andric     Printer.Unindent(Indent);
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric     if (IS->getCompression() == PDB_SourceCompression::None)
10070b57cec5SDimitry Andric       Printer.printLine(IS->getCode());
10080b57cec5SDimitry Andric     else
10090b57cec5SDimitry Andric       Printer.formatBinary("Compressed data",
10100b57cec5SDimitry Andric                            arrayRefFromStringRef(IS->getCode()),
10110b57cec5SDimitry Andric                            /*StartOffset=*/0);
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric     // Re-indent back to the original level.
10140b57cec5SDimitry Andric     Printer.Indent(Indent);
10150b57cec5SDimitry Andric   }
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric template <typename OuterT, typename ChildT>
diaDumpChildren(PDBSymbol & Outer,PdbSymbolIdField Ids,PdbSymbolIdField Recurse)10190b57cec5SDimitry Andric void diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,
10200b57cec5SDimitry Andric                      PdbSymbolIdField Recurse) {
10210b57cec5SDimitry Andric   OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);
10220b57cec5SDimitry Andric   if (!ConcreteOuter)
10230b57cec5SDimitry Andric     return;
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric   auto Children = ConcreteOuter->template findAllChildren<ChildT>();
10260b57cec5SDimitry Andric   while (auto Child = Children->getNext()) {
10270b57cec5SDimitry Andric     outs() << "  {";
10280b57cec5SDimitry Andric     Child->defaultDump(outs(), 4, Ids, Recurse);
10290b57cec5SDimitry Andric     outs() << "\n  }\n";
10300b57cec5SDimitry Andric   }
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
dumpDia(StringRef Path)10330b57cec5SDimitry Andric static void dumpDia(StringRef Path) {
10340b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   const auto ReaderType =
10370b57cec5SDimitry Andric       opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
10380b57cec5SDimitry Andric   ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   auto GlobalScope = Session->getGlobalScope();
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric   std::vector<PDB_SymType> SymTypes;
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   if (opts::diadump::Compilands)
10450b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::Compiland);
10460b57cec5SDimitry Andric   if (opts::diadump::Enums)
10470b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::Enum);
10480b57cec5SDimitry Andric   if (opts::diadump::Pointers)
10490b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::PointerType);
10500b57cec5SDimitry Andric   if (opts::diadump::UDTs)
10510b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::UDT);
10520b57cec5SDimitry Andric   if (opts::diadump::Funcsigs)
10530b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::FunctionSig);
10540b57cec5SDimitry Andric   if (opts::diadump::Arrays)
10550b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::ArrayType);
10560b57cec5SDimitry Andric   if (opts::diadump::VTShapes)
10570b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::VTableShape);
10580b57cec5SDimitry Andric   if (opts::diadump::Typedefs)
10590b57cec5SDimitry Andric     SymTypes.push_back(PDB_SymType::Typedef);
10600b57cec5SDimitry Andric   PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
10610b57cec5SDimitry Andric                                                       : PdbSymbolIdField::All;
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   PdbSymbolIdField Recurse = PdbSymbolIdField::None;
10640b57cec5SDimitry Andric   if (opts::diadump::Recurse)
10650b57cec5SDimitry Andric     Recurse = PdbSymbolIdField::All;
10660b57cec5SDimitry Andric   if (!opts::diadump::ShowClassHierarchy)
10670b57cec5SDimitry Andric     Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric   for (PDB_SymType ST : SymTypes) {
10700b57cec5SDimitry Andric     auto Children = GlobalScope->findAllChildren(ST);
10710b57cec5SDimitry Andric     while (auto Child = Children->getNext()) {
10720b57cec5SDimitry Andric       outs() << "{";
10730b57cec5SDimitry Andric       Child->defaultDump(outs(), 2, Ids, Recurse);
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric       diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);
10760b57cec5SDimitry Andric       outs() << "\n}\n";
10770b57cec5SDimitry Andric     }
10780b57cec5SDimitry Andric   }
10790b57cec5SDimitry Andric }
10800b57cec5SDimitry Andric 
dumpPretty(StringRef Path)10810b57cec5SDimitry Andric static void dumpPretty(StringRef Path) {
10820b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   const auto ReaderType =
10850b57cec5SDimitry Andric       opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
10860b57cec5SDimitry Andric   ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   if (opts::pretty::LoadAddress)
10890b57cec5SDimitry Andric     Session->setLoadAddress(opts::pretty::LoadAddress);
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   auto &Stream = outs();
10920b57cec5SDimitry Andric   const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
10930b57cec5SDimitry Andric                             ? Stream.has_colors()
10940b57cec5SDimitry Andric                             : opts::pretty::ColorOutput == cl::BOU_TRUE;
109581ad6265SDimitry Andric   LinePrinter Printer(2, UseColor, Stream, opts::Filters);
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   auto GlobalScope(Session->getGlobalScope());
10980b57cec5SDimitry Andric   if (!GlobalScope)
10990b57cec5SDimitry Andric     return;
11000b57cec5SDimitry Andric   std::string FileName(GlobalScope->getSymbolsFileName());
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
11030b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
11040b57cec5SDimitry Andric   Printer.Indent();
11050b57cec5SDimitry Andric   uint64_t FileSize = 0;
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   Printer.NewLine();
11080b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
11090b57cec5SDimitry Andric   if (!sys::fs::file_size(FileName, FileSize)) {
11100b57cec5SDimitry Andric     Printer << ": " << FileSize << " bytes";
11110b57cec5SDimitry Andric   } else {
11120b57cec5SDimitry Andric     Printer << ": (Unable to obtain file size)";
11130b57cec5SDimitry Andric   }
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   Printer.NewLine();
11160b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
11170b57cec5SDimitry Andric   Printer << ": " << GlobalScope->getGuid();
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   Printer.NewLine();
11200b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
11210b57cec5SDimitry Andric   Printer << ": " << GlobalScope->getAge();
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   Printer.NewLine();
11240b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
11250b57cec5SDimitry Andric   Printer << ": ";
11260b57cec5SDimitry Andric   if (GlobalScope->hasCTypes())
11270b57cec5SDimitry Andric     outs() << "HasCTypes ";
11280b57cec5SDimitry Andric   if (GlobalScope->hasPrivateSymbols())
11290b57cec5SDimitry Andric     outs() << "HasPrivateSymbols ";
11300b57cec5SDimitry Andric   Printer.Unindent();
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   if (!opts::pretty::WithName.empty()) {
11330b57cec5SDimitry Andric     Printer.NewLine();
11340b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get()
11350b57cec5SDimitry Andric         << "---SYMBOLS & TYPES BY NAME---";
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     for (StringRef Name : opts::pretty::WithName) {
11380b57cec5SDimitry Andric       auto Symbols = GlobalScope->findChildren(
11390b57cec5SDimitry Andric           PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
11400b57cec5SDimitry Andric       if (!Symbols || Symbols->getChildCount() == 0) {
11410b57cec5SDimitry Andric         Printer.formatLine("[not found] - {0}", Name);
11420b57cec5SDimitry Andric         continue;
11430b57cec5SDimitry Andric       }
11440b57cec5SDimitry Andric       Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
11450b57cec5SDimitry Andric                          Name);
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric       AutoIndent Indent(Printer);
11480b57cec5SDimitry Andric       Printer.NewLine();
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric       while (auto Symbol = Symbols->getNext()) {
11510b57cec5SDimitry Andric         switch (Symbol->getSymTag()) {
11520b57cec5SDimitry Andric         case PDB_SymType::Typedef: {
11530b57cec5SDimitry Andric           TypedefDumper TD(Printer);
11540b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolTypeTypedef> T =
11550b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
11560b57cec5SDimitry Andric           TD.start(*T);
11570b57cec5SDimitry Andric           break;
11580b57cec5SDimitry Andric         }
11590b57cec5SDimitry Andric         case PDB_SymType::Enum: {
11600b57cec5SDimitry Andric           EnumDumper ED(Printer);
11610b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolTypeEnum> E =
11620b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
11630b57cec5SDimitry Andric           ED.start(*E);
11640b57cec5SDimitry Andric           break;
11650b57cec5SDimitry Andric         }
11660b57cec5SDimitry Andric         case PDB_SymType::UDT: {
11670b57cec5SDimitry Andric           ClassDefinitionDumper CD(Printer);
11680b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolTypeUDT> C =
11690b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
11700b57cec5SDimitry Andric           CD.start(*C);
11710b57cec5SDimitry Andric           break;
11720b57cec5SDimitry Andric         }
11730b57cec5SDimitry Andric         case PDB_SymType::BaseClass:
11740b57cec5SDimitry Andric         case PDB_SymType::Friend: {
11750b57cec5SDimitry Andric           TypeDumper TD(Printer);
11760b57cec5SDimitry Andric           Symbol->dump(TD);
11770b57cec5SDimitry Andric           break;
11780b57cec5SDimitry Andric         }
11790b57cec5SDimitry Andric         case PDB_SymType::Function: {
11800b57cec5SDimitry Andric           FunctionDumper FD(Printer);
11810b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolFunc> F =
11820b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
11830b57cec5SDimitry Andric           FD.start(*F, FunctionDumper::PointerType::None);
11840b57cec5SDimitry Andric           break;
11850b57cec5SDimitry Andric         }
11860b57cec5SDimitry Andric         case PDB_SymType::Data: {
11870b57cec5SDimitry Andric           VariableDumper VD(Printer);
11880b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolData> D =
11890b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
11900b57cec5SDimitry Andric           VD.start(*D);
11910b57cec5SDimitry Andric           break;
11920b57cec5SDimitry Andric         }
11930b57cec5SDimitry Andric         case PDB_SymType::PublicSymbol: {
11940b57cec5SDimitry Andric           ExternalSymbolDumper ED(Printer);
11950b57cec5SDimitry Andric           std::unique_ptr<PDBSymbolPublicSymbol> PS =
11960b57cec5SDimitry Andric               llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
11970b57cec5SDimitry Andric           ED.dump(*PS);
11980b57cec5SDimitry Andric           break;
11990b57cec5SDimitry Andric         }
12000b57cec5SDimitry Andric         default:
12010b57cec5SDimitry Andric           llvm_unreachable("Unexpected symbol tag!");
12020b57cec5SDimitry Andric         }
12030b57cec5SDimitry Andric       }
12040b57cec5SDimitry Andric     }
12050b57cec5SDimitry Andric     llvm::outs().flush();
12060b57cec5SDimitry Andric   }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric   if (opts::pretty::Compilands) {
12090b57cec5SDimitry Andric     Printer.NewLine();
12100b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get()
12110b57cec5SDimitry Andric         << "---COMPILANDS---";
12120b57cec5SDimitry Andric     auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric     if (Compilands) {
12150b57cec5SDimitry Andric       Printer.Indent();
12160b57cec5SDimitry Andric       CompilandDumper Dumper(Printer);
12170b57cec5SDimitry Andric       CompilandDumpFlags options = CompilandDumper::Flags::None;
12180b57cec5SDimitry Andric       if (opts::pretty::Lines)
12190b57cec5SDimitry Andric         options = options | CompilandDumper::Flags::Lines;
12200b57cec5SDimitry Andric       while (auto Compiland = Compilands->getNext())
12210b57cec5SDimitry Andric         Dumper.start(*Compiland, options);
12220b57cec5SDimitry Andric       Printer.Unindent();
12230b57cec5SDimitry Andric     }
12240b57cec5SDimitry Andric   }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
12270b57cec5SDimitry Andric       opts::pretty::Funcsigs || opts::pretty::Pointers ||
12280b57cec5SDimitry Andric       opts::pretty::Arrays || opts::pretty::VTShapes) {
12290b57cec5SDimitry Andric     Printer.NewLine();
12300b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
12310b57cec5SDimitry Andric     Printer.Indent();
12320b57cec5SDimitry Andric     TypeDumper Dumper(Printer);
12330b57cec5SDimitry Andric     Dumper.start(*GlobalScope);
12340b57cec5SDimitry Andric     Printer.Unindent();
12350b57cec5SDimitry Andric   }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   if (opts::pretty::Symbols) {
12380b57cec5SDimitry Andric     Printer.NewLine();
12390b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
12400b57cec5SDimitry Andric     if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
12410b57cec5SDimitry Andric       Printer.Indent();
12420b57cec5SDimitry Andric       CompilandDumper Dumper(Printer);
12430b57cec5SDimitry Andric       while (auto Compiland = Compilands->getNext())
12440b57cec5SDimitry Andric         Dumper.start(*Compiland, true);
12450b57cec5SDimitry Andric       Printer.Unindent();
12460b57cec5SDimitry Andric     }
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   if (opts::pretty::Globals) {
12500b57cec5SDimitry Andric     Printer.NewLine();
12510b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
12520b57cec5SDimitry Andric     Printer.Indent();
12530b57cec5SDimitry Andric     if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
12540b57cec5SDimitry Andric       if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
12550b57cec5SDimitry Andric         FunctionDumper Dumper(Printer);
12560b57cec5SDimitry Andric         if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
12570b57cec5SDimitry Andric           while (auto Function = Functions->getNext()) {
12580b57cec5SDimitry Andric             Printer.NewLine();
12590b57cec5SDimitry Andric             Dumper.start(*Function, FunctionDumper::PointerType::None);
12600b57cec5SDimitry Andric           }
12610b57cec5SDimitry Andric         } else {
12620b57cec5SDimitry Andric           std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
12630b57cec5SDimitry Andric           while (auto Func = Functions->getNext())
12640b57cec5SDimitry Andric             Funcs.push_back(std::move(Func));
12650b57cec5SDimitry Andric           llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);
12660b57cec5SDimitry Andric           for (const auto &Func : Funcs) {
12670b57cec5SDimitry Andric             Printer.NewLine();
12680b57cec5SDimitry Andric             Dumper.start(*Func, FunctionDumper::PointerType::None);
12690b57cec5SDimitry Andric           }
12700b57cec5SDimitry Andric         }
12710b57cec5SDimitry Andric       }
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric     if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
12740b57cec5SDimitry Andric       if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
12750b57cec5SDimitry Andric         VariableDumper Dumper(Printer);
12760b57cec5SDimitry Andric         if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
12770b57cec5SDimitry Andric           while (auto Var = Vars->getNext())
12780b57cec5SDimitry Andric             Dumper.start(*Var);
12790b57cec5SDimitry Andric         } else {
12800b57cec5SDimitry Andric           std::vector<std::unique_ptr<PDBSymbolData>> Datas;
12810b57cec5SDimitry Andric           while (auto Var = Vars->getNext())
12820b57cec5SDimitry Andric             Datas.push_back(std::move(Var));
12830b57cec5SDimitry Andric           llvm::sort(Datas, opts::pretty::compareDataSymbols);
12840b57cec5SDimitry Andric           for (const auto &Var : Datas)
12850b57cec5SDimitry Andric             Dumper.start(*Var);
12860b57cec5SDimitry Andric         }
12870b57cec5SDimitry Andric       }
12880b57cec5SDimitry Andric     }
12890b57cec5SDimitry Andric     if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
12900b57cec5SDimitry Andric       if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
12910b57cec5SDimitry Andric         CompilandDumper Dumper(Printer);
12920b57cec5SDimitry Andric         while (auto Thunk = Thunks->getNext())
12930b57cec5SDimitry Andric           Dumper.dump(*Thunk);
12940b57cec5SDimitry Andric       }
12950b57cec5SDimitry Andric     }
12960b57cec5SDimitry Andric     Printer.Unindent();
12970b57cec5SDimitry Andric   }
12980b57cec5SDimitry Andric   if (opts::pretty::Externals) {
12990b57cec5SDimitry Andric     Printer.NewLine();
13000b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
13010b57cec5SDimitry Andric     Printer.Indent();
13020b57cec5SDimitry Andric     ExternalSymbolDumper Dumper(Printer);
13030b57cec5SDimitry Andric     Dumper.start(*GlobalScope);
13040b57cec5SDimitry Andric   }
13050b57cec5SDimitry Andric   if (opts::pretty::Lines) {
13060b57cec5SDimitry Andric     Printer.NewLine();
13070b57cec5SDimitry Andric   }
13080b57cec5SDimitry Andric   if (opts::pretty::InjectedSources) {
13090b57cec5SDimitry Andric     Printer.NewLine();
13100b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::SectionHeader).get()
13110b57cec5SDimitry Andric         << "---INJECTED SOURCES---";
13120b57cec5SDimitry Andric     AutoIndent Indent1(Printer);
13130b57cec5SDimitry Andric     dumpInjectedSources(Printer, *Session);
13140b57cec5SDimitry Andric   }
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   Printer.NewLine();
13170b57cec5SDimitry Andric   outs().flush();
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric 
mergePdbs()13200b57cec5SDimitry Andric static void mergePdbs() {
13210b57cec5SDimitry Andric   BumpPtrAllocator Allocator;
13220b57cec5SDimitry Andric   MergingTypeTableBuilder MergedTpi(Allocator);
13230b57cec5SDimitry Andric   MergingTypeTableBuilder MergedIpi(Allocator);
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric   // Create a Tpi and Ipi type table with all types from all input files.
13260b57cec5SDimitry Andric   for (const auto &Path : opts::merge::InputFilenames) {
13270b57cec5SDimitry Andric     std::unique_ptr<IPDBSession> Session;
13280b57cec5SDimitry Andric     auto &File = loadPDB(Path, Session);
13290b57cec5SDimitry Andric     SmallVector<TypeIndex, 128> TypeMap;
13300b57cec5SDimitry Andric     SmallVector<TypeIndex, 128> IdMap;
13310b57cec5SDimitry Andric     if (File.hasPDBTpiStream()) {
13320b57cec5SDimitry Andric       auto &Tpi = ExitOnErr(File.getPDBTpiStream());
13330b57cec5SDimitry Andric       ExitOnErr(
13340b57cec5SDimitry Andric           codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));
13350b57cec5SDimitry Andric     }
13360b57cec5SDimitry Andric     if (File.hasPDBIpiStream()) {
13370b57cec5SDimitry Andric       auto &Ipi = ExitOnErr(File.getPDBIpiStream());
13380b57cec5SDimitry Andric       ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
13390b57cec5SDimitry Andric                                          Ipi.typeArray()));
13400b57cec5SDimitry Andric     }
13410b57cec5SDimitry Andric   }
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric   // Then write the PDB.
13440b57cec5SDimitry Andric   PDBFileBuilder Builder(Allocator);
13450b57cec5SDimitry Andric   ExitOnErr(Builder.initialize(4096));
13460b57cec5SDimitry Andric   // Add each of the reserved streams.  We might not put any data in them,
13470b57cec5SDimitry Andric   // but at least they have to be present.
13480b57cec5SDimitry Andric   for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
13490b57cec5SDimitry Andric     ExitOnErr(Builder.getMsfBuilder().addStream(0));
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   auto &DestTpi = Builder.getTpiBuilder();
13520b57cec5SDimitry Andric   auto &DestIpi = Builder.getIpiBuilder();
13530b57cec5SDimitry Andric   MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
1354bdd1243dSDimitry Andric     DestTpi.addTypeRecord(Type.RecordData, std::nullopt);
13550b57cec5SDimitry Andric   });
13560b57cec5SDimitry Andric   MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
1357bdd1243dSDimitry Andric     DestIpi.addTypeRecord(Type.RecordData, std::nullopt);
13580b57cec5SDimitry Andric   });
13590b57cec5SDimitry Andric   Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   SmallString<64> OutFile(opts::merge::PdbOutputFile);
13620b57cec5SDimitry Andric   if (OutFile.empty()) {
13630b57cec5SDimitry Andric     OutFile = opts::merge::InputFilenames[0];
13640b57cec5SDimitry Andric     llvm::sys::path::replace_extension(OutFile, "merged.pdb");
13650b57cec5SDimitry Andric   }
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric   codeview::GUID IgnoredOutGuid;
13680b57cec5SDimitry Andric   ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
13690b57cec5SDimitry Andric }
13700b57cec5SDimitry Andric 
explain()13710b57cec5SDimitry Andric static void explain() {
13720b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
13730b57cec5SDimitry Andric   InputFile IF =
13740b57cec5SDimitry Andric       ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric   for (uint64_t Off : opts::explain::Offsets) {
13778bcb0991SDimitry Andric     auto O = std::make_unique<ExplainOutputStyle>(IF, Off);
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric     ExitOnErr(O->dump());
13800b57cec5SDimitry Andric   }
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric 
exportStream()13830b57cec5SDimitry Andric static void exportStream() {
13840b57cec5SDimitry Andric   std::unique_ptr<IPDBSession> Session;
13850b57cec5SDimitry Andric   PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
13860b57cec5SDimitry Andric 
13870b57cec5SDimitry Andric   std::unique_ptr<MappedBlockStream> SourceStream;
13880b57cec5SDimitry Andric   uint32_t Index = 0;
13890b57cec5SDimitry Andric   bool Success = false;
13900b57cec5SDimitry Andric   std::string OutFileName = opts::exportstream::OutputFile;
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric   if (!opts::exportstream::ForceName) {
13930b57cec5SDimitry Andric     // First try to parse it as an integer, if it fails fall back to treating it
13940b57cec5SDimitry Andric     // as a named stream.
13950b57cec5SDimitry Andric     if (to_integer(opts::exportstream::Stream, Index)) {
13960b57cec5SDimitry Andric       if (Index >= File.getNumStreams()) {
13970b57cec5SDimitry Andric         errs() << "Error: " << Index << " is not a valid stream index.\n";
13980b57cec5SDimitry Andric         exit(1);
13990b57cec5SDimitry Andric       }
14000b57cec5SDimitry Andric       Success = true;
14010b57cec5SDimitry Andric       outs() << "Dumping contents of stream index " << Index << " to file "
14020b57cec5SDimitry Andric              << OutFileName << ".\n";
14030b57cec5SDimitry Andric     }
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   if (!Success) {
14070b57cec5SDimitry Andric     InfoStream &IS = cantFail(File.getPDBInfoStream());
14080b57cec5SDimitry Andric     Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
14090b57cec5SDimitry Andric     outs() << "Dumping contents of stream '" << opts::exportstream::Stream
14100b57cec5SDimitry Andric            << "' (index " << Index << ") to file " << OutFileName << ".\n";
14110b57cec5SDimitry Andric   }
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric   SourceStream = File.createIndexedStream(Index);
14140b57cec5SDimitry Andric   auto OutFile = ExitOnErr(
14150b57cec5SDimitry Andric       FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
14165f757f3fSDimitry Andric   FileBufferByteStream DestStream(std::move(OutFile), llvm::endianness::little);
14170b57cec5SDimitry Andric   BinaryStreamWriter Writer(DestStream);
14180b57cec5SDimitry Andric   ExitOnErr(Writer.writeStreamRef(*SourceStream));
14190b57cec5SDimitry Andric   ExitOnErr(DestStream.commit());
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric 
parseRange(StringRef Str,std::optional<opts::bytes::NumberRange> & Parsed)14220b57cec5SDimitry Andric static bool parseRange(StringRef Str,
1423bdd1243dSDimitry Andric                        std::optional<opts::bytes::NumberRange> &Parsed) {
14240b57cec5SDimitry Andric   if (Str.empty())
14250b57cec5SDimitry Andric     return true;
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric   llvm::Regex R("^([^-]+)(-([^-]+))?$");
14280b57cec5SDimitry Andric   llvm::SmallVector<llvm::StringRef, 2> Matches;
14290b57cec5SDimitry Andric   if (!R.match(Str, &Matches))
14300b57cec5SDimitry Andric     return false;
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric   Parsed.emplace();
14330b57cec5SDimitry Andric   if (!to_integer(Matches[1], Parsed->Min))
14340b57cec5SDimitry Andric     return false;
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric   if (!Matches[3].empty()) {
14370b57cec5SDimitry Andric     Parsed->Max.emplace();
14380b57cec5SDimitry Andric     if (!to_integer(Matches[3], *Parsed->Max))
14390b57cec5SDimitry Andric       return false;
14400b57cec5SDimitry Andric   }
14410b57cec5SDimitry Andric   return true;
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> & Chunks)14440b57cec5SDimitry Andric static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
14450b57cec5SDimitry Andric   // If this list contains "All" plus some other stuff, remove the other stuff
14460b57cec5SDimitry Andric   // and just keep "All" in the list.
14470b57cec5SDimitry Andric   if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))
14480b57cec5SDimitry Andric     return;
14490b57cec5SDimitry Andric   Chunks.reset();
14500b57cec5SDimitry Andric   Chunks.push_back(opts::ModuleSubsection::All);
14510b57cec5SDimitry Andric }
14520b57cec5SDimitry Andric 
main(int Argc,const char ** Argv)14530b57cec5SDimitry Andric int main(int Argc, const char **Argv) {
14540b57cec5SDimitry Andric   InitLLVM X(Argc, Argv);
14550b57cec5SDimitry Andric   ExitOnErr.setBanner("llvm-pdbutil: ");
14560b57cec5SDimitry Andric 
1457fe6060f1SDimitry Andric   cl::HideUnrelatedOptions(
1458fe6060f1SDimitry Andric       {&opts::TypeCategory, &opts::FilterCategory, &opts::OtherOptions});
14590b57cec5SDimitry Andric   cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric   if (opts::BytesSubcommand) {
14620b57cec5SDimitry Andric     if (!parseRange(opts::bytes::DumpBlockRangeOpt,
14630b57cec5SDimitry Andric                     opts::bytes::DumpBlockRange)) {
14640b57cec5SDimitry Andric       errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
14650b57cec5SDimitry Andric              << "' invalid format.\n";
14660b57cec5SDimitry Andric       errs().flush();
14670b57cec5SDimitry Andric       exit(1);
14680b57cec5SDimitry Andric     }
14690b57cec5SDimitry Andric     if (!parseRange(opts::bytes::DumpByteRangeOpt,
14700b57cec5SDimitry Andric                     opts::bytes::DumpByteRange)) {
14710b57cec5SDimitry Andric       errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
14720b57cec5SDimitry Andric              << "' invalid format.\n";
14730b57cec5SDimitry Andric       errs().flush();
14740b57cec5SDimitry Andric       exit(1);
14750b57cec5SDimitry Andric     }
14760b57cec5SDimitry Andric   }
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric   if (opts::DumpSubcommand) {
14790b57cec5SDimitry Andric     if (opts::dump::RawAll) {
14800b57cec5SDimitry Andric       opts::dump::DumpGlobals = true;
14810b57cec5SDimitry Andric       opts::dump::DumpFpo = true;
14820b57cec5SDimitry Andric       opts::dump::DumpInlineeLines = true;
14830b57cec5SDimitry Andric       opts::dump::DumpIds = true;
14840b57cec5SDimitry Andric       opts::dump::DumpIdExtras = true;
14850b57cec5SDimitry Andric       opts::dump::DumpLines = true;
14860b57cec5SDimitry Andric       opts::dump::DumpModules = true;
14870b57cec5SDimitry Andric       opts::dump::DumpModuleFiles = true;
14880b57cec5SDimitry Andric       opts::dump::DumpPublics = true;
14890b57cec5SDimitry Andric       opts::dump::DumpSectionContribs = true;
14900b57cec5SDimitry Andric       opts::dump::DumpSectionHeaders = true;
14910b57cec5SDimitry Andric       opts::dump::DumpSectionMap = true;
14920b57cec5SDimitry Andric       opts::dump::DumpStreams = true;
14930b57cec5SDimitry Andric       opts::dump::DumpStreamBlocks = true;
14940b57cec5SDimitry Andric       opts::dump::DumpStringTable = true;
14950b57cec5SDimitry Andric       opts::dump::DumpStringTableDetails = true;
14960b57cec5SDimitry Andric       opts::dump::DumpSummary = true;
14970b57cec5SDimitry Andric       opts::dump::DumpSymbols = true;
14980b57cec5SDimitry Andric       opts::dump::DumpSymbolStats = true;
14990b57cec5SDimitry Andric       opts::dump::DumpTypes = true;
15000b57cec5SDimitry Andric       opts::dump::DumpTypeExtras = true;
15010b57cec5SDimitry Andric       opts::dump::DumpUdtStats = true;
15020b57cec5SDimitry Andric       opts::dump::DumpXme = true;
15030b57cec5SDimitry Andric       opts::dump::DumpXmi = true;
15040b57cec5SDimitry Andric     }
15050b57cec5SDimitry Andric   }
15060b57cec5SDimitry Andric   if (opts::PdbToYamlSubcommand) {
15070b57cec5SDimitry Andric     if (opts::pdb2yaml::All) {
15080b57cec5SDimitry Andric       opts::pdb2yaml::StreamMetadata = true;
15090b57cec5SDimitry Andric       opts::pdb2yaml::StreamDirectory = true;
15100b57cec5SDimitry Andric       opts::pdb2yaml::PdbStream = true;
15110b57cec5SDimitry Andric       opts::pdb2yaml::StringTable = true;
15120b57cec5SDimitry Andric       opts::pdb2yaml::DbiStream = true;
15130b57cec5SDimitry Andric       opts::pdb2yaml::TpiStream = true;
15140b57cec5SDimitry Andric       opts::pdb2yaml::IpiStream = true;
15150b57cec5SDimitry Andric       opts::pdb2yaml::PublicsStream = true;
15160b57cec5SDimitry Andric       opts::pdb2yaml::DumpModules = true;
15170b57cec5SDimitry Andric       opts::pdb2yaml::DumpModuleFiles = true;
15180b57cec5SDimitry Andric       opts::pdb2yaml::DumpModuleSyms = true;
15190b57cec5SDimitry Andric       opts::pdb2yaml::DumpModuleSubsections.push_back(
15200b57cec5SDimitry Andric           opts::ModuleSubsection::All);
15210b57cec5SDimitry Andric     }
15220b57cec5SDimitry Andric     simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric     if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
15250b57cec5SDimitry Andric       opts::pdb2yaml::DumpModules = true;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric     if (opts::pdb2yaml::DumpModules)
15280b57cec5SDimitry Andric       opts::pdb2yaml::DbiStream = true;
15290b57cec5SDimitry Andric   }
15300b57cec5SDimitry Andric 
15310b57cec5SDimitry Andric   llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
15320b57cec5SDimitry Andric 
153381ad6265SDimitry Andric   // Initialize the filters for LinePrinter.
153481ad6265SDimitry Andric   auto propagate = [&](auto &Target, auto &Reference) {
153581ad6265SDimitry Andric     for (std::string &Option : Reference)
153681ad6265SDimitry Andric       Target.push_back(Option);
153781ad6265SDimitry Andric   };
153881ad6265SDimitry Andric 
153981ad6265SDimitry Andric   propagate(opts::Filters.ExcludeTypes, opts::pretty::ExcludeTypes);
154081ad6265SDimitry Andric   propagate(opts::Filters.ExcludeTypes, opts::pretty::ExcludeTypes);
154181ad6265SDimitry Andric   propagate(opts::Filters.ExcludeSymbols, opts::pretty::ExcludeSymbols);
154281ad6265SDimitry Andric   propagate(opts::Filters.ExcludeCompilands, opts::pretty::ExcludeCompilands);
154381ad6265SDimitry Andric   propagate(opts::Filters.IncludeTypes, opts::pretty::IncludeTypes);
154481ad6265SDimitry Andric   propagate(opts::Filters.IncludeSymbols, opts::pretty::IncludeSymbols);
154581ad6265SDimitry Andric   propagate(opts::Filters.IncludeCompilands, opts::pretty::IncludeCompilands);
154681ad6265SDimitry Andric   opts::Filters.PaddingThreshold = opts::pretty::PaddingThreshold;
154781ad6265SDimitry Andric   opts::Filters.SizeThreshold = opts::pretty::SizeThreshold;
154881ad6265SDimitry Andric   opts::Filters.JustMyCode = opts::dump::JustMyCode;
154981ad6265SDimitry Andric   if (opts::dump::DumpModi.getNumOccurrences() > 0) {
155081ad6265SDimitry Andric     if (opts::dump::DumpModi.getNumOccurrences() != 1) {
155181ad6265SDimitry Andric       errs() << "argument '-modi' specified more than once.\n";
155281ad6265SDimitry Andric       errs().flush();
155381ad6265SDimitry Andric       exit(1);
155481ad6265SDimitry Andric     }
155581ad6265SDimitry Andric     opts::Filters.DumpModi = opts::dump::DumpModi;
155681ad6265SDimitry Andric   }
155781ad6265SDimitry Andric   if (opts::dump::DumpSymbolOffset) {
155881ad6265SDimitry Andric     if (opts::dump::DumpModi.getNumOccurrences() != 1) {
155981ad6265SDimitry Andric       errs()
156081ad6265SDimitry Andric           << "need to specify argument '-modi' when using '-symbol-offset'.\n";
156181ad6265SDimitry Andric       errs().flush();
156281ad6265SDimitry Andric       exit(1);
156381ad6265SDimitry Andric     }
156481ad6265SDimitry Andric     opts::Filters.SymbolOffset = opts::dump::DumpSymbolOffset;
156581ad6265SDimitry Andric     if (opts::dump::DumpParents)
156681ad6265SDimitry Andric       opts::Filters.ParentRecurseDepth = opts::dump::DumpParentDepth;
156781ad6265SDimitry Andric     if (opts::dump::DumpChildren)
156881ad6265SDimitry Andric       opts::Filters.ChildrenRecurseDepth = opts::dump::DumpChildrenDepth;
156981ad6265SDimitry Andric   }
157081ad6265SDimitry Andric 
15710b57cec5SDimitry Andric   if (opts::PdbToYamlSubcommand) {
15720b57cec5SDimitry Andric     pdb2Yaml(opts::pdb2yaml::InputFilename.front());
15730b57cec5SDimitry Andric   } else if (opts::YamlToPdbSubcommand) {
15740b57cec5SDimitry Andric     if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
15750b57cec5SDimitry Andric       SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
15760b57cec5SDimitry Andric       sys::path::replace_extension(OutputFilename, ".pdb");
1577*7a6dacacSDimitry Andric       opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename);
15780b57cec5SDimitry Andric     }
15790b57cec5SDimitry Andric     yamlToPdb(opts::yaml2pdb::InputFilename);
15800b57cec5SDimitry Andric   } else if (opts::DiaDumpSubcommand) {
15810b57cec5SDimitry Andric     llvm::for_each(opts::diadump::InputFilenames, dumpDia);
15820b57cec5SDimitry Andric   } else if (opts::PrettySubcommand) {
15830b57cec5SDimitry Andric     if (opts::pretty::Lines)
15840b57cec5SDimitry Andric       opts::pretty::Compilands = true;
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric     if (opts::pretty::All) {
15870b57cec5SDimitry Andric       opts::pretty::Compilands = true;
15880b57cec5SDimitry Andric       opts::pretty::Symbols = true;
15890b57cec5SDimitry Andric       opts::pretty::Globals = true;
15900b57cec5SDimitry Andric       opts::pretty::Types = true;
15910b57cec5SDimitry Andric       opts::pretty::Externals = true;
15920b57cec5SDimitry Andric       opts::pretty::Lines = true;
15930b57cec5SDimitry Andric     }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric     if (opts::pretty::Types) {
15960b57cec5SDimitry Andric       opts::pretty::Classes = true;
15970b57cec5SDimitry Andric       opts::pretty::Typedefs = true;
15980b57cec5SDimitry Andric       opts::pretty::Enums = true;
15990b57cec5SDimitry Andric       opts::pretty::Pointers = true;
16000b57cec5SDimitry Andric       opts::pretty::Funcsigs = true;
16010b57cec5SDimitry Andric     }
16020b57cec5SDimitry Andric 
16030b57cec5SDimitry Andric     // When adding filters for excluded compilands and types, we need to
16040b57cec5SDimitry Andric     // remember that these are regexes.  So special characters such as * and \
16050b57cec5SDimitry Andric     // need to be escaped in the regex.  In the case of a literal \, this means
16060b57cec5SDimitry Andric     // it needs to be escaped again in the C++.  So matching a single \ in the
16070b57cec5SDimitry Andric     // input requires 4 \es in the C++.
16080b57cec5SDimitry Andric     if (opts::pretty::ExcludeCompilerGenerated) {
160981ad6265SDimitry Andric       opts::Filters.ExcludeTypes.push_back("__vc_attributes");
161081ad6265SDimitry Andric       opts::Filters.ExcludeCompilands.push_back("\\* Linker \\*");
16110b57cec5SDimitry Andric     }
16120b57cec5SDimitry Andric     if (opts::pretty::ExcludeSystemLibraries) {
161381ad6265SDimitry Andric       opts::Filters.ExcludeCompilands.push_back(
16140b57cec5SDimitry Andric           "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
161581ad6265SDimitry Andric       opts::Filters.ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
161681ad6265SDimitry Andric       opts::Filters.ExcludeCompilands.push_back(
16170b57cec5SDimitry Andric           "d:\\\\th.obj.x86fre\\\\minkernel");
16180b57cec5SDimitry Andric     }
16190b57cec5SDimitry Andric     llvm::for_each(opts::pretty::InputFilenames, dumpPretty);
16200b57cec5SDimitry Andric   } else if (opts::DumpSubcommand) {
16210b57cec5SDimitry Andric     llvm::for_each(opts::dump::InputFilenames, dumpRaw);
16220b57cec5SDimitry Andric   } else if (opts::BytesSubcommand) {
16230b57cec5SDimitry Andric     llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
16240b57cec5SDimitry Andric   } else if (opts::MergeSubcommand) {
16250b57cec5SDimitry Andric     if (opts::merge::InputFilenames.size() < 2) {
16260b57cec5SDimitry Andric       errs() << "merge subcommand requires at least 2 input files.\n";
16270b57cec5SDimitry Andric       exit(1);
16280b57cec5SDimitry Andric     }
16290b57cec5SDimitry Andric     mergePdbs();
16300b57cec5SDimitry Andric   } else if (opts::ExplainSubcommand) {
16310b57cec5SDimitry Andric     explain();
16320b57cec5SDimitry Andric   } else if (opts::ExportSubcommand) {
16330b57cec5SDimitry Andric     exportStream();
16340b57cec5SDimitry Andric   }
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric   outs().flush();
16370b57cec5SDimitry Andric   return 0;
16380b57cec5SDimitry Andric }
1639