1319780Sdim//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
2319780Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6319780Sdim//
7319780Sdim//===----------------------------------------------------------------------===//
8319780Sdim//
9319780Sdim// Dumps debug information present in PDB files.
10319780Sdim//
11319780Sdim//===----------------------------------------------------------------------===//
12319780Sdim
13319780Sdim#include "llvm-pdbutil.h"
14319780Sdim
15320397Sdim#include "BytesOutputStyle.h"
16320397Sdim#include "DumpOutputStyle.h"
17341825Sdim#include "ExplainOutputStyle.h"
18327952Sdim#include "InputFile.h"
19319780Sdim#include "LinePrinter.h"
20319780Sdim#include "OutputStyle.h"
21341825Sdim#include "PrettyClassDefinitionDumper.h"
22319780Sdim#include "PrettyCompilandDumper.h"
23341825Sdim#include "PrettyEnumDumper.h"
24319780Sdim#include "PrettyExternalSymbolDumper.h"
25319780Sdim#include "PrettyFunctionDumper.h"
26319780Sdim#include "PrettyTypeDumper.h"
27341825Sdim#include "PrettyTypedefDumper.h"
28319780Sdim#include "PrettyVariableDumper.h"
29319780Sdim#include "YAMLOutputStyle.h"
30319780Sdim
31319780Sdim#include "llvm/ADT/ArrayRef.h"
32319780Sdim#include "llvm/ADT/BitVector.h"
33319780Sdim#include "llvm/ADT/DenseMap.h"
34319780Sdim#include "llvm/ADT/STLExtras.h"
35319780Sdim#include "llvm/ADT/StringExtras.h"
36327952Sdim#include "llvm/BinaryFormat/Magic.h"
37319780Sdim#include "llvm/Config/config.h"
38327952Sdim#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
39319780Sdim#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
40319780Sdim#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
41319780Sdim#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
42319780Sdim#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
43327952Sdim#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
44320041Sdim#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
45319780Sdim#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
46319780Sdim#include "llvm/DebugInfo/MSF/MSFBuilder.h"
47319780Sdim#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
48341825Sdim#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
49319780Sdim#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
50319780Sdim#include "llvm/DebugInfo/PDB/IPDBSession.h"
51319780Sdim#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
52319780Sdim#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
53341825Sdim#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
54319780Sdim#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
55319780Sdim#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
56319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
57319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
58319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
59319780Sdim#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
60319780Sdim#include "llvm/DebugInfo/PDB/Native/RawError.h"
61319780Sdim#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
62319780Sdim#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
63319780Sdim#include "llvm/DebugInfo/PDB/PDB.h"
64319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
65319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
66319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
67319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
68341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
69319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
70341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
71344779Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
72344779Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
73341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
74341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
75319780Sdim#include "llvm/Support/BinaryByteStream.h"
76319780Sdim#include "llvm/Support/COM.h"
77319780Sdim#include "llvm/Support/CommandLine.h"
78319780Sdim#include "llvm/Support/ConvertUTF.h"
79319780Sdim#include "llvm/Support/FileOutputBuffer.h"
80319780Sdim#include "llvm/Support/FileSystem.h"
81319780Sdim#include "llvm/Support/Format.h"
82341825Sdim#include "llvm/Support/InitLLVM.h"
83327952Sdim#include "llvm/Support/LineIterator.h"
84319780Sdim#include "llvm/Support/ManagedStatic.h"
85319780Sdim#include "llvm/Support/MemoryBuffer.h"
86319780Sdim#include "llvm/Support/Path.h"
87319780Sdim#include "llvm/Support/PrettyStackTrace.h"
88319780Sdim#include "llvm/Support/Process.h"
89319780Sdim#include "llvm/Support/Regex.h"
90319780Sdim#include "llvm/Support/ScopedPrinter.h"
91319780Sdim#include "llvm/Support/Signals.h"
92319780Sdim#include "llvm/Support/raw_ostream.h"
93319780Sdim
94319780Sdimusing namespace llvm;
95319780Sdimusing namespace llvm::codeview;
96319780Sdimusing namespace llvm::msf;
97319780Sdimusing namespace llvm::pdb;
98319780Sdim
99319780Sdimnamespace opts {
100319780Sdim
101320397Sdimcl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info");
102320397Sdimcl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file");
103320397Sdim
104344779Sdimcl::SubCommand DiaDumpSubcommand("diadump",
105344779Sdim                                 "Dump debug information using a DIA-like API");
106344779Sdim
107319780Sdimcl::SubCommand
108319780Sdim    PrettySubcommand("pretty",
109319780Sdim                     "Dump semantic information about types and symbols");
110319780Sdim
111319780Sdimcl::SubCommand
112319780Sdim    YamlToPdbSubcommand("yaml2pdb",
113319780Sdim                        "Generate a PDB file from a YAML description");
114319780Sdimcl::SubCommand
115319780Sdim    PdbToYamlSubcommand("pdb2yaml",
116319780Sdim                        "Generate a detailed YAML description of a PDB File");
117319780Sdim
118319780Sdimcl::SubCommand MergeSubcommand("merge",
119319780Sdim                               "Merge multiple PDBs into a single PDB");
120319780Sdim
121341825Sdimcl::SubCommand ExplainSubcommand("explain",
122341825Sdim                                 "Explain the meaning of a file offset");
123341825Sdim
124341825Sdimcl::SubCommand ExportSubcommand("export",
125341825Sdim                                "Write binary data from a stream to a file");
126341825Sdim
127319780Sdimcl::OptionCategory TypeCategory("Symbol Type Options");
128319780Sdimcl::OptionCategory FilterCategory("Filtering and Sorting Options");
129319780Sdimcl::OptionCategory OtherOptions("Other Options");
130319780Sdim
131320397Sdimcl::ValuesClass ChunkValues = cl::values(
132320397Sdim    clEnumValN(ModuleSubsection::CrossScopeExports, "cme",
133320397Sdim               "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
134320397Sdim    clEnumValN(ModuleSubsection::CrossScopeImports, "cmi",
135320397Sdim               "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
136320397Sdim    clEnumValN(ModuleSubsection::FileChecksums, "fc",
137320397Sdim               "File checksums (DEBUG_S_CHECKSUMS subsection)"),
138320397Sdim    clEnumValN(ModuleSubsection::InlineeLines, "ilines",
139320397Sdim               "Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
140320397Sdim    clEnumValN(ModuleSubsection::Lines, "lines",
141320397Sdim               "Lines (DEBUG_S_LINES subsection)"),
142320397Sdim    clEnumValN(ModuleSubsection::StringTable, "strings",
143320397Sdim               "String Table (DEBUG_S_STRINGTABLE subsection) (not "
144320397Sdim               "typically present in PDB file)"),
145320397Sdim    clEnumValN(ModuleSubsection::FrameData, "frames",
146320397Sdim               "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
147320397Sdim    clEnumValN(ModuleSubsection::Symbols, "symbols",
148320397Sdim               "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
149320397Sdim               "present in PDB file)"),
150320397Sdim    clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas",
151320397Sdim               "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"),
152320397Sdim    clEnumValN(ModuleSubsection::Unknown, "unknown",
153320397Sdim               "Any subsection not covered by another option"),
154320397Sdim    clEnumValN(ModuleSubsection::All, "all", "All known subsections"));
155320397Sdim
156344779Sdimnamespace diadump {
157344779Sdimcl::list<std::string> InputFilenames(cl::Positional,
158344779Sdim                                     cl::desc("<input PDB files>"),
159344779Sdim                                     cl::OneOrMore, cl::sub(DiaDumpSubcommand));
160344779Sdim
161344779Sdimcl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
162344779Sdim                     cl::sub(DiaDumpSubcommand));
163344779Sdim
164344779Sdimstatic cl::opt<bool>
165344779Sdim    ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"),
166344779Sdim                       cl::sub(DiaDumpSubcommand));
167344779Sdimstatic cl::opt<bool> NoSymIndexIds(
168344779Sdim    "no-ids",
169344779Sdim    cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"),
170344779Sdim    cl::sub(DiaDumpSubcommand));
171344779Sdim
172344779Sdimstatic cl::opt<bool>
173344779Sdim    Recurse("recurse",
174344779Sdim            cl::desc("When dumping a SymIndexId, dump the full details of the "
175344779Sdim                     "corresponding record"),
176344779Sdim            cl::sub(DiaDumpSubcommand));
177344779Sdim
178344779Sdimstatic cl::opt<bool> Enums("enums", cl::desc("Dump enum types"),
179344779Sdim                           cl::sub(DiaDumpSubcommand));
180344779Sdimstatic cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),
181344779Sdim                              cl::sub(DiaDumpSubcommand));
182344779Sdimstatic cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),
183344779Sdim                          cl::sub(DiaDumpSubcommand));
184344779Sdimstatic cl::opt<bool> Compilands("compilands",
185344779Sdim                                cl::desc("Dump compiland information"),
186344779Sdim                                cl::sub(DiaDumpSubcommand));
187344779Sdimstatic cl::opt<bool> Funcsigs("funcsigs",
188344779Sdim                              cl::desc("Dump function signature information"),
189344779Sdim                              cl::sub(DiaDumpSubcommand));
190344779Sdimstatic cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"),
191344779Sdim                            cl::sub(DiaDumpSubcommand));
192344779Sdimstatic cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"),
193344779Sdim                              cl::sub(DiaDumpSubcommand));
194344779Sdimstatic cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"),
195344779Sdim                              cl::sub(DiaDumpSubcommand));
196344779Sdim} // namespace diadump
197344779Sdim
198319780Sdimnamespace pretty {
199319780Sdimcl::list<std::string> InputFilenames(cl::Positional,
200319780Sdim                                     cl::desc("<input PDB files>"),
201319780Sdim                                     cl::OneOrMore, cl::sub(PrettySubcommand));
202319780Sdim
203341825Sdimcl::opt<bool> InjectedSources("injected-sources",
204341825Sdim                              cl::desc("Display injected sources"),
205341825Sdim                              cl::cat(OtherOptions), cl::sub(PrettySubcommand));
206341825Sdimcl::opt<bool> ShowInjectedSourceContent(
207341825Sdim    "injected-source-content",
208341825Sdim    cl::desc("When displaying an injected source, display the file content"),
209341825Sdim    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
210341825Sdim
211341825Sdimcl::list<std::string> WithName(
212341825Sdim    "with-name",
213341825Sdim    cl::desc("Display any symbol or type with the specified exact name"),
214341825Sdim    cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
215341825Sdim
216319780Sdimcl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
217319780Sdim                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
218319780Sdimcl::opt<bool> Symbols("module-syms",
219319780Sdim                      cl::desc("Display symbols for each compiland"),
220319780Sdim                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
221319780Sdimcl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
222319780Sdim                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
223319780Sdimcl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
224319780Sdim                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
225319780Sdimcl::list<SymLevel> SymTypes(
226319780Sdim    "sym-types", cl::desc("Type of symbols to dump (default all)"),
227319780Sdim    cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore,
228319780Sdim    cl::values(
229319780Sdim        clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),
230319780Sdim        clEnumValN(SymLevel::Data, "data", "Display data symbols"),
231319780Sdim        clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),
232319780Sdim        clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));
233319780Sdim
234319780Sdimcl::opt<bool>
235319780Sdim    Types("types",
236319780Sdim          cl::desc("Display all types (implies -classes, -enums, -typedefs)"),
237319780Sdim          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
238319780Sdimcl::opt<bool> Classes("classes", cl::desc("Display class types"),
239319780Sdim                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
240319780Sdimcl::opt<bool> Enums("enums", cl::desc("Display enum types"),
241319780Sdim                    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
242319780Sdimcl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
243319780Sdim                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
244344779Sdimcl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"),
245344779Sdim                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
246344779Sdimcl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"),
247344779Sdim                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
248344779Sdimcl::opt<bool> Arrays("arrays", cl::desc("Display arrays"),
249344779Sdim                     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
250344779Sdimcl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"),
251344779Sdim                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
252344779Sdim
253319780Sdimcl::opt<SymbolSortMode> SymbolOrder(
254319780Sdim    "symbol-order", cl::desc("symbol sort order"),
255319780Sdim    cl::init(SymbolSortMode::None),
256319780Sdim    cl::values(clEnumValN(SymbolSortMode::None, "none",
257319780Sdim                          "Undefined / no particular sort order"),
258319780Sdim               clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),
259319780Sdim               clEnumValN(SymbolSortMode::Size, "size",
260319780Sdim                          "Sort symbols by size")),
261319780Sdim    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
262319780Sdim
263319780Sdimcl::opt<ClassSortMode> ClassOrder(
264319780Sdim    "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
265319780Sdim    cl::values(
266319780Sdim        clEnumValN(ClassSortMode::None, "none",
267319780Sdim                   "Undefined / no particular sort order"),
268319780Sdim        clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
269319780Sdim        clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
270319780Sdim        clEnumValN(ClassSortMode::Padding, "padding",
271319780Sdim                   "Sort classes by amount of padding"),
272319780Sdim        clEnumValN(ClassSortMode::PaddingPct, "padding-pct",
273319780Sdim                   "Sort classes by percentage of space consumed by padding"),
274319780Sdim        clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",
275319780Sdim                   "Sort classes by amount of immediate padding"),
276319780Sdim        clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",
277319780Sdim                   "Sort classes by percentage of space consumed by immediate "
278319780Sdim                   "padding")),
279319780Sdim    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
280319780Sdim
281319780Sdimcl::opt<ClassDefinitionFormat> ClassFormat(
282319780Sdim    "class-definitions", cl::desc("Class definition format"),
283319780Sdim    cl::init(ClassDefinitionFormat::All),
284319780Sdim    cl::values(
285319780Sdim        clEnumValN(ClassDefinitionFormat::All, "all",
286319780Sdim                   "Display all class members including data, constants, "
287319780Sdim                   "typedefs, functions, etc"),
288319780Sdim        clEnumValN(ClassDefinitionFormat::Layout, "layout",
289319780Sdim                   "Only display members that contribute to class size."),
290319780Sdim        clEnumValN(ClassDefinitionFormat::None, "none",
291319780Sdim                   "Don't display class definitions")),
292319780Sdim    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
293319780Sdimcl::opt<uint32_t> ClassRecursionDepth(
294319780Sdim    "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),
295319780Sdim    cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));
296319780Sdim
297319780Sdimcl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
298319780Sdim                    cl::sub(PrettySubcommand));
299319780Sdimcl::opt<bool>
300319780Sdim    All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
301319780Sdim        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
302319780Sdim
303319780Sdimcl::opt<uint64_t> LoadAddress(
304319780Sdim    "load-address",
305319780Sdim    cl::desc("Assume the module is loaded at the specified address"),
306319780Sdim    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
307319780Sdimcl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
308319780Sdim                     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
309319780Sdimcl::opt<cl::boolOrDefault>
310319780Sdim    ColorOutput("color-output",
311319780Sdim                cl::desc("Override use of color (default = isatty)"),
312319780Sdim                cl::cat(OtherOptions), cl::sub(PrettySubcommand));
313319780Sdimcl::list<std::string> ExcludeTypes(
314319780Sdim    "exclude-types", cl::desc("Exclude types by regular expression"),
315319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
316319780Sdimcl::list<std::string> ExcludeSymbols(
317319780Sdim    "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
318319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
319319780Sdimcl::list<std::string> ExcludeCompilands(
320319780Sdim    "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
321319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
322319780Sdim
323319780Sdimcl::list<std::string> IncludeTypes(
324319780Sdim    "include-types",
325319780Sdim    cl::desc("Include only types which match a regular expression"),
326319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
327319780Sdimcl::list<std::string> IncludeSymbols(
328319780Sdim    "include-symbols",
329319780Sdim    cl::desc("Include only symbols which match a regular expression"),
330319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
331319780Sdimcl::list<std::string> IncludeCompilands(
332319780Sdim    "include-compilands",
333319780Sdim    cl::desc("Include only compilands those which match a regular expression"),
334319780Sdim    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
335319780Sdimcl::opt<uint32_t> SizeThreshold(
336319780Sdim    "min-type-size", cl::desc("Displays only those types which are greater "
337319780Sdim                              "than or equal to the specified size."),
338319780Sdim    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
339319780Sdimcl::opt<uint32_t> PaddingThreshold(
340319780Sdim    "min-class-padding", cl::desc("Displays only those classes which have at "
341319780Sdim                                  "least the specified amount of padding."),
342319780Sdim    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
343319780Sdimcl::opt<uint32_t> ImmediatePaddingThreshold(
344319780Sdim    "min-class-padding-imm",
345319780Sdim    cl::desc("Displays only those classes which have at least the specified "
346319780Sdim             "amount of immediate padding, ignoring padding internal to bases "
347319780Sdim             "and aggregates."),
348319780Sdim    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
349319780Sdim
350319780Sdimcl::opt<bool> ExcludeCompilerGenerated(
351319780Sdim    "no-compiler-generated",
352319780Sdim    cl::desc("Don't show compiler generated types and symbols"),
353319780Sdim    cl::cat(FilterCategory), cl::sub(PrettySubcommand));
354319780Sdimcl::opt<bool>
355319780Sdim    ExcludeSystemLibraries("no-system-libs",
356319780Sdim                           cl::desc("Don't show symbols from system libraries"),
357319780Sdim                           cl::cat(FilterCategory), cl::sub(PrettySubcommand));
358319780Sdim
359319780Sdimcl::opt<bool> NoEnumDefs("no-enum-definitions",
360319780Sdim                         cl::desc("Don't display full enum definitions"),
361319780Sdim                         cl::cat(FilterCategory), cl::sub(PrettySubcommand));
362319780Sdim}
363319780Sdim
364320041Sdimcl::OptionCategory FileOptions("Module & File Options");
365320041Sdim
366320397Sdimnamespace bytes {
367320397Sdimcl::OptionCategory MsfBytes("MSF File Options");
368320397Sdimcl::OptionCategory DbiBytes("Dbi Stream Options");
369320397Sdimcl::OptionCategory PdbBytes("PDB Stream Options");
370320397Sdimcl::OptionCategory Types("Type Options");
371320397Sdimcl::OptionCategory ModuleCategory("Module Options");
372319780Sdim
373320397Sdimllvm::Optional<NumberRange> DumpBlockRange;
374320397Sdimllvm::Optional<NumberRange> DumpByteRange;
375320397Sdim
376320397Sdimcl::opt<std::string> DumpBlockRangeOpt(
377320397Sdim    "block-range", cl::value_desc("start[-end]"),
378320397Sdim    cl::desc("Dump binary data from specified range of blocks."),
379320397Sdim    cl::sub(BytesSubcommand), cl::cat(MsfBytes));
380320397Sdim
381320397Sdimcl::opt<std::string>
382320397Sdim    DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
383320397Sdim                     cl::desc("Dump binary data from specified range of bytes"),
384320397Sdim                     cl::sub(BytesSubcommand), cl::cat(MsfBytes));
385320397Sdim
386320397Sdimcl::list<std::string>
387320397Sdim    DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
388320397Sdim                   cl::desc("Dump binary data from specified streams.  Format "
389320397Sdim                            "is SN[:Start][@Size]"),
390320397Sdim                   cl::sub(BytesSubcommand), cl::cat(MsfBytes));
391320397Sdim
392320397Sdimcl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),
393320397Sdim                      cl::sub(BytesSubcommand), cl::cat(PdbBytes));
394327952Sdimcl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"),
395327952Sdim                  cl::sub(BytesSubcommand), cl::cat(MsfBytes));
396320397Sdim
397320397Sdimcl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"),
398320397Sdim                                   cl::sub(BytesSubcommand), cl::cat(DbiBytes));
399320397Sdimcl::opt<bool> SectionMap("sm", cl::desc("Dump section map"),
400320397Sdim                         cl::sub(BytesSubcommand), cl::cat(DbiBytes));
401320397Sdimcl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"),
402320397Sdim                          cl::sub(BytesSubcommand), cl::cat(DbiBytes));
403320397Sdimcl::opt<bool> FileInfo("files", cl::desc("Dump source file info"),
404320397Sdim                       cl::sub(BytesSubcommand), cl::cat(DbiBytes));
405320397Sdimcl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),
406320397Sdim                            cl::sub(BytesSubcommand), cl::cat(DbiBytes));
407320397Sdimcl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),
408320397Sdim                     cl::sub(BytesSubcommand), cl::cat(DbiBytes));
409320397Sdim
410320397Sdimcl::list<uint32_t>
411320397Sdim    TypeIndex("type",
412320397Sdim              cl::desc("Dump the type record with the given type index"),
413320397Sdim              cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
414320397Sdim              cl::cat(TypeCategory));
415320397Sdimcl::list<uint32_t>
416320397Sdim    IdIndex("id", cl::desc("Dump the id record with the given type index"),
417320397Sdim            cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
418320397Sdim            cl::cat(TypeCategory));
419320397Sdim
420320397Sdimcl::opt<uint32_t> ModuleIndex(
421320397Sdim    "mod",
422320397Sdim    cl::desc(
423320397Sdim        "Limit options in the Modules category to the specified module index"),
424320397Sdim    cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
425320397Sdimcl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"),
426320397Sdim                         cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
427320397Sdimcl::opt<bool> ModuleC11("c11-chunks", cl::Hidden,
428320397Sdim                        cl::desc("Dump C11 CodeView debug chunks"),
429320397Sdim                        cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
430320397Sdimcl::opt<bool> ModuleC13("chunks",
431320397Sdim                        cl::desc("Dump C13 CodeView debug chunk subsection"),
432320397Sdim                        cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
433320397Sdimcl::opt<bool> SplitChunks(
434320397Sdim    "split-chunks",
435320397Sdim    cl::desc(
436320397Sdim        "When dumping debug chunks, show a different section for each chunk"),
437320397Sdim    cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
438320397Sdimcl::list<std::string> InputFilenames(cl::Positional,
439320397Sdim                                     cl::desc("<input PDB files>"),
440320397Sdim                                     cl::OneOrMore, cl::sub(BytesSubcommand));
441320397Sdim
442320397Sdim} // namespace bytes
443320397Sdim
444320397Sdimnamespace dump {
445320397Sdim
446319780Sdimcl::OptionCategory MsfOptions("MSF Container Options");
447319780Sdimcl::OptionCategory TypeOptions("Type Record Options");
448319780Sdimcl::OptionCategory SymbolOptions("Symbol Options");
449319780Sdimcl::OptionCategory MiscOptions("Miscellaneous Options");
450319780Sdim
451319780Sdim// MSF OPTIONS
452320041Sdimcl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),
453320397Sdim                          cl::cat(MsfOptions), cl::sub(DumpSubcommand));
454320041Sdimcl::opt<bool> DumpStreams("streams",
455320041Sdim                          cl::desc("dump summary of the PDB streams"),
456320397Sdim                          cl::cat(MsfOptions), cl::sub(DumpSubcommand));
457320397Sdimcl::opt<bool> DumpStreamBlocks(
458320397Sdim    "stream-blocks",
459320397Sdim    cl::desc("Add block information to the output of -streams"),
460320397Sdim    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
461327952Sdimcl::opt<bool> DumpSymbolStats(
462327952Sdim    "sym-stats",
463327952Sdim    cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),
464327952Sdim    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
465353358Sdimcl::opt<bool> DumpTypeStats(
466353358Sdim    "type-stats",
467353358Sdim    cl::desc("Dump a detailed breakdown of type usage/size"),
468353358Sdim    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
469327952Sdimcl::opt<bool> DumpUdtStats(
470327952Sdim    "udt-stats",
471327952Sdim    cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
472327952Sdim    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
473327952Sdim
474319780Sdim// TYPE OPTIONS
475320041Sdimcl::opt<bool> DumpTypes("types",
476320041Sdim                        cl::desc("dump CodeView type records from TPI stream"),
477320397Sdim                        cl::cat(TypeOptions), cl::sub(DumpSubcommand));
478320041Sdimcl::opt<bool> DumpTypeData(
479320041Sdim    "type-data",
480319780Sdim    cl::desc("dump CodeView type record raw bytes from TPI stream"),
481320397Sdim    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
482353358Sdimcl::opt<bool>
483353358Sdim    DumpTypeRefStats("type-ref-stats",
484353358Sdim                     cl::desc("dump statistics on the number and size of types "
485353358Sdim                              "transitively referenced by symbol records"),
486353358Sdim                     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
487320041Sdim
488320041Sdimcl::opt<bool> DumpTypeExtras("type-extras",
489320041Sdim                             cl::desc("dump type hashes and index offsets"),
490320397Sdim                             cl::cat(TypeOptions), cl::sub(DumpSubcommand));
491320041Sdim
492344779Sdimcl::opt<bool> DontResolveForwardRefs(
493344779Sdim    "dont-resolve-forward-refs",
494344779Sdim    cl::desc("When dumping type records for classes, unions, enums, and "
495344779Sdim             "structs, don't try to resolve forward references"),
496344779Sdim    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
497344779Sdim
498320397Sdimcl::list<uint32_t> DumpTypeIndex(
499320970Sdim    "type-index", cl::ZeroOrMore, cl::CommaSeparated,
500320397Sdim    cl::desc("only dump types with the specified hexadecimal type index"),
501320397Sdim    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
502320397Sdim
503320041Sdimcl::opt<bool> DumpIds("ids",
504320041Sdim                      cl::desc("dump CodeView type records from IPI stream"),
505320397Sdim                      cl::cat(TypeOptions), cl::sub(DumpSubcommand));
506319780Sdimcl::opt<bool>
507320041Sdim    DumpIdData("id-data",
508320041Sdim               cl::desc("dump CodeView type record raw bytes from IPI stream"),
509320397Sdim               cl::cat(TypeOptions), cl::sub(DumpSubcommand));
510319780Sdim
511320041Sdimcl::opt<bool> DumpIdExtras("id-extras",
512320041Sdim                           cl::desc("dump id hashes and index offsets"),
513320397Sdim                           cl::cat(TypeOptions), cl::sub(DumpSubcommand));
514320397Sdimcl::list<uint32_t> DumpIdIndex(
515320970Sdim    "id-index", cl::ZeroOrMore, cl::CommaSeparated,
516320397Sdim    cl::desc("only dump ids with the specified hexadecimal type index"),
517320397Sdim    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
518320041Sdim
519320572Sdimcl::opt<bool> DumpTypeDependents(
520320572Sdim    "dependents",
521320572Sdim    cl::desc("In conjunection with -type-index and -id-index, dumps the entire "
522320572Sdim             "dependency graph for the specified index instead of "
523320572Sdim             "just the single record with the specified index"),
524320572Sdim    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
525320572Sdim
526319780Sdim// SYMBOL OPTIONS
527327952Sdimcl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
528327952Sdim                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
529327952Sdimcl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
530327952Sdim                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
531344779Sdimcl::list<std::string> DumpGlobalNames(
532344779Sdim    "global-name",
533344779Sdim    cl::desc(
534344779Sdim        "With -globals, only dump globals whose name matches the given value"),
535344779Sdim    cl::cat(SymbolOptions), cl::sub(DumpSubcommand), cl::ZeroOrMore);
536319780Sdimcl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
537320397Sdim                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
538327952Sdimcl::opt<bool> DumpPublicExtras("public-extras",
539327952Sdim                               cl::desc("dump Publics hashes and address maps"),
540327952Sdim                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
541341825Sdimcl::opt<bool>
542341825Sdim    DumpGSIRecords("gsi-records",
543341825Sdim                   cl::desc("dump public / global common record stream"),
544341825Sdim                   cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
545320041Sdimcl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
546320397Sdim                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
547320041Sdim
548319780Sdimcl::opt<bool>
549320041Sdim    DumpSymRecordBytes("sym-data",
550319780Sdim                       cl::desc("dump CodeView symbol record raw bytes"),
551320397Sdim                       cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
552319780Sdim
553344779Sdimcl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
554344779Sdim                      cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
555344779Sdim
556320041Sdim// MODULE & FILE OPTIONS
557320041Sdimcl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
558320397Sdim                          cl::cat(FileOptions), cl::sub(DumpSubcommand));
559320041Sdimcl::opt<bool> DumpModuleFiles(
560320041Sdim    "files",
561320041Sdim    cl::desc("Dump the source files that contribute to each module's."),
562320397Sdim    cl::cat(FileOptions), cl::sub(DumpSubcommand));
563320041Sdimcl::opt<bool> DumpLines(
564320041Sdim    "l",
565320041Sdim    cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
566320397Sdim    cl::cat(FileOptions), cl::sub(DumpSubcommand));
567320041Sdimcl::opt<bool> DumpInlineeLines(
568320041Sdim    "il",
569320041Sdim    cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
570320397Sdim    cl::cat(FileOptions), cl::sub(DumpSubcommand));
571320041Sdimcl::opt<bool> DumpXmi(
572320041Sdim    "xmi",
573320041Sdim    cl::desc(
574320041Sdim        "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
575320397Sdim    cl::cat(FileOptions), cl::sub(DumpSubcommand));
576320041Sdimcl::opt<bool> DumpXme(
577320041Sdim    "xme",
578320041Sdim    cl::desc(
579320041Sdim        "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
580320397Sdim    cl::cat(FileOptions), cl::sub(DumpSubcommand));
581327952Sdimcl::opt<uint32_t> DumpModi("modi", cl::Optional,
582327952Sdim                           cl::desc("For all options that iterate over "
583327952Sdim                                    "modules, limit to the specified module"),
584327952Sdim                           cl::cat(FileOptions), cl::sub(DumpSubcommand));
585327952Sdimcl::opt<bool> JustMyCode("jmc", cl::Optional,
586327952Sdim                         cl::desc("For all options that iterate over modules, "
587327952Sdim                                  "ignore modules from system libraries"),
588327952Sdim                         cl::cat(FileOptions), cl::sub(DumpSubcommand));
589320041Sdim
590319780Sdim// MISCELLANEOUS OPTIONS
591341825Sdimcl::opt<bool> DumpNamedStreams("named-streams",
592341825Sdim                               cl::desc("dump PDB named stream table"),
593341825Sdim                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
594341825Sdim
595319780Sdimcl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
596320397Sdim                              cl::cat(MiscOptions), cl::sub(DumpSubcommand));
597341825Sdimcl::opt<bool> DumpStringTableDetails("string-table-details",
598341825Sdim                                     cl::desc("dump PDB String Table Details"),
599341825Sdim                                     cl::cat(MiscOptions),
600341825Sdim                                     cl::sub(DumpSubcommand));
601319780Sdim
602319780Sdimcl::opt<bool> DumpSectionContribs("section-contribs",
603319780Sdim                                  cl::desc("dump section contributions"),
604320397Sdim                                  cl::cat(MiscOptions),
605320397Sdim                                  cl::sub(DumpSubcommand));
606319780Sdimcl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
607320397Sdim                             cl::cat(MiscOptions), cl::sub(DumpSubcommand));
608327952Sdimcl::opt<bool> DumpSectionHeaders("section-headers",
609327952Sdim                                 cl::desc("Dump image section headers"),
610327952Sdim                                 cl::cat(MiscOptions), cl::sub(DumpSubcommand));
611319780Sdim
612319780Sdimcl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
613320397Sdim                     cl::cat(MiscOptions), cl::sub(DumpSubcommand));
614319780Sdim
615319780Sdimcl::list<std::string> InputFilenames(cl::Positional,
616319780Sdim                                     cl::desc("<input PDB files>"),
617320397Sdim                                     cl::OneOrMore, cl::sub(DumpSubcommand));
618319780Sdim}
619319780Sdim
620319780Sdimnamespace yaml2pdb {
621319780Sdimcl::opt<std::string>
622319780Sdim    YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
623319780Sdim                      cl::sub(YamlToPdbSubcommand));
624319780Sdim
625319780Sdimcl::opt<std::string> InputFilename(cl::Positional,
626319780Sdim                                   cl::desc("<input YAML file>"), cl::Required,
627319780Sdim                                   cl::sub(YamlToPdbSubcommand));
628319780Sdim}
629319780Sdim
630319780Sdimnamespace pdb2yaml {
631319780Sdimcl::opt<bool> All("all",
632319780Sdim                  cl::desc("Dump everything we know how to dump."),
633319780Sdim                  cl::sub(PdbToYamlSubcommand), cl::init(false));
634319780Sdimcl::opt<bool> NoFileHeaders("no-file-headers",
635319780Sdim                            cl::desc("Do not dump MSF file headers"),
636319780Sdim                            cl::sub(PdbToYamlSubcommand), cl::init(false));
637319780Sdimcl::opt<bool> Minimal("minimal",
638319780Sdim                      cl::desc("Don't write fields with default values"),
639319780Sdim                      cl::sub(PdbToYamlSubcommand), cl::init(false));
640319780Sdim
641319780Sdimcl::opt<bool> StreamMetadata(
642319780Sdim    "stream-metadata",
643319780Sdim    cl::desc("Dump the number of streams and each stream's size"),
644319780Sdim    cl::sub(PdbToYamlSubcommand), cl::init(false));
645319780Sdimcl::opt<bool> StreamDirectory(
646319780Sdim    "stream-directory",
647319780Sdim    cl::desc("Dump each stream's block map (implies -stream-metadata)"),
648319780Sdim    cl::sub(PdbToYamlSubcommand), cl::init(false));
649319780Sdimcl::opt<bool> PdbStream("pdb-stream",
650319780Sdim                        cl::desc("Dump the PDB Stream (Stream 1)"),
651319780Sdim                        cl::sub(PdbToYamlSubcommand), cl::init(false));
652319780Sdim
653319780Sdimcl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
654319780Sdim                          cl::sub(PdbToYamlSubcommand), cl::init(false));
655319780Sdim
656319780Sdimcl::opt<bool> DbiStream("dbi-stream",
657319780Sdim                        cl::desc("Dump the DBI Stream Headers (Stream 2)"),
658319780Sdim                        cl::sub(PdbToYamlSubcommand), cl::init(false));
659319780Sdim
660319780Sdimcl::opt<bool> TpiStream("tpi-stream",
661319780Sdim                        cl::desc("Dump the TPI Stream (Stream 3)"),
662319780Sdim                        cl::sub(PdbToYamlSubcommand), cl::init(false));
663319780Sdim
664319780Sdimcl::opt<bool> IpiStream("ipi-stream",
665319780Sdim                        cl::desc("Dump the IPI Stream (Stream 5)"),
666319780Sdim                        cl::sub(PdbToYamlSubcommand), cl::init(false));
667319780Sdim
668344779Sdimcl::opt<bool> PublicsStream("publics-stream",
669344779Sdim                            cl::desc("Dump the Publics Stream"),
670344779Sdim                            cl::sub(PdbToYamlSubcommand), cl::init(false));
671344779Sdim
672319780Sdim// MODULE & FILE OPTIONS
673319780Sdimcl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
674320041Sdim                          cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
675319780Sdimcl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
676320041Sdim                              cl::cat(FileOptions),
677319780Sdim                              cl::sub(PdbToYamlSubcommand));
678319780Sdimcl::list<ModuleSubsection> DumpModuleSubsections(
679319780Sdim    "subsections", cl::ZeroOrMore, cl::CommaSeparated,
680320397Sdim    cl::desc("dump subsections from each module's debug stream"), ChunkValues,
681320041Sdim    cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
682319780Sdimcl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
683320041Sdim                             cl::cat(FileOptions),
684319780Sdim                             cl::sub(PdbToYamlSubcommand));
685319780Sdim
686320041Sdimcl::list<std::string> InputFilename(cl::Positional,
687320041Sdim                                    cl::desc("<input PDB file>"), cl::Required,
688320041Sdim                                    cl::sub(PdbToYamlSubcommand));
689320041Sdim} // namespace pdb2yaml
690320041Sdim
691319780Sdimnamespace merge {
692319780Sdimcl::list<std::string> InputFilenames(cl::Positional,
693319780Sdim                                     cl::desc("<input PDB files>"),
694319780Sdim                                     cl::OneOrMore, cl::sub(MergeSubcommand));
695319780Sdimcl::opt<std::string>
696319780Sdim    PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
697319780Sdim                  cl::sub(MergeSubcommand));
698319780Sdim}
699341825Sdim
700341825Sdimnamespace explain {
701341825Sdimcl::list<std::string> InputFilename(cl::Positional,
702341825Sdim                                    cl::desc("<input PDB file>"), cl::Required,
703341825Sdim                                    cl::sub(ExplainSubcommand));
704341825Sdim
705341825Sdimcl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
706341825Sdim                           cl::sub(ExplainSubcommand), cl::OneOrMore);
707341825Sdim
708341825Sdimcl::opt<InputFileType> InputType(
709341825Sdim    "input-type", cl::desc("Specify how to interpret the input file"),
710341825Sdim    cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
711341825Sdim    cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
712341825Sdim                          "Treat input as a PDB file (default)"),
713341825Sdim               clEnumValN(InputFileType::PDBStream, "pdb-stream",
714341825Sdim                          "Treat input as raw contents of PDB stream"),
715341825Sdim               clEnumValN(InputFileType::DBIStream, "dbi-stream",
716341825Sdim                          "Treat input as raw contents of DBI stream"),
717341825Sdim               clEnumValN(InputFileType::Names, "names-stream",
718341825Sdim                          "Treat input as raw contents of /names named stream"),
719341825Sdim               clEnumValN(InputFileType::ModuleStream, "mod-stream",
720341825Sdim                          "Treat input as raw contents of a module stream")));
721341825Sdim} // namespace explain
722341825Sdim
723341825Sdimnamespace exportstream {
724341825Sdimcl::list<std::string> InputFilename(cl::Positional,
725341825Sdim                                    cl::desc("<input PDB file>"), cl::Required,
726341825Sdim                                    cl::sub(ExportSubcommand));
727341825Sdimcl::opt<std::string> OutputFile("out",
728341825Sdim                                cl::desc("The file to write the stream to"),
729341825Sdim                                cl::Required, cl::sub(ExportSubcommand));
730341825Sdimcl::opt<std::string>
731341825Sdim    Stream("stream", cl::Required,
732341825Sdim           cl::desc("The index or name of the stream whose contents to export"),
733341825Sdim           cl::sub(ExportSubcommand));
734341825Sdimcl::opt<bool> ForceName("name",
735341825Sdim                        cl::desc("Force the interpretation of -stream as a "
736341825Sdim                                 "string, even if it is a valid integer"),
737341825Sdim                        cl::sub(ExportSubcommand), cl::Optional,
738341825Sdim                        cl::init(false));
739341825Sdim} // namespace exportstream
740319780Sdim}
741319780Sdim
742319780Sdimstatic ExitOnError ExitOnErr;
743319780Sdim
744319780Sdimstatic void yamlToPdb(StringRef Path) {
745319780Sdim  BumpPtrAllocator Allocator;
746319780Sdim  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
747319780Sdim      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
748319780Sdim                                   /*RequiresNullTerminator=*/false);
749319780Sdim
750319780Sdim  if (ErrorOrBuffer.getError()) {
751344779Sdim    ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));
752319780Sdim  }
753319780Sdim
754319780Sdim  std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
755319780Sdim
756319780Sdim  llvm::yaml::Input In(Buffer->getBuffer());
757319780Sdim  pdb::yaml::PdbObject YamlObj(Allocator);
758319780Sdim  In >> YamlObj;
759319780Sdim
760319780Sdim  PDBFileBuilder Builder(Allocator);
761319780Sdim
762319780Sdim  uint32_t BlockSize = 4096;
763319780Sdim  if (YamlObj.Headers.hasValue())
764319780Sdim    BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
765319780Sdim  ExitOnErr(Builder.initialize(BlockSize));
766319780Sdim  // Add each of the reserved streams.  We ignore stream metadata in the
767319780Sdim  // yaml, because we will reconstruct our own view of the streams.  For
768319780Sdim  // example, the YAML may say that there were 20 streams in the original
769319780Sdim  // PDB, but maybe we only dump a subset of those 20 streams, so we will
770319780Sdim  // have fewer, and the ones we do have may end up with different indices
771319780Sdim  // than the ones in the original PDB.  So we just start with a clean slate.
772319780Sdim  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
773319780Sdim    ExitOnErr(Builder.getMsfBuilder().addStream(0));
774319780Sdim
775320041Sdim  StringsAndChecksums Strings;
776320041Sdim  Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
777320041Sdim
778319780Sdim  if (YamlObj.StringTable.hasValue()) {
779319780Sdim    for (auto S : *YamlObj.StringTable)
780320041Sdim      Strings.strings()->insert(S);
781319780Sdim  }
782319780Sdim
783319780Sdim  pdb::yaml::PdbInfoStream DefaultInfoStream;
784319780Sdim  pdb::yaml::PdbDbiStream DefaultDbiStream;
785319780Sdim  pdb::yaml::PdbTpiStream DefaultTpiStream;
786319780Sdim  pdb::yaml::PdbTpiStream DefaultIpiStream;
787319780Sdim
788319780Sdim  const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream);
789319780Sdim
790319780Sdim  auto &InfoBuilder = Builder.getInfoBuilder();
791319780Sdim  InfoBuilder.setAge(Info.Age);
792319780Sdim  InfoBuilder.setGuid(Info.Guid);
793319780Sdim  InfoBuilder.setSignature(Info.Signature);
794319780Sdim  InfoBuilder.setVersion(Info.Version);
795319780Sdim  for (auto F : Info.Features)
796319780Sdim    InfoBuilder.addFeature(F);
797319780Sdim
798319780Sdim  const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
799319780Sdim  auto &DbiBuilder = Builder.getDbiBuilder();
800319780Sdim  DbiBuilder.setAge(Dbi.Age);
801319780Sdim  DbiBuilder.setBuildNumber(Dbi.BuildNumber);
802319780Sdim  DbiBuilder.setFlags(Dbi.Flags);
803319780Sdim  DbiBuilder.setMachineType(Dbi.MachineType);
804319780Sdim  DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
805319780Sdim  DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
806319780Sdim  DbiBuilder.setVersionHeader(Dbi.VerHeader);
807319780Sdim  for (const auto &MI : Dbi.ModInfos) {
808319780Sdim    auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
809319780Sdim    ModiBuilder.setObjFileName(MI.Obj);
810319780Sdim
811319780Sdim    for (auto S : MI.SourceFiles)
812327952Sdim      ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
813319780Sdim    if (MI.Modi.hasValue()) {
814319780Sdim      const auto &ModiStream = *MI.Modi;
815319780Sdim      for (auto Symbol : ModiStream.Symbols) {
816319780Sdim        ModiBuilder.addSymbol(
817319780Sdim            Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
818319780Sdim      }
819319780Sdim    }
820319780Sdim
821320041Sdim    // Each module has its own checksum subsection, so scan for it every time.
822320041Sdim    Strings.setChecksums(nullptr);
823320041Sdim    CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
824320041Sdim
825319780Sdim    auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
826319780Sdim        Allocator, MI.Subsections, Strings));
827319780Sdim    for (auto &SS : CodeViewSubsections) {
828320041Sdim      ModiBuilder.addDebugSubsection(SS);
829319780Sdim    }
830319780Sdim  }
831319780Sdim
832319780Sdim  auto &TpiBuilder = Builder.getTpiBuilder();
833319780Sdim  const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
834319780Sdim  TpiBuilder.setVersionHeader(Tpi.Version);
835327952Sdim  AppendingTypeTableBuilder TS(Allocator);
836319780Sdim  for (const auto &R : Tpi.Records) {
837327952Sdim    CVType Type = R.toCodeViewRecord(TS);
838319780Sdim    TpiBuilder.addTypeRecord(Type.RecordData, None);
839319780Sdim  }
840319780Sdim
841319780Sdim  const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream);
842319780Sdim  auto &IpiBuilder = Builder.getIpiBuilder();
843319780Sdim  IpiBuilder.setVersionHeader(Ipi.Version);
844319780Sdim  for (const auto &R : Ipi.Records) {
845327952Sdim    CVType Type = R.toCodeViewRecord(TS);
846319780Sdim    IpiBuilder.addTypeRecord(Type.RecordData, None);
847319780Sdim  }
848319780Sdim
849320041Sdim  Builder.getStringTableBuilder().setStrings(*Strings.strings());
850320041Sdim
851344779Sdim  codeview::GUID IgnoredOutGuid;
852344779Sdim  ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
853319780Sdim}
854319780Sdim
855319780Sdimstatic PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
856319780Sdim  ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
857319780Sdim
858319780Sdim  NativeSession *NS = static_cast<NativeSession *>(Session.get());
859319780Sdim  return NS->getPDBFile();
860319780Sdim}
861319780Sdim
862319780Sdimstatic void pdb2Yaml(StringRef Path) {
863319780Sdim  std::unique_ptr<IPDBSession> Session;
864319780Sdim  auto &File = loadPDB(Path, Session);
865319780Sdim
866360784Sdim  auto O = std::make_unique<YAMLOutputStyle>(File);
867360784Sdim  O = std::make_unique<YAMLOutputStyle>(File);
868319780Sdim
869319780Sdim  ExitOnErr(O->dump());
870319780Sdim}
871319780Sdim
872319780Sdimstatic void dumpRaw(StringRef Path) {
873327952Sdim  InputFile IF = ExitOnErr(InputFile::open(Path));
874319780Sdim
875360784Sdim  auto O = std::make_unique<DumpOutputStyle>(IF);
876319780Sdim  ExitOnErr(O->dump());
877319780Sdim}
878319780Sdim
879320397Sdimstatic void dumpBytes(StringRef Path) {
880320397Sdim  std::unique_ptr<IPDBSession> Session;
881320397Sdim  auto &File = loadPDB(Path, Session);
882320397Sdim
883360784Sdim  auto O = std::make_unique<BytesOutputStyle>(File);
884320397Sdim
885320397Sdim  ExitOnErr(O->dump());
886320397Sdim}
887320397Sdim
888319780Sdimbool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
889319780Sdim  if (SymTypes.empty())
890319780Sdim    return true;
891319780Sdim  if (llvm::find(SymTypes, Search) != SymTypes.end())
892319780Sdim    return true;
893319780Sdim  if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end())
894319780Sdim    return true;
895319780Sdim  return false;
896319780Sdim}
897319780Sdim
898319780Sdimuint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
899319780Sdim  auto SymbolType = Symbol.getType();
900319780Sdim  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
901319780Sdim
902319780Sdim  return RawType.getLength();
903319780Sdim}
904319780Sdim
905319780Sdimbool opts::pretty::compareFunctionSymbols(
906319780Sdim    const std::unique_ptr<PDBSymbolFunc> &F1,
907319780Sdim    const std::unique_ptr<PDBSymbolFunc> &F2) {
908319780Sdim  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
909319780Sdim
910319780Sdim  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
911319780Sdim    return F1->getName() < F2->getName();
912319780Sdim
913319780Sdim  // Note that we intentionally sort in descending order on length, since
914319780Sdim  // long functions are more interesting than short functions.
915319780Sdim  return F1->getLength() > F2->getLength();
916319780Sdim}
917319780Sdim
918319780Sdimbool opts::pretty::compareDataSymbols(
919319780Sdim    const std::unique_ptr<PDBSymbolData> &F1,
920319780Sdim    const std::unique_ptr<PDBSymbolData> &F2) {
921319780Sdim  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
922319780Sdim
923319780Sdim  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
924319780Sdim    return F1->getName() < F2->getName();
925319780Sdim
926319780Sdim  // Note that we intentionally sort in descending order on length, since
927319780Sdim  // large types are more interesting than short ones.
928319780Sdim  return getTypeLength(*F1) > getTypeLength(*F2);
929319780Sdim}
930319780Sdim
931341825Sdimstatic std::string stringOr(std::string Str, std::string IfEmpty) {
932341825Sdim  return (Str.empty()) ? IfEmpty : Str;
933341825Sdim}
934341825Sdim
935341825Sdimstatic void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
936341825Sdim  auto Sources = Session.getInjectedSources();
937353358Sdim  if (!Sources || !Sources->getChildCount()) {
938341825Sdim    Printer.printLine("There are no injected sources.");
939341825Sdim    return;
940341825Sdim  }
941341825Sdim
942341825Sdim  while (auto IS = Sources->getNext()) {
943341825Sdim    Printer.NewLine();
944341825Sdim    std::string File = stringOr(IS->getFileName(), "<null>");
945341825Sdim    uint64_t Size = IS->getCodeByteSize();
946341825Sdim    std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
947341825Sdim    std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
948341825Sdim    uint32_t CRC = IS->getCrc32();
949341825Sdim
950341825Sdim    WithColor(Printer, PDB_ColorItem::Path).get() << File;
951341825Sdim    Printer << " (";
952341825Sdim    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
953341825Sdim    Printer << " bytes): ";
954341825Sdim    WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
955341825Sdim    Printer << "=";
956341825Sdim    WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
957341825Sdim    Printer << ", ";
958341825Sdim    WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
959341825Sdim    Printer << "=";
960341825Sdim    WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
961341825Sdim    Printer << ", ";
962341825Sdim    WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
963341825Sdim    Printer << "=";
964341825Sdim    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
965341825Sdim    Printer << ", ";
966341825Sdim    WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
967341825Sdim    Printer << "=";
968353358Sdim    dumpPDBSourceCompression(
969353358Sdim        WithColor(Printer, PDB_ColorItem::LiteralValue).get(),
970353358Sdim        IS->getCompression());
971341825Sdim
972341825Sdim    if (!opts::pretty::ShowInjectedSourceContent)
973341825Sdim      continue;
974341825Sdim
975341825Sdim    // Set the indent level to 0 when printing file content.
976341825Sdim    int Indent = Printer.getIndentLevel();
977341825Sdim    Printer.Unindent(Indent);
978341825Sdim
979353358Sdim    if (IS->getCompression() == PDB_SourceCompression::None)
980353358Sdim      Printer.printLine(IS->getCode());
981353358Sdim    else
982353358Sdim      Printer.formatBinary("Compressed data",
983353358Sdim                           arrayRefFromStringRef(IS->getCode()),
984353358Sdim                           /*StartOffset=*/0);
985341825Sdim
986341825Sdim    // Re-indent back to the original level.
987341825Sdim    Printer.Indent(Indent);
988341825Sdim  }
989341825Sdim}
990341825Sdim
991344779Sdimtemplate <typename OuterT, typename ChildT>
992344779Sdimvoid diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,
993344779Sdim                     PdbSymbolIdField Recurse) {
994344779Sdim  OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);
995344779Sdim  if (!ConcreteOuter)
996344779Sdim    return;
997344779Sdim
998344779Sdim  auto Children = ConcreteOuter->template findAllChildren<ChildT>();
999344779Sdim  while (auto Child = Children->getNext()) {
1000344779Sdim    outs() << "  {";
1001344779Sdim    Child->defaultDump(outs(), 4, Ids, Recurse);
1002344779Sdim    outs() << "\n  }\n";
1003344779Sdim  }
1004344779Sdim}
1005344779Sdim
1006344779Sdimstatic void dumpDia(StringRef Path) {
1007344779Sdim  std::unique_ptr<IPDBSession> Session;
1008344779Sdim
1009344779Sdim  const auto ReaderType =
1010344779Sdim      opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1011344779Sdim  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1012344779Sdim
1013344779Sdim  auto GlobalScope = Session->getGlobalScope();
1014344779Sdim
1015344779Sdim  std::vector<PDB_SymType> SymTypes;
1016344779Sdim
1017344779Sdim  if (opts::diadump::Compilands)
1018344779Sdim    SymTypes.push_back(PDB_SymType::Compiland);
1019344779Sdim  if (opts::diadump::Enums)
1020344779Sdim    SymTypes.push_back(PDB_SymType::Enum);
1021344779Sdim  if (opts::diadump::Pointers)
1022344779Sdim    SymTypes.push_back(PDB_SymType::PointerType);
1023344779Sdim  if (opts::diadump::UDTs)
1024344779Sdim    SymTypes.push_back(PDB_SymType::UDT);
1025344779Sdim  if (opts::diadump::Funcsigs)
1026344779Sdim    SymTypes.push_back(PDB_SymType::FunctionSig);
1027344779Sdim  if (opts::diadump::Arrays)
1028344779Sdim    SymTypes.push_back(PDB_SymType::ArrayType);
1029344779Sdim  if (opts::diadump::VTShapes)
1030344779Sdim    SymTypes.push_back(PDB_SymType::VTableShape);
1031344779Sdim  if (opts::diadump::Typedefs)
1032344779Sdim    SymTypes.push_back(PDB_SymType::Typedef);
1033344779Sdim  PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
1034344779Sdim                                                      : PdbSymbolIdField::All;
1035344779Sdim
1036344779Sdim  PdbSymbolIdField Recurse = PdbSymbolIdField::None;
1037344779Sdim  if (opts::diadump::Recurse)
1038344779Sdim    Recurse = PdbSymbolIdField::All;
1039344779Sdim  if (!opts::diadump::ShowClassHierarchy)
1040344779Sdim    Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);
1041344779Sdim
1042344779Sdim  for (PDB_SymType ST : SymTypes) {
1043344779Sdim    auto Children = GlobalScope->findAllChildren(ST);
1044344779Sdim    while (auto Child = Children->getNext()) {
1045344779Sdim      outs() << "{";
1046344779Sdim      Child->defaultDump(outs(), 2, Ids, Recurse);
1047344779Sdim
1048344779Sdim      diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);
1049344779Sdim      outs() << "\n}\n";
1050344779Sdim    }
1051344779Sdim  }
1052344779Sdim}
1053344779Sdim
1054319780Sdimstatic void dumpPretty(StringRef Path) {
1055319780Sdim  std::unique_ptr<IPDBSession> Session;
1056319780Sdim
1057319780Sdim  const auto ReaderType =
1058319780Sdim      opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1059319780Sdim  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1060319780Sdim
1061319780Sdim  if (opts::pretty::LoadAddress)
1062319780Sdim    Session->setLoadAddress(opts::pretty::LoadAddress);
1063319780Sdim
1064319780Sdim  auto &Stream = outs();
1065319780Sdim  const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
1066319780Sdim                            ? Stream.has_colors()
1067319780Sdim                            : opts::pretty::ColorOutput == cl::BOU_TRUE;
1068319780Sdim  LinePrinter Printer(2, UseColor, Stream);
1069319780Sdim
1070319780Sdim  auto GlobalScope(Session->getGlobalScope());
1071341825Sdim  if (!GlobalScope)
1072341825Sdim    return;
1073319780Sdim  std::string FileName(GlobalScope->getSymbolsFileName());
1074319780Sdim
1075319780Sdim  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
1076319780Sdim  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
1077319780Sdim  Printer.Indent();
1078319780Sdim  uint64_t FileSize = 0;
1079319780Sdim
1080319780Sdim  Printer.NewLine();
1081319780Sdim  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
1082319780Sdim  if (!sys::fs::file_size(FileName, FileSize)) {
1083319780Sdim    Printer << ": " << FileSize << " bytes";
1084319780Sdim  } else {
1085319780Sdim    Printer << ": (Unable to obtain file size)";
1086319780Sdim  }
1087319780Sdim
1088319780Sdim  Printer.NewLine();
1089319780Sdim  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
1090319780Sdim  Printer << ": " << GlobalScope->getGuid();
1091319780Sdim
1092319780Sdim  Printer.NewLine();
1093319780Sdim  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
1094319780Sdim  Printer << ": " << GlobalScope->getAge();
1095319780Sdim
1096319780Sdim  Printer.NewLine();
1097319780Sdim  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
1098319780Sdim  Printer << ": ";
1099319780Sdim  if (GlobalScope->hasCTypes())
1100319780Sdim    outs() << "HasCTypes ";
1101319780Sdim  if (GlobalScope->hasPrivateSymbols())
1102319780Sdim    outs() << "HasPrivateSymbols ";
1103319780Sdim  Printer.Unindent();
1104319780Sdim
1105341825Sdim  if (!opts::pretty::WithName.empty()) {
1106341825Sdim    Printer.NewLine();
1107341825Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1108341825Sdim        << "---SYMBOLS & TYPES BY NAME---";
1109341825Sdim
1110341825Sdim    for (StringRef Name : opts::pretty::WithName) {
1111341825Sdim      auto Symbols = GlobalScope->findChildren(
1112341825Sdim          PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
1113341825Sdim      if (!Symbols || Symbols->getChildCount() == 0) {
1114341825Sdim        Printer.formatLine("[not found] - {0}", Name);
1115341825Sdim        continue;
1116341825Sdim      }
1117341825Sdim      Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
1118341825Sdim                         Name);
1119341825Sdim
1120341825Sdim      AutoIndent Indent(Printer);
1121341825Sdim      Printer.NewLine();
1122341825Sdim
1123341825Sdim      while (auto Symbol = Symbols->getNext()) {
1124341825Sdim        switch (Symbol->getSymTag()) {
1125341825Sdim        case PDB_SymType::Typedef: {
1126341825Sdim          TypedefDumper TD(Printer);
1127341825Sdim          std::unique_ptr<PDBSymbolTypeTypedef> T =
1128341825Sdim              llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
1129341825Sdim          TD.start(*T);
1130341825Sdim          break;
1131341825Sdim        }
1132341825Sdim        case PDB_SymType::Enum: {
1133341825Sdim          EnumDumper ED(Printer);
1134341825Sdim          std::unique_ptr<PDBSymbolTypeEnum> E =
1135341825Sdim              llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
1136341825Sdim          ED.start(*E);
1137341825Sdim          break;
1138341825Sdim        }
1139341825Sdim        case PDB_SymType::UDT: {
1140341825Sdim          ClassDefinitionDumper CD(Printer);
1141341825Sdim          std::unique_ptr<PDBSymbolTypeUDT> C =
1142341825Sdim              llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
1143341825Sdim          CD.start(*C);
1144341825Sdim          break;
1145341825Sdim        }
1146341825Sdim        case PDB_SymType::BaseClass:
1147341825Sdim        case PDB_SymType::Friend: {
1148341825Sdim          TypeDumper TD(Printer);
1149341825Sdim          Symbol->dump(TD);
1150341825Sdim          break;
1151341825Sdim        }
1152341825Sdim        case PDB_SymType::Function: {
1153341825Sdim          FunctionDumper FD(Printer);
1154341825Sdim          std::unique_ptr<PDBSymbolFunc> F =
1155341825Sdim              llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
1156341825Sdim          FD.start(*F, FunctionDumper::PointerType::None);
1157341825Sdim          break;
1158341825Sdim        }
1159341825Sdim        case PDB_SymType::Data: {
1160341825Sdim          VariableDumper VD(Printer);
1161341825Sdim          std::unique_ptr<PDBSymbolData> D =
1162341825Sdim              llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
1163341825Sdim          VD.start(*D);
1164341825Sdim          break;
1165341825Sdim        }
1166341825Sdim        case PDB_SymType::PublicSymbol: {
1167341825Sdim          ExternalSymbolDumper ED(Printer);
1168341825Sdim          std::unique_ptr<PDBSymbolPublicSymbol> PS =
1169341825Sdim              llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
1170341825Sdim          ED.dump(*PS);
1171341825Sdim          break;
1172341825Sdim        }
1173341825Sdim        default:
1174341825Sdim          llvm_unreachable("Unexpected symbol tag!");
1175341825Sdim        }
1176341825Sdim      }
1177341825Sdim    }
1178341825Sdim    llvm::outs().flush();
1179341825Sdim  }
1180341825Sdim
1181319780Sdim  if (opts::pretty::Compilands) {
1182319780Sdim    Printer.NewLine();
1183319780Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1184319780Sdim        << "---COMPILANDS---";
1185344779Sdim    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
1186344779Sdim
1187344779Sdim    if (Compilands) {
1188341825Sdim      Printer.Indent();
1189341825Sdim      CompilandDumper Dumper(Printer);
1190341825Sdim      CompilandDumpFlags options = CompilandDumper::Flags::None;
1191341825Sdim      if (opts::pretty::Lines)
1192341825Sdim        options = options | CompilandDumper::Flags::Lines;
1193341825Sdim      while (auto Compiland = Compilands->getNext())
1194341825Sdim        Dumper.start(*Compiland, options);
1195341825Sdim      Printer.Unindent();
1196341825Sdim    }
1197319780Sdim  }
1198319780Sdim
1199344779Sdim  if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
1200344779Sdim      opts::pretty::Funcsigs || opts::pretty::Pointers ||
1201344779Sdim      opts::pretty::Arrays || opts::pretty::VTShapes) {
1202319780Sdim    Printer.NewLine();
1203319780Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
1204319780Sdim    Printer.Indent();
1205319780Sdim    TypeDumper Dumper(Printer);
1206319780Sdim    Dumper.start(*GlobalScope);
1207319780Sdim    Printer.Unindent();
1208319780Sdim  }
1209319780Sdim
1210319780Sdim  if (opts::pretty::Symbols) {
1211319780Sdim    Printer.NewLine();
1212319780Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
1213341825Sdim    if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
1214341825Sdim      Printer.Indent();
1215341825Sdim      CompilandDumper Dumper(Printer);
1216341825Sdim      while (auto Compiland = Compilands->getNext())
1217341825Sdim        Dumper.start(*Compiland, true);
1218341825Sdim      Printer.Unindent();
1219341825Sdim    }
1220319780Sdim  }
1221319780Sdim
1222319780Sdim  if (opts::pretty::Globals) {
1223319780Sdim    Printer.NewLine();
1224319780Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
1225319780Sdim    Printer.Indent();
1226319780Sdim    if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
1227341825Sdim      if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
1228341825Sdim        FunctionDumper Dumper(Printer);
1229341825Sdim        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1230341825Sdim          while (auto Function = Functions->getNext()) {
1231341825Sdim            Printer.NewLine();
1232341825Sdim            Dumper.start(*Function, FunctionDumper::PointerType::None);
1233341825Sdim          }
1234341825Sdim        } else {
1235341825Sdim          std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
1236341825Sdim          while (auto Func = Functions->getNext())
1237341825Sdim            Funcs.push_back(std::move(Func));
1238344779Sdim          llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);
1239341825Sdim          for (const auto &Func : Funcs) {
1240341825Sdim            Printer.NewLine();
1241341825Sdim            Dumper.start(*Func, FunctionDumper::PointerType::None);
1242341825Sdim          }
1243319780Sdim        }
1244319780Sdim      }
1245319780Sdim    }
1246319780Sdim    if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
1247341825Sdim      if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
1248341825Sdim        VariableDumper Dumper(Printer);
1249341825Sdim        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1250341825Sdim          while (auto Var = Vars->getNext())
1251341825Sdim            Dumper.start(*Var);
1252341825Sdim        } else {
1253341825Sdim          std::vector<std::unique_ptr<PDBSymbolData>> Datas;
1254341825Sdim          while (auto Var = Vars->getNext())
1255341825Sdim            Datas.push_back(std::move(Var));
1256344779Sdim          llvm::sort(Datas, opts::pretty::compareDataSymbols);
1257341825Sdim          for (const auto &Var : Datas)
1258341825Sdim            Dumper.start(*Var);
1259341825Sdim        }
1260319780Sdim      }
1261319780Sdim    }
1262319780Sdim    if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
1263341825Sdim      if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
1264341825Sdim        CompilandDumper Dumper(Printer);
1265341825Sdim        while (auto Thunk = Thunks->getNext())
1266341825Sdim          Dumper.dump(*Thunk);
1267341825Sdim      }
1268319780Sdim    }
1269319780Sdim    Printer.Unindent();
1270319780Sdim  }
1271319780Sdim  if (opts::pretty::Externals) {
1272319780Sdim    Printer.NewLine();
1273319780Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
1274319780Sdim    Printer.Indent();
1275319780Sdim    ExternalSymbolDumper Dumper(Printer);
1276319780Sdim    Dumper.start(*GlobalScope);
1277319780Sdim  }
1278319780Sdim  if (opts::pretty::Lines) {
1279319780Sdim    Printer.NewLine();
1280319780Sdim  }
1281341825Sdim  if (opts::pretty::InjectedSources) {
1282341825Sdim    Printer.NewLine();
1283341825Sdim    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1284341825Sdim        << "---INJECTED SOURCES---";
1285341825Sdim    AutoIndent Indent1(Printer);
1286353358Sdim    dumpInjectedSources(Printer, *Session);
1287341825Sdim  }
1288341825Sdim
1289344779Sdim  Printer.NewLine();
1290319780Sdim  outs().flush();
1291319780Sdim}
1292319780Sdim
1293319780Sdimstatic void mergePdbs() {
1294319780Sdim  BumpPtrAllocator Allocator;
1295327952Sdim  MergingTypeTableBuilder MergedTpi(Allocator);
1296327952Sdim  MergingTypeTableBuilder MergedIpi(Allocator);
1297319780Sdim
1298319780Sdim  // Create a Tpi and Ipi type table with all types from all input files.
1299319780Sdim  for (const auto &Path : opts::merge::InputFilenames) {
1300319780Sdim    std::unique_ptr<IPDBSession> Session;
1301319780Sdim    auto &File = loadPDB(Path, Session);
1302319780Sdim    SmallVector<TypeIndex, 128> TypeMap;
1303319780Sdim    SmallVector<TypeIndex, 128> IdMap;
1304319780Sdim    if (File.hasPDBTpiStream()) {
1305319780Sdim      auto &Tpi = ExitOnErr(File.getPDBTpiStream());
1306321238Sdim      ExitOnErr(
1307321238Sdim          codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));
1308319780Sdim    }
1309319780Sdim    if (File.hasPDBIpiStream()) {
1310319780Sdim      auto &Ipi = ExitOnErr(File.getPDBIpiStream());
1311319780Sdim      ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
1312319780Sdim                                         Ipi.typeArray()));
1313319780Sdim    }
1314319780Sdim  }
1315319780Sdim
1316319780Sdim  // Then write the PDB.
1317319780Sdim  PDBFileBuilder Builder(Allocator);
1318319780Sdim  ExitOnErr(Builder.initialize(4096));
1319319780Sdim  // Add each of the reserved streams.  We might not put any data in them,
1320319780Sdim  // but at least they have to be present.
1321319780Sdim  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
1322319780Sdim    ExitOnErr(Builder.getMsfBuilder().addStream(0));
1323319780Sdim
1324319780Sdim  auto &DestTpi = Builder.getTpiBuilder();
1325319780Sdim  auto &DestIpi = Builder.getIpiBuilder();
1326327952Sdim  MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
1327327952Sdim    DestTpi.addTypeRecord(Type.RecordData, None);
1328319780Sdim  });
1329327952Sdim  MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
1330327952Sdim    DestIpi.addTypeRecord(Type.RecordData, None);
1331319780Sdim  });
1332320041Sdim  Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
1333319780Sdim
1334319780Sdim  SmallString<64> OutFile(opts::merge::PdbOutputFile);
1335319780Sdim  if (OutFile.empty()) {
1336319780Sdim    OutFile = opts::merge::InputFilenames[0];
1337319780Sdim    llvm::sys::path::replace_extension(OutFile, "merged.pdb");
1338319780Sdim  }
1339344779Sdim
1340344779Sdim  codeview::GUID IgnoredOutGuid;
1341344779Sdim  ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
1342319780Sdim}
1343319780Sdim
1344341825Sdimstatic void explain() {
1345341825Sdim  std::unique_ptr<IPDBSession> Session;
1346341825Sdim  InputFile IF =
1347341825Sdim      ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
1348341825Sdim
1349341825Sdim  for (uint64_t Off : opts::explain::Offsets) {
1350360784Sdim    auto O = std::make_unique<ExplainOutputStyle>(IF, Off);
1351341825Sdim
1352341825Sdim    ExitOnErr(O->dump());
1353341825Sdim  }
1354341825Sdim}
1355341825Sdim
1356341825Sdimstatic void exportStream() {
1357341825Sdim  std::unique_ptr<IPDBSession> Session;
1358341825Sdim  PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
1359341825Sdim
1360341825Sdim  std::unique_ptr<MappedBlockStream> SourceStream;
1361341825Sdim  uint32_t Index = 0;
1362341825Sdim  bool Success = false;
1363341825Sdim  std::string OutFileName = opts::exportstream::OutputFile;
1364341825Sdim
1365341825Sdim  if (!opts::exportstream::ForceName) {
1366341825Sdim    // First try to parse it as an integer, if it fails fall back to treating it
1367341825Sdim    // as a named stream.
1368341825Sdim    if (to_integer(opts::exportstream::Stream, Index)) {
1369341825Sdim      if (Index >= File.getNumStreams()) {
1370341825Sdim        errs() << "Error: " << Index << " is not a valid stream index.\n";
1371341825Sdim        exit(1);
1372341825Sdim      }
1373341825Sdim      Success = true;
1374341825Sdim      outs() << "Dumping contents of stream index " << Index << " to file "
1375341825Sdim             << OutFileName << ".\n";
1376341825Sdim    }
1377341825Sdim  }
1378341825Sdim
1379341825Sdim  if (!Success) {
1380341825Sdim    InfoStream &IS = cantFail(File.getPDBInfoStream());
1381341825Sdim    Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
1382341825Sdim    outs() << "Dumping contents of stream '" << opts::exportstream::Stream
1383341825Sdim           << "' (index " << Index << ") to file " << OutFileName << ".\n";
1384341825Sdim  }
1385341825Sdim
1386353358Sdim  SourceStream = File.createIndexedStream(Index);
1387341825Sdim  auto OutFile = ExitOnErr(
1388341825Sdim      FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
1389341825Sdim  FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
1390341825Sdim  BinaryStreamWriter Writer(DestStream);
1391341825Sdim  ExitOnErr(Writer.writeStreamRef(*SourceStream));
1392341825Sdim  ExitOnErr(DestStream.commit());
1393341825Sdim}
1394341825Sdim
1395320397Sdimstatic bool parseRange(StringRef Str,
1396320397Sdim                       Optional<opts::bytes::NumberRange> &Parsed) {
1397320397Sdim  if (Str.empty())
1398320397Sdim    return true;
1399320397Sdim
1400320397Sdim  llvm::Regex R("^([^-]+)(-([^-]+))?$");
1401320397Sdim  llvm::SmallVector<llvm::StringRef, 2> Matches;
1402320397Sdim  if (!R.match(Str, &Matches))
1403320397Sdim    return false;
1404320397Sdim
1405320397Sdim  Parsed.emplace();
1406320397Sdim  if (!to_integer(Matches[1], Parsed->Min))
1407320397Sdim    return false;
1408320397Sdim
1409320397Sdim  if (!Matches[3].empty()) {
1410320397Sdim    Parsed->Max.emplace();
1411320397Sdim    if (!to_integer(Matches[3], *Parsed->Max))
1412320397Sdim      return false;
1413320397Sdim  }
1414320397Sdim  return true;
1415320397Sdim}
1416320397Sdim
1417320397Sdimstatic void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
1418320397Sdim  // If this list contains "All" plus some other stuff, remove the other stuff
1419320397Sdim  // and just keep "All" in the list.
1420320397Sdim  if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))
1421320397Sdim    return;
1422320397Sdim  Chunks.reset();
1423320397Sdim  Chunks.push_back(opts::ModuleSubsection::All);
1424320397Sdim}
1425320397Sdim
1426341825Sdimint main(int Argc, const char **Argv) {
1427341825Sdim  InitLLVM X(Argc, Argv);
1428319780Sdim  ExitOnErr.setBanner("llvm-pdbutil: ");
1429319780Sdim
1430341825Sdim  cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
1431319780Sdim
1432320397Sdim  if (opts::BytesSubcommand) {
1433320397Sdim    if (!parseRange(opts::bytes::DumpBlockRangeOpt,
1434320397Sdim                    opts::bytes::DumpBlockRange)) {
1435320397Sdim      errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
1436319780Sdim             << "' invalid format.\n";
1437319780Sdim      errs().flush();
1438319780Sdim      exit(1);
1439319780Sdim    }
1440320397Sdim    if (!parseRange(opts::bytes::DumpByteRangeOpt,
1441320397Sdim                    opts::bytes::DumpByteRange)) {
1442320397Sdim      errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
1443320397Sdim             << "' invalid format.\n";
1444320397Sdim      errs().flush();
1445320397Sdim      exit(1);
1446319780Sdim    }
1447319780Sdim  }
1448319780Sdim
1449320397Sdim  if (opts::DumpSubcommand) {
1450320397Sdim    if (opts::dump::RawAll) {
1451327952Sdim      opts::dump::DumpGlobals = true;
1452344779Sdim      opts::dump::DumpFpo = true;
1453320397Sdim      opts::dump::DumpInlineeLines = true;
1454320397Sdim      opts::dump::DumpIds = true;
1455327952Sdim      opts::dump::DumpIdExtras = true;
1456327952Sdim      opts::dump::DumpLines = true;
1457327952Sdim      opts::dump::DumpModules = true;
1458327952Sdim      opts::dump::DumpModuleFiles = true;
1459320397Sdim      opts::dump::DumpPublics = true;
1460320397Sdim      opts::dump::DumpSectionContribs = true;
1461327952Sdim      opts::dump::DumpSectionHeaders = true;
1462320397Sdim      opts::dump::DumpSectionMap = true;
1463320397Sdim      opts::dump::DumpStreams = true;
1464320397Sdim      opts::dump::DumpStreamBlocks = true;
1465320397Sdim      opts::dump::DumpStringTable = true;
1466341825Sdim      opts::dump::DumpStringTableDetails = true;
1467320397Sdim      opts::dump::DumpSummary = true;
1468320397Sdim      opts::dump::DumpSymbols = true;
1469327952Sdim      opts::dump::DumpSymbolStats = true;
1470320397Sdim      opts::dump::DumpTypes = true;
1471320397Sdim      opts::dump::DumpTypeExtras = true;
1472327952Sdim      opts::dump::DumpUdtStats = true;
1473327952Sdim      opts::dump::DumpXme = true;
1474327952Sdim      opts::dump::DumpXmi = true;
1475319780Sdim    }
1476319780Sdim  }
1477319780Sdim  if (opts::PdbToYamlSubcommand) {
1478319780Sdim    if (opts::pdb2yaml::All) {
1479319780Sdim      opts::pdb2yaml::StreamMetadata = true;
1480319780Sdim      opts::pdb2yaml::StreamDirectory = true;
1481319780Sdim      opts::pdb2yaml::PdbStream = true;
1482319780Sdim      opts::pdb2yaml::StringTable = true;
1483319780Sdim      opts::pdb2yaml::DbiStream = true;
1484319780Sdim      opts::pdb2yaml::TpiStream = true;
1485319780Sdim      opts::pdb2yaml::IpiStream = true;
1486344779Sdim      opts::pdb2yaml::PublicsStream = true;
1487320041Sdim      opts::pdb2yaml::DumpModules = true;
1488320041Sdim      opts::pdb2yaml::DumpModuleFiles = true;
1489320041Sdim      opts::pdb2yaml::DumpModuleSyms = true;
1490320041Sdim      opts::pdb2yaml::DumpModuleSubsections.push_back(
1491320041Sdim          opts::ModuleSubsection::All);
1492319780Sdim    }
1493320397Sdim    simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);
1494320041Sdim
1495320041Sdim    if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
1496320041Sdim      opts::pdb2yaml::DumpModules = true;
1497320041Sdim
1498320041Sdim    if (opts::pdb2yaml::DumpModules)
1499320041Sdim      opts::pdb2yaml::DbiStream = true;
1500319780Sdim  }
1501319780Sdim
1502319780Sdim  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
1503319780Sdim
1504319780Sdim  if (opts::PdbToYamlSubcommand) {
1505319780Sdim    pdb2Yaml(opts::pdb2yaml::InputFilename.front());
1506319780Sdim  } else if (opts::YamlToPdbSubcommand) {
1507319780Sdim    if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
1508319780Sdim      SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
1509319780Sdim      sys::path::replace_extension(OutputFilename, ".pdb");
1510319780Sdim      opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str();
1511319780Sdim    }
1512319780Sdim    yamlToPdb(opts::yaml2pdb::InputFilename);
1513344779Sdim  } else if (opts::DiaDumpSubcommand) {
1514344779Sdim    llvm::for_each(opts::diadump::InputFilenames, dumpDia);
1515319780Sdim  } else if (opts::PrettySubcommand) {
1516319780Sdim    if (opts::pretty::Lines)
1517319780Sdim      opts::pretty::Compilands = true;
1518319780Sdim
1519319780Sdim    if (opts::pretty::All) {
1520319780Sdim      opts::pretty::Compilands = true;
1521319780Sdim      opts::pretty::Symbols = true;
1522319780Sdim      opts::pretty::Globals = true;
1523319780Sdim      opts::pretty::Types = true;
1524319780Sdim      opts::pretty::Externals = true;
1525319780Sdim      opts::pretty::Lines = true;
1526319780Sdim    }
1527319780Sdim
1528319780Sdim    if (opts::pretty::Types) {
1529319780Sdim      opts::pretty::Classes = true;
1530319780Sdim      opts::pretty::Typedefs = true;
1531319780Sdim      opts::pretty::Enums = true;
1532344779Sdim      opts::pretty::Pointers = true;
1533344779Sdim      opts::pretty::Funcsigs = true;
1534319780Sdim    }
1535319780Sdim
1536319780Sdim    // When adding filters for excluded compilands and types, we need to
1537319780Sdim    // remember that these are regexes.  So special characters such as * and \
1538319780Sdim    // need to be escaped in the regex.  In the case of a literal \, this means
1539319780Sdim    // it needs to be escaped again in the C++.  So matching a single \ in the
1540319780Sdim    // input requires 4 \es in the C++.
1541319780Sdim    if (opts::pretty::ExcludeCompilerGenerated) {
1542319780Sdim      opts::pretty::ExcludeTypes.push_back("__vc_attributes");
1543319780Sdim      opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
1544319780Sdim    }
1545319780Sdim    if (opts::pretty::ExcludeSystemLibraries) {
1546319780Sdim      opts::pretty::ExcludeCompilands.push_back(
1547319780Sdim          "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
1548319780Sdim      opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
1549319780Sdim      opts::pretty::ExcludeCompilands.push_back(
1550319780Sdim          "d:\\\\th.obj.x86fre\\\\minkernel");
1551319780Sdim    }
1552327952Sdim    llvm::for_each(opts::pretty::InputFilenames, dumpPretty);
1553320397Sdim  } else if (opts::DumpSubcommand) {
1554327952Sdim    llvm::for_each(opts::dump::InputFilenames, dumpRaw);
1555320397Sdim  } else if (opts::BytesSubcommand) {
1556327952Sdim    llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
1557319780Sdim  } else if (opts::MergeSubcommand) {
1558319780Sdim    if (opts::merge::InputFilenames.size() < 2) {
1559319780Sdim      errs() << "merge subcommand requires at least 2 input files.\n";
1560319780Sdim      exit(1);
1561319780Sdim    }
1562319780Sdim    mergePdbs();
1563341825Sdim  } else if (opts::ExplainSubcommand) {
1564341825Sdim    explain();
1565341825Sdim  } else if (opts::ExportSubcommand) {
1566341825Sdim    exportStream();
1567319780Sdim  }
1568319780Sdim
1569319780Sdim  outs().flush();
1570319780Sdim  return 0;
1571319780Sdim}
1572