1//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Dumps debug information present in PDB files.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm-pdbutil.h"
14
15#include "BytesOutputStyle.h"
16#include "DumpOutputStyle.h"
17#include "ExplainOutputStyle.h"
18#include "InputFile.h"
19#include "LinePrinter.h"
20#include "OutputStyle.h"
21#include "PrettyClassDefinitionDumper.h"
22#include "PrettyCompilandDumper.h"
23#include "PrettyEnumDumper.h"
24#include "PrettyExternalSymbolDumper.h"
25#include "PrettyFunctionDumper.h"
26#include "PrettyTypeDumper.h"
27#include "PrettyTypedefDumper.h"
28#include "PrettyVariableDumper.h"
29#include "YAMLOutputStyle.h"
30
31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/BitVector.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/StringExtras.h"
36#include "llvm/BinaryFormat/Magic.h"
37#include "llvm/Config/config.h"
38#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
39#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
40#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
41#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
42#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
43#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
44#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
45#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
46#include "llvm/DebugInfo/MSF/MSFBuilder.h"
47#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
48#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
49#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
50#include "llvm/DebugInfo/PDB/IPDBSession.h"
51#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
52#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
53#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
54#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
55#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
56#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
57#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
58#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
59#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
60#include "llvm/DebugInfo/PDB/Native/RawError.h"
61#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
62#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
63#include "llvm/DebugInfo/PDB/PDB.h"
64#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
65#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
66#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
67#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
68#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
69#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
70#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
71#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
72#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
73#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
74#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
75#include "llvm/Support/BinaryByteStream.h"
76#include "llvm/Support/COM.h"
77#include "llvm/Support/CommandLine.h"
78#include "llvm/Support/ConvertUTF.h"
79#include "llvm/Support/FileOutputBuffer.h"
80#include "llvm/Support/FileSystem.h"
81#include "llvm/Support/Format.h"
82#include "llvm/Support/InitLLVM.h"
83#include "llvm/Support/LineIterator.h"
84#include "llvm/Support/ManagedStatic.h"
85#include "llvm/Support/MemoryBuffer.h"
86#include "llvm/Support/Path.h"
87#include "llvm/Support/PrettyStackTrace.h"
88#include "llvm/Support/Process.h"
89#include "llvm/Support/Regex.h"
90#include "llvm/Support/ScopedPrinter.h"
91#include "llvm/Support/Signals.h"
92#include "llvm/Support/raw_ostream.h"
93
94using namespace llvm;
95using namespace llvm::codeview;
96using namespace llvm::msf;
97using namespace llvm::pdb;
98
99namespace opts {
100
101cl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info");
102cl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file");
103
104cl::SubCommand DiaDumpSubcommand("diadump",
105                                 "Dump debug information using a DIA-like API");
106
107cl::SubCommand
108    PrettySubcommand("pretty",
109                     "Dump semantic information about types and symbols");
110
111cl::SubCommand
112    YamlToPdbSubcommand("yaml2pdb",
113                        "Generate a PDB file from a YAML description");
114cl::SubCommand
115    PdbToYamlSubcommand("pdb2yaml",
116                        "Generate a detailed YAML description of a PDB File");
117
118cl::SubCommand MergeSubcommand("merge",
119                               "Merge multiple PDBs into a single PDB");
120
121cl::SubCommand ExplainSubcommand("explain",
122                                 "Explain the meaning of a file offset");
123
124cl::SubCommand ExportSubcommand("export",
125                                "Write binary data from a stream to a file");
126
127cl::OptionCategory TypeCategory("Symbol Type Options");
128cl::OptionCategory FilterCategory("Filtering and Sorting Options");
129cl::OptionCategory OtherOptions("Other Options");
130
131cl::ValuesClass ChunkValues = cl::values(
132    clEnumValN(ModuleSubsection::CrossScopeExports, "cme",
133               "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
134    clEnumValN(ModuleSubsection::CrossScopeImports, "cmi",
135               "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
136    clEnumValN(ModuleSubsection::FileChecksums, "fc",
137               "File checksums (DEBUG_S_CHECKSUMS subsection)"),
138    clEnumValN(ModuleSubsection::InlineeLines, "ilines",
139               "Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
140    clEnumValN(ModuleSubsection::Lines, "lines",
141               "Lines (DEBUG_S_LINES subsection)"),
142    clEnumValN(ModuleSubsection::StringTable, "strings",
143               "String Table (DEBUG_S_STRINGTABLE subsection) (not "
144               "typically present in PDB file)"),
145    clEnumValN(ModuleSubsection::FrameData, "frames",
146               "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
147    clEnumValN(ModuleSubsection::Symbols, "symbols",
148               "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
149               "present in PDB file)"),
150    clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas",
151               "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"),
152    clEnumValN(ModuleSubsection::Unknown, "unknown",
153               "Any subsection not covered by another option"),
154    clEnumValN(ModuleSubsection::All, "all", "All known subsections"));
155
156namespace diadump {
157cl::list<std::string> InputFilenames(cl::Positional,
158                                     cl::desc("<input PDB files>"),
159                                     cl::OneOrMore, cl::sub(DiaDumpSubcommand));
160
161cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
162                     cl::sub(DiaDumpSubcommand));
163
164static cl::opt<bool>
165    ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"),
166                       cl::sub(DiaDumpSubcommand));
167static cl::opt<bool> NoSymIndexIds(
168    "no-ids",
169    cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"),
170    cl::sub(DiaDumpSubcommand));
171
172static cl::opt<bool>
173    Recurse("recurse",
174            cl::desc("When dumping a SymIndexId, dump the full details of the "
175                     "corresponding record"),
176            cl::sub(DiaDumpSubcommand));
177
178static cl::opt<bool> Enums("enums", cl::desc("Dump enum types"),
179                           cl::sub(DiaDumpSubcommand));
180static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),
181                              cl::sub(DiaDumpSubcommand));
182static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),
183                          cl::sub(DiaDumpSubcommand));
184static cl::opt<bool> Compilands("compilands",
185                                cl::desc("Dump compiland information"),
186                                cl::sub(DiaDumpSubcommand));
187static cl::opt<bool> Funcsigs("funcsigs",
188                              cl::desc("Dump function signature information"),
189                              cl::sub(DiaDumpSubcommand));
190static cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"),
191                            cl::sub(DiaDumpSubcommand));
192static cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"),
193                              cl::sub(DiaDumpSubcommand));
194static cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"),
195                              cl::sub(DiaDumpSubcommand));
196} // namespace diadump
197
198namespace pretty {
199cl::list<std::string> InputFilenames(cl::Positional,
200                                     cl::desc("<input PDB files>"),
201                                     cl::OneOrMore, cl::sub(PrettySubcommand));
202
203cl::opt<bool> InjectedSources("injected-sources",
204                              cl::desc("Display injected sources"),
205                              cl::cat(OtherOptions), cl::sub(PrettySubcommand));
206cl::opt<bool> ShowInjectedSourceContent(
207    "injected-source-content",
208    cl::desc("When displaying an injected source, display the file content"),
209    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
210
211cl::list<std::string> WithName(
212    "with-name",
213    cl::desc("Display any symbol or type with the specified exact name"),
214    cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
215
216cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
217                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
218cl::opt<bool> Symbols("module-syms",
219                      cl::desc("Display symbols for each compiland"),
220                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
221cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
222                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
223cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
224                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
225cl::list<SymLevel> SymTypes(
226    "sym-types", cl::desc("Type of symbols to dump (default all)"),
227    cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore,
228    cl::values(
229        clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),
230        clEnumValN(SymLevel::Data, "data", "Display data symbols"),
231        clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),
232        clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));
233
234cl::opt<bool>
235    Types("types",
236          cl::desc("Display all types (implies -classes, -enums, -typedefs)"),
237          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
238cl::opt<bool> Classes("classes", cl::desc("Display class types"),
239                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
240cl::opt<bool> Enums("enums", cl::desc("Display enum types"),
241                    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
242cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
243                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
244cl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"),
245                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
246cl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"),
247                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
248cl::opt<bool> Arrays("arrays", cl::desc("Display arrays"),
249                     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
250cl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"),
251                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
252
253cl::opt<SymbolSortMode> SymbolOrder(
254    "symbol-order", cl::desc("symbol sort order"),
255    cl::init(SymbolSortMode::None),
256    cl::values(clEnumValN(SymbolSortMode::None, "none",
257                          "Undefined / no particular sort order"),
258               clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),
259               clEnumValN(SymbolSortMode::Size, "size",
260                          "Sort symbols by size")),
261    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
262
263cl::opt<ClassSortMode> ClassOrder(
264    "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
265    cl::values(
266        clEnumValN(ClassSortMode::None, "none",
267                   "Undefined / no particular sort order"),
268        clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
269        clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
270        clEnumValN(ClassSortMode::Padding, "padding",
271                   "Sort classes by amount of padding"),
272        clEnumValN(ClassSortMode::PaddingPct, "padding-pct",
273                   "Sort classes by percentage of space consumed by padding"),
274        clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",
275                   "Sort classes by amount of immediate padding"),
276        clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",
277                   "Sort classes by percentage of space consumed by immediate "
278                   "padding")),
279    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
280
281cl::opt<ClassDefinitionFormat> ClassFormat(
282    "class-definitions", cl::desc("Class definition format"),
283    cl::init(ClassDefinitionFormat::All),
284    cl::values(
285        clEnumValN(ClassDefinitionFormat::All, "all",
286                   "Display all class members including data, constants, "
287                   "typedefs, functions, etc"),
288        clEnumValN(ClassDefinitionFormat::Layout, "layout",
289                   "Only display members that contribute to class size."),
290        clEnumValN(ClassDefinitionFormat::None, "none",
291                   "Don't display class definitions")),
292    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
293cl::opt<uint32_t> ClassRecursionDepth(
294    "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),
295    cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));
296
297cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
298                    cl::sub(PrettySubcommand));
299cl::opt<bool>
300    All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
301        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
302
303cl::opt<uint64_t> LoadAddress(
304    "load-address",
305    cl::desc("Assume the module is loaded at the specified address"),
306    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
307cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
308                     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
309cl::opt<cl::boolOrDefault>
310    ColorOutput("color-output",
311                cl::desc("Override use of color (default = isatty)"),
312                cl::cat(OtherOptions), cl::sub(PrettySubcommand));
313cl::list<std::string> ExcludeTypes(
314    "exclude-types", cl::desc("Exclude types by regular expression"),
315    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
316cl::list<std::string> ExcludeSymbols(
317    "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
318    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
319cl::list<std::string> ExcludeCompilands(
320    "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
321    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
322
323cl::list<std::string> IncludeTypes(
324    "include-types",
325    cl::desc("Include only types which match a regular expression"),
326    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
327cl::list<std::string> IncludeSymbols(
328    "include-symbols",
329    cl::desc("Include only symbols which match a regular expression"),
330    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
331cl::list<std::string> IncludeCompilands(
332    "include-compilands",
333    cl::desc("Include only compilands those which match a regular expression"),
334    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
335cl::opt<uint32_t> SizeThreshold(
336    "min-type-size", cl::desc("Displays only those types which are greater "
337                              "than or equal to the specified size."),
338    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
339cl::opt<uint32_t> PaddingThreshold(
340    "min-class-padding", cl::desc("Displays only those classes which have at "
341                                  "least the specified amount of padding."),
342    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
343cl::opt<uint32_t> ImmediatePaddingThreshold(
344    "min-class-padding-imm",
345    cl::desc("Displays only those classes which have at least the specified "
346             "amount of immediate padding, ignoring padding internal to bases "
347             "and aggregates."),
348    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
349
350cl::opt<bool> ExcludeCompilerGenerated(
351    "no-compiler-generated",
352    cl::desc("Don't show compiler generated types and symbols"),
353    cl::cat(FilterCategory), cl::sub(PrettySubcommand));
354cl::opt<bool>
355    ExcludeSystemLibraries("no-system-libs",
356                           cl::desc("Don't show symbols from system libraries"),
357                           cl::cat(FilterCategory), cl::sub(PrettySubcommand));
358
359cl::opt<bool> NoEnumDefs("no-enum-definitions",
360                         cl::desc("Don't display full enum definitions"),
361                         cl::cat(FilterCategory), cl::sub(PrettySubcommand));
362}
363
364cl::OptionCategory FileOptions("Module & File Options");
365
366namespace bytes {
367cl::OptionCategory MsfBytes("MSF File Options");
368cl::OptionCategory DbiBytes("Dbi Stream Options");
369cl::OptionCategory PdbBytes("PDB Stream Options");
370cl::OptionCategory Types("Type Options");
371cl::OptionCategory ModuleCategory("Module Options");
372
373llvm::Optional<NumberRange> DumpBlockRange;
374llvm::Optional<NumberRange> DumpByteRange;
375
376cl::opt<std::string> DumpBlockRangeOpt(
377    "block-range", cl::value_desc("start[-end]"),
378    cl::desc("Dump binary data from specified range of blocks."),
379    cl::sub(BytesSubcommand), cl::cat(MsfBytes));
380
381cl::opt<std::string>
382    DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),
383                     cl::desc("Dump binary data from specified range of bytes"),
384                     cl::sub(BytesSubcommand), cl::cat(MsfBytes));
385
386cl::list<std::string>
387    DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
388                   cl::desc("Dump binary data from specified streams.  Format "
389                            "is SN[:Start][@Size]"),
390                   cl::sub(BytesSubcommand), cl::cat(MsfBytes));
391
392cl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),
393                      cl::sub(BytesSubcommand), cl::cat(PdbBytes));
394cl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"),
395                  cl::sub(BytesSubcommand), cl::cat(MsfBytes));
396
397cl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"),
398                                   cl::sub(BytesSubcommand), cl::cat(DbiBytes));
399cl::opt<bool> SectionMap("sm", cl::desc("Dump section map"),
400                         cl::sub(BytesSubcommand), cl::cat(DbiBytes));
401cl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"),
402                          cl::sub(BytesSubcommand), cl::cat(DbiBytes));
403cl::opt<bool> FileInfo("files", cl::desc("Dump source file info"),
404                       cl::sub(BytesSubcommand), cl::cat(DbiBytes));
405cl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),
406                            cl::sub(BytesSubcommand), cl::cat(DbiBytes));
407cl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),
408                     cl::sub(BytesSubcommand), cl::cat(DbiBytes));
409
410cl::list<uint32_t>
411    TypeIndex("type",
412              cl::desc("Dump the type record with the given type index"),
413              cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
414              cl::cat(TypeCategory));
415cl::list<uint32_t>
416    IdIndex("id", cl::desc("Dump the id record with the given type index"),
417            cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
418            cl::cat(TypeCategory));
419
420cl::opt<uint32_t> ModuleIndex(
421    "mod",
422    cl::desc(
423        "Limit options in the Modules category to the specified module index"),
424    cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
425cl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"),
426                         cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
427cl::opt<bool> ModuleC11("c11-chunks", cl::Hidden,
428                        cl::desc("Dump C11 CodeView debug chunks"),
429                        cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
430cl::opt<bool> ModuleC13("chunks",
431                        cl::desc("Dump C13 CodeView debug chunk subsection"),
432                        cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
433cl::opt<bool> SplitChunks(
434    "split-chunks",
435    cl::desc(
436        "When dumping debug chunks, show a different section for each chunk"),
437    cl::sub(BytesSubcommand), cl::cat(ModuleCategory));
438cl::list<std::string> InputFilenames(cl::Positional,
439                                     cl::desc("<input PDB files>"),
440                                     cl::OneOrMore, cl::sub(BytesSubcommand));
441
442} // namespace bytes
443
444namespace dump {
445
446cl::OptionCategory MsfOptions("MSF Container Options");
447cl::OptionCategory TypeOptions("Type Record Options");
448cl::OptionCategory SymbolOptions("Symbol Options");
449cl::OptionCategory MiscOptions("Miscellaneous Options");
450
451// MSF OPTIONS
452cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),
453                          cl::cat(MsfOptions), cl::sub(DumpSubcommand));
454cl::opt<bool> DumpStreams("streams",
455                          cl::desc("dump summary of the PDB streams"),
456                          cl::cat(MsfOptions), cl::sub(DumpSubcommand));
457cl::opt<bool> DumpStreamBlocks(
458    "stream-blocks",
459    cl::desc("Add block information to the output of -streams"),
460    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
461cl::opt<bool> DumpSymbolStats(
462    "sym-stats",
463    cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),
464    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
465cl::opt<bool> DumpTypeStats(
466    "type-stats",
467    cl::desc("Dump a detailed breakdown of type usage/size"),
468    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
469cl::opt<bool> DumpUdtStats(
470    "udt-stats",
471    cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
472    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
473
474// TYPE OPTIONS
475cl::opt<bool> DumpTypes("types",
476                        cl::desc("dump CodeView type records from TPI stream"),
477                        cl::cat(TypeOptions), cl::sub(DumpSubcommand));
478cl::opt<bool> DumpTypeData(
479    "type-data",
480    cl::desc("dump CodeView type record raw bytes from TPI stream"),
481    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
482cl::opt<bool>
483    DumpTypeRefStats("type-ref-stats",
484                     cl::desc("dump statistics on the number and size of types "
485                              "transitively referenced by symbol records"),
486                     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
487
488cl::opt<bool> DumpTypeExtras("type-extras",
489                             cl::desc("dump type hashes and index offsets"),
490                             cl::cat(TypeOptions), cl::sub(DumpSubcommand));
491
492cl::opt<bool> DontResolveForwardRefs(
493    "dont-resolve-forward-refs",
494    cl::desc("When dumping type records for classes, unions, enums, and "
495             "structs, don't try to resolve forward references"),
496    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
497
498cl::list<uint32_t> DumpTypeIndex(
499    "type-index", cl::ZeroOrMore, cl::CommaSeparated,
500    cl::desc("only dump types with the specified hexadecimal type index"),
501    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
502
503cl::opt<bool> DumpIds("ids",
504                      cl::desc("dump CodeView type records from IPI stream"),
505                      cl::cat(TypeOptions), cl::sub(DumpSubcommand));
506cl::opt<bool>
507    DumpIdData("id-data",
508               cl::desc("dump CodeView type record raw bytes from IPI stream"),
509               cl::cat(TypeOptions), cl::sub(DumpSubcommand));
510
511cl::opt<bool> DumpIdExtras("id-extras",
512                           cl::desc("dump id hashes and index offsets"),
513                           cl::cat(TypeOptions), cl::sub(DumpSubcommand));
514cl::list<uint32_t> DumpIdIndex(
515    "id-index", cl::ZeroOrMore, cl::CommaSeparated,
516    cl::desc("only dump ids with the specified hexadecimal type index"),
517    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
518
519cl::opt<bool> DumpTypeDependents(
520    "dependents",
521    cl::desc("In conjunection with -type-index and -id-index, dumps the entire "
522             "dependency graph for the specified index instead of "
523             "just the single record with the specified index"),
524    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
525
526// SYMBOL OPTIONS
527cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
528                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
529cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
530                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
531cl::list<std::string> DumpGlobalNames(
532    "global-name",
533    cl::desc(
534        "With -globals, only dump globals whose name matches the given value"),
535    cl::cat(SymbolOptions), cl::sub(DumpSubcommand), cl::ZeroOrMore);
536cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
537                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
538cl::opt<bool> DumpPublicExtras("public-extras",
539                               cl::desc("dump Publics hashes and address maps"),
540                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
541cl::opt<bool>
542    DumpGSIRecords("gsi-records",
543                   cl::desc("dump public / global common record stream"),
544                   cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
545cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
546                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
547
548cl::opt<bool>
549    DumpSymRecordBytes("sym-data",
550                       cl::desc("dump CodeView symbol record raw bytes"),
551                       cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
552
553cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
554                      cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
555
556// MODULE & FILE OPTIONS
557cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
558                          cl::cat(FileOptions), cl::sub(DumpSubcommand));
559cl::opt<bool> DumpModuleFiles(
560    "files",
561    cl::desc("Dump the source files that contribute to each module's."),
562    cl::cat(FileOptions), cl::sub(DumpSubcommand));
563cl::opt<bool> DumpLines(
564    "l",
565    cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
566    cl::cat(FileOptions), cl::sub(DumpSubcommand));
567cl::opt<bool> DumpInlineeLines(
568    "il",
569    cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
570    cl::cat(FileOptions), cl::sub(DumpSubcommand));
571cl::opt<bool> DumpXmi(
572    "xmi",
573    cl::desc(
574        "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
575    cl::cat(FileOptions), cl::sub(DumpSubcommand));
576cl::opt<bool> DumpXme(
577    "xme",
578    cl::desc(
579        "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
580    cl::cat(FileOptions), cl::sub(DumpSubcommand));
581cl::opt<uint32_t> DumpModi("modi", cl::Optional,
582                           cl::desc("For all options that iterate over "
583                                    "modules, limit to the specified module"),
584                           cl::cat(FileOptions), cl::sub(DumpSubcommand));
585cl::opt<bool> JustMyCode("jmc", cl::Optional,
586                         cl::desc("For all options that iterate over modules, "
587                                  "ignore modules from system libraries"),
588                         cl::cat(FileOptions), cl::sub(DumpSubcommand));
589
590// MISCELLANEOUS OPTIONS
591cl::opt<bool> DumpNamedStreams("named-streams",
592                               cl::desc("dump PDB named stream table"),
593                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
594
595cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
596                              cl::cat(MiscOptions), cl::sub(DumpSubcommand));
597cl::opt<bool> DumpStringTableDetails("string-table-details",
598                                     cl::desc("dump PDB String Table Details"),
599                                     cl::cat(MiscOptions),
600                                     cl::sub(DumpSubcommand));
601
602cl::opt<bool> DumpSectionContribs("section-contribs",
603                                  cl::desc("dump section contributions"),
604                                  cl::cat(MiscOptions),
605                                  cl::sub(DumpSubcommand));
606cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
607                             cl::cat(MiscOptions), cl::sub(DumpSubcommand));
608cl::opt<bool> DumpSectionHeaders("section-headers",
609                                 cl::desc("Dump image section headers"),
610                                 cl::cat(MiscOptions), cl::sub(DumpSubcommand));
611
612cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
613                     cl::cat(MiscOptions), cl::sub(DumpSubcommand));
614
615cl::list<std::string> InputFilenames(cl::Positional,
616                                     cl::desc("<input PDB files>"),
617                                     cl::OneOrMore, cl::sub(DumpSubcommand));
618}
619
620namespace yaml2pdb {
621cl::opt<std::string>
622    YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
623                      cl::sub(YamlToPdbSubcommand));
624
625cl::opt<std::string> InputFilename(cl::Positional,
626                                   cl::desc("<input YAML file>"), cl::Required,
627                                   cl::sub(YamlToPdbSubcommand));
628}
629
630namespace pdb2yaml {
631cl::opt<bool> All("all",
632                  cl::desc("Dump everything we know how to dump."),
633                  cl::sub(PdbToYamlSubcommand), cl::init(false));
634cl::opt<bool> NoFileHeaders("no-file-headers",
635                            cl::desc("Do not dump MSF file headers"),
636                            cl::sub(PdbToYamlSubcommand), cl::init(false));
637cl::opt<bool> Minimal("minimal",
638                      cl::desc("Don't write fields with default values"),
639                      cl::sub(PdbToYamlSubcommand), cl::init(false));
640
641cl::opt<bool> StreamMetadata(
642    "stream-metadata",
643    cl::desc("Dump the number of streams and each stream's size"),
644    cl::sub(PdbToYamlSubcommand), cl::init(false));
645cl::opt<bool> StreamDirectory(
646    "stream-directory",
647    cl::desc("Dump each stream's block map (implies -stream-metadata)"),
648    cl::sub(PdbToYamlSubcommand), cl::init(false));
649cl::opt<bool> PdbStream("pdb-stream",
650                        cl::desc("Dump the PDB Stream (Stream 1)"),
651                        cl::sub(PdbToYamlSubcommand), cl::init(false));
652
653cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
654                          cl::sub(PdbToYamlSubcommand), cl::init(false));
655
656cl::opt<bool> DbiStream("dbi-stream",
657                        cl::desc("Dump the DBI Stream Headers (Stream 2)"),
658                        cl::sub(PdbToYamlSubcommand), cl::init(false));
659
660cl::opt<bool> TpiStream("tpi-stream",
661                        cl::desc("Dump the TPI Stream (Stream 3)"),
662                        cl::sub(PdbToYamlSubcommand), cl::init(false));
663
664cl::opt<bool> IpiStream("ipi-stream",
665                        cl::desc("Dump the IPI Stream (Stream 5)"),
666                        cl::sub(PdbToYamlSubcommand), cl::init(false));
667
668cl::opt<bool> PublicsStream("publics-stream",
669                            cl::desc("Dump the Publics Stream"),
670                            cl::sub(PdbToYamlSubcommand), cl::init(false));
671
672// MODULE & FILE OPTIONS
673cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
674                          cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
675cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
676                              cl::cat(FileOptions),
677                              cl::sub(PdbToYamlSubcommand));
678cl::list<ModuleSubsection> DumpModuleSubsections(
679    "subsections", cl::ZeroOrMore, cl::CommaSeparated,
680    cl::desc("dump subsections from each module's debug stream"), ChunkValues,
681    cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
682cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
683                             cl::cat(FileOptions),
684                             cl::sub(PdbToYamlSubcommand));
685
686cl::list<std::string> InputFilename(cl::Positional,
687                                    cl::desc("<input PDB file>"), cl::Required,
688                                    cl::sub(PdbToYamlSubcommand));
689} // namespace pdb2yaml
690
691namespace merge {
692cl::list<std::string> InputFilenames(cl::Positional,
693                                     cl::desc("<input PDB files>"),
694                                     cl::OneOrMore, cl::sub(MergeSubcommand));
695cl::opt<std::string>
696    PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
697                  cl::sub(MergeSubcommand));
698}
699
700namespace explain {
701cl::list<std::string> InputFilename(cl::Positional,
702                                    cl::desc("<input PDB file>"), cl::Required,
703                                    cl::sub(ExplainSubcommand));
704
705cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
706                           cl::sub(ExplainSubcommand), cl::OneOrMore);
707
708cl::opt<InputFileType> InputType(
709    "input-type", cl::desc("Specify how to interpret the input file"),
710    cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
711    cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
712                          "Treat input as a PDB file (default)"),
713               clEnumValN(InputFileType::PDBStream, "pdb-stream",
714                          "Treat input as raw contents of PDB stream"),
715               clEnumValN(InputFileType::DBIStream, "dbi-stream",
716                          "Treat input as raw contents of DBI stream"),
717               clEnumValN(InputFileType::Names, "names-stream",
718                          "Treat input as raw contents of /names named stream"),
719               clEnumValN(InputFileType::ModuleStream, "mod-stream",
720                          "Treat input as raw contents of a module stream")));
721} // namespace explain
722
723namespace exportstream {
724cl::list<std::string> InputFilename(cl::Positional,
725                                    cl::desc("<input PDB file>"), cl::Required,
726                                    cl::sub(ExportSubcommand));
727cl::opt<std::string> OutputFile("out",
728                                cl::desc("The file to write the stream to"),
729                                cl::Required, cl::sub(ExportSubcommand));
730cl::opt<std::string>
731    Stream("stream", cl::Required,
732           cl::desc("The index or name of the stream whose contents to export"),
733           cl::sub(ExportSubcommand));
734cl::opt<bool> ForceName("name",
735                        cl::desc("Force the interpretation of -stream as a "
736                                 "string, even if it is a valid integer"),
737                        cl::sub(ExportSubcommand), cl::Optional,
738                        cl::init(false));
739} // namespace exportstream
740}
741
742static ExitOnError ExitOnErr;
743
744static void yamlToPdb(StringRef Path) {
745  BumpPtrAllocator Allocator;
746  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
747      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
748                                   /*RequiresNullTerminator=*/false);
749
750  if (ErrorOrBuffer.getError()) {
751    ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));
752  }
753
754  std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
755
756  llvm::yaml::Input In(Buffer->getBuffer());
757  pdb::yaml::PdbObject YamlObj(Allocator);
758  In >> YamlObj;
759
760  PDBFileBuilder Builder(Allocator);
761
762  uint32_t BlockSize = 4096;
763  if (YamlObj.Headers.hasValue())
764    BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
765  ExitOnErr(Builder.initialize(BlockSize));
766  // Add each of the reserved streams.  We ignore stream metadata in the
767  // yaml, because we will reconstruct our own view of the streams.  For
768  // example, the YAML may say that there were 20 streams in the original
769  // PDB, but maybe we only dump a subset of those 20 streams, so we will
770  // have fewer, and the ones we do have may end up with different indices
771  // than the ones in the original PDB.  So we just start with a clean slate.
772  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
773    ExitOnErr(Builder.getMsfBuilder().addStream(0));
774
775  StringsAndChecksums Strings;
776  Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
777
778  if (YamlObj.StringTable.hasValue()) {
779    for (auto S : *YamlObj.StringTable)
780      Strings.strings()->insert(S);
781  }
782
783  pdb::yaml::PdbInfoStream DefaultInfoStream;
784  pdb::yaml::PdbDbiStream DefaultDbiStream;
785  pdb::yaml::PdbTpiStream DefaultTpiStream;
786  pdb::yaml::PdbTpiStream DefaultIpiStream;
787
788  const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream);
789
790  auto &InfoBuilder = Builder.getInfoBuilder();
791  InfoBuilder.setAge(Info.Age);
792  InfoBuilder.setGuid(Info.Guid);
793  InfoBuilder.setSignature(Info.Signature);
794  InfoBuilder.setVersion(Info.Version);
795  for (auto F : Info.Features)
796    InfoBuilder.addFeature(F);
797
798  const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
799  auto &DbiBuilder = Builder.getDbiBuilder();
800  DbiBuilder.setAge(Dbi.Age);
801  DbiBuilder.setBuildNumber(Dbi.BuildNumber);
802  DbiBuilder.setFlags(Dbi.Flags);
803  DbiBuilder.setMachineType(Dbi.MachineType);
804  DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
805  DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
806  DbiBuilder.setVersionHeader(Dbi.VerHeader);
807  for (const auto &MI : Dbi.ModInfos) {
808    auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
809    ModiBuilder.setObjFileName(MI.Obj);
810
811    for (auto S : MI.SourceFiles)
812      ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
813    if (MI.Modi.hasValue()) {
814      const auto &ModiStream = *MI.Modi;
815      for (auto Symbol : ModiStream.Symbols) {
816        ModiBuilder.addSymbol(
817            Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
818      }
819    }
820
821    // Each module has its own checksum subsection, so scan for it every time.
822    Strings.setChecksums(nullptr);
823    CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
824
825    auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
826        Allocator, MI.Subsections, Strings));
827    for (auto &SS : CodeViewSubsections) {
828      ModiBuilder.addDebugSubsection(SS);
829    }
830  }
831
832  auto &TpiBuilder = Builder.getTpiBuilder();
833  const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
834  TpiBuilder.setVersionHeader(Tpi.Version);
835  AppendingTypeTableBuilder TS(Allocator);
836  for (const auto &R : Tpi.Records) {
837    CVType Type = R.toCodeViewRecord(TS);
838    TpiBuilder.addTypeRecord(Type.RecordData, None);
839  }
840
841  const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream);
842  auto &IpiBuilder = Builder.getIpiBuilder();
843  IpiBuilder.setVersionHeader(Ipi.Version);
844  for (const auto &R : Ipi.Records) {
845    CVType Type = R.toCodeViewRecord(TS);
846    IpiBuilder.addTypeRecord(Type.RecordData, None);
847  }
848
849  Builder.getStringTableBuilder().setStrings(*Strings.strings());
850
851  codeview::GUID IgnoredOutGuid;
852  ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
853}
854
855static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
856  ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
857
858  NativeSession *NS = static_cast<NativeSession *>(Session.get());
859  return NS->getPDBFile();
860}
861
862static void pdb2Yaml(StringRef Path) {
863  std::unique_ptr<IPDBSession> Session;
864  auto &File = loadPDB(Path, Session);
865
866  auto O = std::make_unique<YAMLOutputStyle>(File);
867  O = std::make_unique<YAMLOutputStyle>(File);
868
869  ExitOnErr(O->dump());
870}
871
872static void dumpRaw(StringRef Path) {
873  InputFile IF = ExitOnErr(InputFile::open(Path));
874
875  auto O = std::make_unique<DumpOutputStyle>(IF);
876  ExitOnErr(O->dump());
877}
878
879static void dumpBytes(StringRef Path) {
880  std::unique_ptr<IPDBSession> Session;
881  auto &File = loadPDB(Path, Session);
882
883  auto O = std::make_unique<BytesOutputStyle>(File);
884
885  ExitOnErr(O->dump());
886}
887
888bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
889  if (SymTypes.empty())
890    return true;
891  if (llvm::find(SymTypes, Search) != SymTypes.end())
892    return true;
893  if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end())
894    return true;
895  return false;
896}
897
898uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
899  auto SymbolType = Symbol.getType();
900  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
901
902  return RawType.getLength();
903}
904
905bool opts::pretty::compareFunctionSymbols(
906    const std::unique_ptr<PDBSymbolFunc> &F1,
907    const std::unique_ptr<PDBSymbolFunc> &F2) {
908  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
909
910  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
911    return F1->getName() < F2->getName();
912
913  // Note that we intentionally sort in descending order on length, since
914  // long functions are more interesting than short functions.
915  return F1->getLength() > F2->getLength();
916}
917
918bool opts::pretty::compareDataSymbols(
919    const std::unique_ptr<PDBSymbolData> &F1,
920    const std::unique_ptr<PDBSymbolData> &F2) {
921  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
922
923  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
924    return F1->getName() < F2->getName();
925
926  // Note that we intentionally sort in descending order on length, since
927  // large types are more interesting than short ones.
928  return getTypeLength(*F1) > getTypeLength(*F2);
929}
930
931static std::string stringOr(std::string Str, std::string IfEmpty) {
932  return (Str.empty()) ? IfEmpty : Str;
933}
934
935static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
936  auto Sources = Session.getInjectedSources();
937  if (!Sources || !Sources->getChildCount()) {
938    Printer.printLine("There are no injected sources.");
939    return;
940  }
941
942  while (auto IS = Sources->getNext()) {
943    Printer.NewLine();
944    std::string File = stringOr(IS->getFileName(), "<null>");
945    uint64_t Size = IS->getCodeByteSize();
946    std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
947    std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
948    uint32_t CRC = IS->getCrc32();
949
950    WithColor(Printer, PDB_ColorItem::Path).get() << File;
951    Printer << " (";
952    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
953    Printer << " bytes): ";
954    WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
955    Printer << "=";
956    WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
957    Printer << ", ";
958    WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
959    Printer << "=";
960    WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
961    Printer << ", ";
962    WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
963    Printer << "=";
964    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
965    Printer << ", ";
966    WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
967    Printer << "=";
968    dumpPDBSourceCompression(
969        WithColor(Printer, PDB_ColorItem::LiteralValue).get(),
970        IS->getCompression());
971
972    if (!opts::pretty::ShowInjectedSourceContent)
973      continue;
974
975    // Set the indent level to 0 when printing file content.
976    int Indent = Printer.getIndentLevel();
977    Printer.Unindent(Indent);
978
979    if (IS->getCompression() == PDB_SourceCompression::None)
980      Printer.printLine(IS->getCode());
981    else
982      Printer.formatBinary("Compressed data",
983                           arrayRefFromStringRef(IS->getCode()),
984                           /*StartOffset=*/0);
985
986    // Re-indent back to the original level.
987    Printer.Indent(Indent);
988  }
989}
990
991template <typename OuterT, typename ChildT>
992void diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,
993                     PdbSymbolIdField Recurse) {
994  OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);
995  if (!ConcreteOuter)
996    return;
997
998  auto Children = ConcreteOuter->template findAllChildren<ChildT>();
999  while (auto Child = Children->getNext()) {
1000    outs() << "  {";
1001    Child->defaultDump(outs(), 4, Ids, Recurse);
1002    outs() << "\n  }\n";
1003  }
1004}
1005
1006static void dumpDia(StringRef Path) {
1007  std::unique_ptr<IPDBSession> Session;
1008
1009  const auto ReaderType =
1010      opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1011  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1012
1013  auto GlobalScope = Session->getGlobalScope();
1014
1015  std::vector<PDB_SymType> SymTypes;
1016
1017  if (opts::diadump::Compilands)
1018    SymTypes.push_back(PDB_SymType::Compiland);
1019  if (opts::diadump::Enums)
1020    SymTypes.push_back(PDB_SymType::Enum);
1021  if (opts::diadump::Pointers)
1022    SymTypes.push_back(PDB_SymType::PointerType);
1023  if (opts::diadump::UDTs)
1024    SymTypes.push_back(PDB_SymType::UDT);
1025  if (opts::diadump::Funcsigs)
1026    SymTypes.push_back(PDB_SymType::FunctionSig);
1027  if (opts::diadump::Arrays)
1028    SymTypes.push_back(PDB_SymType::ArrayType);
1029  if (opts::diadump::VTShapes)
1030    SymTypes.push_back(PDB_SymType::VTableShape);
1031  if (opts::diadump::Typedefs)
1032    SymTypes.push_back(PDB_SymType::Typedef);
1033  PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
1034                                                      : PdbSymbolIdField::All;
1035
1036  PdbSymbolIdField Recurse = PdbSymbolIdField::None;
1037  if (opts::diadump::Recurse)
1038    Recurse = PdbSymbolIdField::All;
1039  if (!opts::diadump::ShowClassHierarchy)
1040    Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);
1041
1042  for (PDB_SymType ST : SymTypes) {
1043    auto Children = GlobalScope->findAllChildren(ST);
1044    while (auto Child = Children->getNext()) {
1045      outs() << "{";
1046      Child->defaultDump(outs(), 2, Ids, Recurse);
1047
1048      diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);
1049      outs() << "\n}\n";
1050    }
1051  }
1052}
1053
1054static void dumpPretty(StringRef Path) {
1055  std::unique_ptr<IPDBSession> Session;
1056
1057  const auto ReaderType =
1058      opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1059  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1060
1061  if (opts::pretty::LoadAddress)
1062    Session->setLoadAddress(opts::pretty::LoadAddress);
1063
1064  auto &Stream = outs();
1065  const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
1066                            ? Stream.has_colors()
1067                            : opts::pretty::ColorOutput == cl::BOU_TRUE;
1068  LinePrinter Printer(2, UseColor, Stream);
1069
1070  auto GlobalScope(Session->getGlobalScope());
1071  if (!GlobalScope)
1072    return;
1073  std::string FileName(GlobalScope->getSymbolsFileName());
1074
1075  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
1076  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
1077  Printer.Indent();
1078  uint64_t FileSize = 0;
1079
1080  Printer.NewLine();
1081  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
1082  if (!sys::fs::file_size(FileName, FileSize)) {
1083    Printer << ": " << FileSize << " bytes";
1084  } else {
1085    Printer << ": (Unable to obtain file size)";
1086  }
1087
1088  Printer.NewLine();
1089  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
1090  Printer << ": " << GlobalScope->getGuid();
1091
1092  Printer.NewLine();
1093  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
1094  Printer << ": " << GlobalScope->getAge();
1095
1096  Printer.NewLine();
1097  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
1098  Printer << ": ";
1099  if (GlobalScope->hasCTypes())
1100    outs() << "HasCTypes ";
1101  if (GlobalScope->hasPrivateSymbols())
1102    outs() << "HasPrivateSymbols ";
1103  Printer.Unindent();
1104
1105  if (!opts::pretty::WithName.empty()) {
1106    Printer.NewLine();
1107    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1108        << "---SYMBOLS & TYPES BY NAME---";
1109
1110    for (StringRef Name : opts::pretty::WithName) {
1111      auto Symbols = GlobalScope->findChildren(
1112          PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
1113      if (!Symbols || Symbols->getChildCount() == 0) {
1114        Printer.formatLine("[not found] - {0}", Name);
1115        continue;
1116      }
1117      Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
1118                         Name);
1119
1120      AutoIndent Indent(Printer);
1121      Printer.NewLine();
1122
1123      while (auto Symbol = Symbols->getNext()) {
1124        switch (Symbol->getSymTag()) {
1125        case PDB_SymType::Typedef: {
1126          TypedefDumper TD(Printer);
1127          std::unique_ptr<PDBSymbolTypeTypedef> T =
1128              llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
1129          TD.start(*T);
1130          break;
1131        }
1132        case PDB_SymType::Enum: {
1133          EnumDumper ED(Printer);
1134          std::unique_ptr<PDBSymbolTypeEnum> E =
1135              llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
1136          ED.start(*E);
1137          break;
1138        }
1139        case PDB_SymType::UDT: {
1140          ClassDefinitionDumper CD(Printer);
1141          std::unique_ptr<PDBSymbolTypeUDT> C =
1142              llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
1143          CD.start(*C);
1144          break;
1145        }
1146        case PDB_SymType::BaseClass:
1147        case PDB_SymType::Friend: {
1148          TypeDumper TD(Printer);
1149          Symbol->dump(TD);
1150          break;
1151        }
1152        case PDB_SymType::Function: {
1153          FunctionDumper FD(Printer);
1154          std::unique_ptr<PDBSymbolFunc> F =
1155              llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
1156          FD.start(*F, FunctionDumper::PointerType::None);
1157          break;
1158        }
1159        case PDB_SymType::Data: {
1160          VariableDumper VD(Printer);
1161          std::unique_ptr<PDBSymbolData> D =
1162              llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
1163          VD.start(*D);
1164          break;
1165        }
1166        case PDB_SymType::PublicSymbol: {
1167          ExternalSymbolDumper ED(Printer);
1168          std::unique_ptr<PDBSymbolPublicSymbol> PS =
1169              llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
1170          ED.dump(*PS);
1171          break;
1172        }
1173        default:
1174          llvm_unreachable("Unexpected symbol tag!");
1175        }
1176      }
1177    }
1178    llvm::outs().flush();
1179  }
1180
1181  if (opts::pretty::Compilands) {
1182    Printer.NewLine();
1183    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1184        << "---COMPILANDS---";
1185    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
1186
1187    if (Compilands) {
1188      Printer.Indent();
1189      CompilandDumper Dumper(Printer);
1190      CompilandDumpFlags options = CompilandDumper::Flags::None;
1191      if (opts::pretty::Lines)
1192        options = options | CompilandDumper::Flags::Lines;
1193      while (auto Compiland = Compilands->getNext())
1194        Dumper.start(*Compiland, options);
1195      Printer.Unindent();
1196    }
1197  }
1198
1199  if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
1200      opts::pretty::Funcsigs || opts::pretty::Pointers ||
1201      opts::pretty::Arrays || opts::pretty::VTShapes) {
1202    Printer.NewLine();
1203    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
1204    Printer.Indent();
1205    TypeDumper Dumper(Printer);
1206    Dumper.start(*GlobalScope);
1207    Printer.Unindent();
1208  }
1209
1210  if (opts::pretty::Symbols) {
1211    Printer.NewLine();
1212    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
1213    if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
1214      Printer.Indent();
1215      CompilandDumper Dumper(Printer);
1216      while (auto Compiland = Compilands->getNext())
1217        Dumper.start(*Compiland, true);
1218      Printer.Unindent();
1219    }
1220  }
1221
1222  if (opts::pretty::Globals) {
1223    Printer.NewLine();
1224    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
1225    Printer.Indent();
1226    if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
1227      if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
1228        FunctionDumper Dumper(Printer);
1229        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1230          while (auto Function = Functions->getNext()) {
1231            Printer.NewLine();
1232            Dumper.start(*Function, FunctionDumper::PointerType::None);
1233          }
1234        } else {
1235          std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
1236          while (auto Func = Functions->getNext())
1237            Funcs.push_back(std::move(Func));
1238          llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);
1239          for (const auto &Func : Funcs) {
1240            Printer.NewLine();
1241            Dumper.start(*Func, FunctionDumper::PointerType::None);
1242          }
1243        }
1244      }
1245    }
1246    if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
1247      if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
1248        VariableDumper Dumper(Printer);
1249        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1250          while (auto Var = Vars->getNext())
1251            Dumper.start(*Var);
1252        } else {
1253          std::vector<std::unique_ptr<PDBSymbolData>> Datas;
1254          while (auto Var = Vars->getNext())
1255            Datas.push_back(std::move(Var));
1256          llvm::sort(Datas, opts::pretty::compareDataSymbols);
1257          for (const auto &Var : Datas)
1258            Dumper.start(*Var);
1259        }
1260      }
1261    }
1262    if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
1263      if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
1264        CompilandDumper Dumper(Printer);
1265        while (auto Thunk = Thunks->getNext())
1266          Dumper.dump(*Thunk);
1267      }
1268    }
1269    Printer.Unindent();
1270  }
1271  if (opts::pretty::Externals) {
1272    Printer.NewLine();
1273    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
1274    Printer.Indent();
1275    ExternalSymbolDumper Dumper(Printer);
1276    Dumper.start(*GlobalScope);
1277  }
1278  if (opts::pretty::Lines) {
1279    Printer.NewLine();
1280  }
1281  if (opts::pretty::InjectedSources) {
1282    Printer.NewLine();
1283    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1284        << "---INJECTED SOURCES---";
1285    AutoIndent Indent1(Printer);
1286    dumpInjectedSources(Printer, *Session);
1287  }
1288
1289  Printer.NewLine();
1290  outs().flush();
1291}
1292
1293static void mergePdbs() {
1294  BumpPtrAllocator Allocator;
1295  MergingTypeTableBuilder MergedTpi(Allocator);
1296  MergingTypeTableBuilder MergedIpi(Allocator);
1297
1298  // Create a Tpi and Ipi type table with all types from all input files.
1299  for (const auto &Path : opts::merge::InputFilenames) {
1300    std::unique_ptr<IPDBSession> Session;
1301    auto &File = loadPDB(Path, Session);
1302    SmallVector<TypeIndex, 128> TypeMap;
1303    SmallVector<TypeIndex, 128> IdMap;
1304    if (File.hasPDBTpiStream()) {
1305      auto &Tpi = ExitOnErr(File.getPDBTpiStream());
1306      ExitOnErr(
1307          codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));
1308    }
1309    if (File.hasPDBIpiStream()) {
1310      auto &Ipi = ExitOnErr(File.getPDBIpiStream());
1311      ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
1312                                         Ipi.typeArray()));
1313    }
1314  }
1315
1316  // Then write the PDB.
1317  PDBFileBuilder Builder(Allocator);
1318  ExitOnErr(Builder.initialize(4096));
1319  // Add each of the reserved streams.  We might not put any data in them,
1320  // but at least they have to be present.
1321  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
1322    ExitOnErr(Builder.getMsfBuilder().addStream(0));
1323
1324  auto &DestTpi = Builder.getTpiBuilder();
1325  auto &DestIpi = Builder.getIpiBuilder();
1326  MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
1327    DestTpi.addTypeRecord(Type.RecordData, None);
1328  });
1329  MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
1330    DestIpi.addTypeRecord(Type.RecordData, None);
1331  });
1332  Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
1333
1334  SmallString<64> OutFile(opts::merge::PdbOutputFile);
1335  if (OutFile.empty()) {
1336    OutFile = opts::merge::InputFilenames[0];
1337    llvm::sys::path::replace_extension(OutFile, "merged.pdb");
1338  }
1339
1340  codeview::GUID IgnoredOutGuid;
1341  ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
1342}
1343
1344static void explain() {
1345  std::unique_ptr<IPDBSession> Session;
1346  InputFile IF =
1347      ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
1348
1349  for (uint64_t Off : opts::explain::Offsets) {
1350    auto O = std::make_unique<ExplainOutputStyle>(IF, Off);
1351
1352    ExitOnErr(O->dump());
1353  }
1354}
1355
1356static void exportStream() {
1357  std::unique_ptr<IPDBSession> Session;
1358  PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
1359
1360  std::unique_ptr<MappedBlockStream> SourceStream;
1361  uint32_t Index = 0;
1362  bool Success = false;
1363  std::string OutFileName = opts::exportstream::OutputFile;
1364
1365  if (!opts::exportstream::ForceName) {
1366    // First try to parse it as an integer, if it fails fall back to treating it
1367    // as a named stream.
1368    if (to_integer(opts::exportstream::Stream, Index)) {
1369      if (Index >= File.getNumStreams()) {
1370        errs() << "Error: " << Index << " is not a valid stream index.\n";
1371        exit(1);
1372      }
1373      Success = true;
1374      outs() << "Dumping contents of stream index " << Index << " to file "
1375             << OutFileName << ".\n";
1376    }
1377  }
1378
1379  if (!Success) {
1380    InfoStream &IS = cantFail(File.getPDBInfoStream());
1381    Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
1382    outs() << "Dumping contents of stream '" << opts::exportstream::Stream
1383           << "' (index " << Index << ") to file " << OutFileName << ".\n";
1384  }
1385
1386  SourceStream = File.createIndexedStream(Index);
1387  auto OutFile = ExitOnErr(
1388      FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
1389  FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
1390  BinaryStreamWriter Writer(DestStream);
1391  ExitOnErr(Writer.writeStreamRef(*SourceStream));
1392  ExitOnErr(DestStream.commit());
1393}
1394
1395static bool parseRange(StringRef Str,
1396                       Optional<opts::bytes::NumberRange> &Parsed) {
1397  if (Str.empty())
1398    return true;
1399
1400  llvm::Regex R("^([^-]+)(-([^-]+))?$");
1401  llvm::SmallVector<llvm::StringRef, 2> Matches;
1402  if (!R.match(Str, &Matches))
1403    return false;
1404
1405  Parsed.emplace();
1406  if (!to_integer(Matches[1], Parsed->Min))
1407    return false;
1408
1409  if (!Matches[3].empty()) {
1410    Parsed->Max.emplace();
1411    if (!to_integer(Matches[3], *Parsed->Max))
1412      return false;
1413  }
1414  return true;
1415}
1416
1417static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
1418  // If this list contains "All" plus some other stuff, remove the other stuff
1419  // and just keep "All" in the list.
1420  if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))
1421    return;
1422  Chunks.reset();
1423  Chunks.push_back(opts::ModuleSubsection::All);
1424}
1425
1426int main(int Argc, const char **Argv) {
1427  InitLLVM X(Argc, Argv);
1428  ExitOnErr.setBanner("llvm-pdbutil: ");
1429
1430  cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
1431
1432  if (opts::BytesSubcommand) {
1433    if (!parseRange(opts::bytes::DumpBlockRangeOpt,
1434                    opts::bytes::DumpBlockRange)) {
1435      errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
1436             << "' invalid format.\n";
1437      errs().flush();
1438      exit(1);
1439    }
1440    if (!parseRange(opts::bytes::DumpByteRangeOpt,
1441                    opts::bytes::DumpByteRange)) {
1442      errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
1443             << "' invalid format.\n";
1444      errs().flush();
1445      exit(1);
1446    }
1447  }
1448
1449  if (opts::DumpSubcommand) {
1450    if (opts::dump::RawAll) {
1451      opts::dump::DumpGlobals = true;
1452      opts::dump::DumpFpo = true;
1453      opts::dump::DumpInlineeLines = true;
1454      opts::dump::DumpIds = true;
1455      opts::dump::DumpIdExtras = true;
1456      opts::dump::DumpLines = true;
1457      opts::dump::DumpModules = true;
1458      opts::dump::DumpModuleFiles = true;
1459      opts::dump::DumpPublics = true;
1460      opts::dump::DumpSectionContribs = true;
1461      opts::dump::DumpSectionHeaders = true;
1462      opts::dump::DumpSectionMap = true;
1463      opts::dump::DumpStreams = true;
1464      opts::dump::DumpStreamBlocks = true;
1465      opts::dump::DumpStringTable = true;
1466      opts::dump::DumpStringTableDetails = true;
1467      opts::dump::DumpSummary = true;
1468      opts::dump::DumpSymbols = true;
1469      opts::dump::DumpSymbolStats = true;
1470      opts::dump::DumpTypes = true;
1471      opts::dump::DumpTypeExtras = true;
1472      opts::dump::DumpUdtStats = true;
1473      opts::dump::DumpXme = true;
1474      opts::dump::DumpXmi = true;
1475    }
1476  }
1477  if (opts::PdbToYamlSubcommand) {
1478    if (opts::pdb2yaml::All) {
1479      opts::pdb2yaml::StreamMetadata = true;
1480      opts::pdb2yaml::StreamDirectory = true;
1481      opts::pdb2yaml::PdbStream = true;
1482      opts::pdb2yaml::StringTable = true;
1483      opts::pdb2yaml::DbiStream = true;
1484      opts::pdb2yaml::TpiStream = true;
1485      opts::pdb2yaml::IpiStream = true;
1486      opts::pdb2yaml::PublicsStream = true;
1487      opts::pdb2yaml::DumpModules = true;
1488      opts::pdb2yaml::DumpModuleFiles = true;
1489      opts::pdb2yaml::DumpModuleSyms = true;
1490      opts::pdb2yaml::DumpModuleSubsections.push_back(
1491          opts::ModuleSubsection::All);
1492    }
1493    simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);
1494
1495    if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
1496      opts::pdb2yaml::DumpModules = true;
1497
1498    if (opts::pdb2yaml::DumpModules)
1499      opts::pdb2yaml::DbiStream = true;
1500  }
1501
1502  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
1503
1504  if (opts::PdbToYamlSubcommand) {
1505    pdb2Yaml(opts::pdb2yaml::InputFilename.front());
1506  } else if (opts::YamlToPdbSubcommand) {
1507    if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
1508      SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
1509      sys::path::replace_extension(OutputFilename, ".pdb");
1510      opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str();
1511    }
1512    yamlToPdb(opts::yaml2pdb::InputFilename);
1513  } else if (opts::DiaDumpSubcommand) {
1514    llvm::for_each(opts::diadump::InputFilenames, dumpDia);
1515  } else if (opts::PrettySubcommand) {
1516    if (opts::pretty::Lines)
1517      opts::pretty::Compilands = true;
1518
1519    if (opts::pretty::All) {
1520      opts::pretty::Compilands = true;
1521      opts::pretty::Symbols = true;
1522      opts::pretty::Globals = true;
1523      opts::pretty::Types = true;
1524      opts::pretty::Externals = true;
1525      opts::pretty::Lines = true;
1526    }
1527
1528    if (opts::pretty::Types) {
1529      opts::pretty::Classes = true;
1530      opts::pretty::Typedefs = true;
1531      opts::pretty::Enums = true;
1532      opts::pretty::Pointers = true;
1533      opts::pretty::Funcsigs = true;
1534    }
1535
1536    // When adding filters for excluded compilands and types, we need to
1537    // remember that these are regexes.  So special characters such as * and \
1538    // need to be escaped in the regex.  In the case of a literal \, this means
1539    // it needs to be escaped again in the C++.  So matching a single \ in the
1540    // input requires 4 \es in the C++.
1541    if (opts::pretty::ExcludeCompilerGenerated) {
1542      opts::pretty::ExcludeTypes.push_back("__vc_attributes");
1543      opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
1544    }
1545    if (opts::pretty::ExcludeSystemLibraries) {
1546      opts::pretty::ExcludeCompilands.push_back(
1547          "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
1548      opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
1549      opts::pretty::ExcludeCompilands.push_back(
1550          "d:\\\\th.obj.x86fre\\\\minkernel");
1551    }
1552    llvm::for_each(opts::pretty::InputFilenames, dumpPretty);
1553  } else if (opts::DumpSubcommand) {
1554    llvm::for_each(opts::dump::InputFilenames, dumpRaw);
1555  } else if (opts::BytesSubcommand) {
1556    llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
1557  } else if (opts::MergeSubcommand) {
1558    if (opts::merge::InputFilenames.size() < 2) {
1559      errs() << "merge subcommand requires at least 2 input files.\n";
1560      exit(1);
1561    }
1562    mergePdbs();
1563  } else if (opts::ExplainSubcommand) {
1564    explain();
1565  } else if (opts::ExportSubcommand) {
1566    exportStream();
1567  }
1568
1569  outs().flush();
1570  return 0;
1571}
1572