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> DumpIDStats(
470    "id-stats",
471    cl::desc("Dump a detailed breakdown of IPI types usage/size"),
472    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
473cl::opt<bool> DumpUdtStats(
474    "udt-stats",
475    cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
476    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
477
478// TYPE OPTIONS
479cl::opt<bool> DumpTypes("types",
480                        cl::desc("dump CodeView type records from TPI stream"),
481                        cl::cat(TypeOptions), cl::sub(DumpSubcommand));
482cl::opt<bool> DumpTypeData(
483    "type-data",
484    cl::desc("dump CodeView type record raw bytes from TPI stream"),
485    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
486cl::opt<bool>
487    DumpTypeRefStats("type-ref-stats",
488                     cl::desc("dump statistics on the number and size of types "
489                              "transitively referenced by symbol records"),
490                     cl::cat(TypeOptions), cl::sub(DumpSubcommand));
491
492cl::opt<bool> DumpTypeExtras("type-extras",
493                             cl::desc("dump type hashes and index offsets"),
494                             cl::cat(TypeOptions), cl::sub(DumpSubcommand));
495
496cl::opt<bool> DontResolveForwardRefs(
497    "dont-resolve-forward-refs",
498    cl::desc("When dumping type records for classes, unions, enums, and "
499             "structs, don't try to resolve forward references"),
500    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
501
502cl::list<uint32_t> DumpTypeIndex(
503    "type-index", cl::ZeroOrMore, cl::CommaSeparated,
504    cl::desc("only dump types with the specified hexadecimal type index"),
505    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
506
507cl::opt<bool> DumpIds("ids",
508                      cl::desc("dump CodeView type records from IPI stream"),
509                      cl::cat(TypeOptions), cl::sub(DumpSubcommand));
510cl::opt<bool>
511    DumpIdData("id-data",
512               cl::desc("dump CodeView type record raw bytes from IPI stream"),
513               cl::cat(TypeOptions), cl::sub(DumpSubcommand));
514
515cl::opt<bool> DumpIdExtras("id-extras",
516                           cl::desc("dump id hashes and index offsets"),
517                           cl::cat(TypeOptions), cl::sub(DumpSubcommand));
518cl::list<uint32_t> DumpIdIndex(
519    "id-index", cl::ZeroOrMore, cl::CommaSeparated,
520    cl::desc("only dump ids with the specified hexadecimal type index"),
521    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
522
523cl::opt<bool> DumpTypeDependents(
524    "dependents",
525    cl::desc("In conjunection with -type-index and -id-index, dumps the entire "
526             "dependency graph for the specified index instead of "
527             "just the single record with the specified index"),
528    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
529
530// SYMBOL OPTIONS
531cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
532                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
533cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
534                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
535cl::list<std::string> DumpGlobalNames(
536    "global-name",
537    cl::desc(
538        "With -globals, only dump globals whose name matches the given value"),
539    cl::cat(SymbolOptions), cl::sub(DumpSubcommand), cl::ZeroOrMore);
540cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
541                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
542cl::opt<bool> DumpPublicExtras("public-extras",
543                               cl::desc("dump Publics hashes and address maps"),
544                               cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
545cl::opt<bool>
546    DumpGSIRecords("gsi-records",
547                   cl::desc("dump public / global common record stream"),
548                   cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
549cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
550                          cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
551
552cl::opt<bool>
553    DumpSymRecordBytes("sym-data",
554                       cl::desc("dump CodeView symbol record raw bytes"),
555                       cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
556
557cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
558                      cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
559
560// MODULE & FILE OPTIONS
561cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
562                          cl::cat(FileOptions), cl::sub(DumpSubcommand));
563cl::opt<bool> DumpModuleFiles(
564    "files",
565    cl::desc("Dump the source files that contribute to each module's."),
566    cl::cat(FileOptions), cl::sub(DumpSubcommand));
567cl::opt<bool> DumpLines(
568    "l",
569    cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
570    cl::cat(FileOptions), cl::sub(DumpSubcommand));
571cl::opt<bool> DumpInlineeLines(
572    "il",
573    cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
574    cl::cat(FileOptions), cl::sub(DumpSubcommand));
575cl::opt<bool> DumpXmi(
576    "xmi",
577    cl::desc(
578        "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
579    cl::cat(FileOptions), cl::sub(DumpSubcommand));
580cl::opt<bool> DumpXme(
581    "xme",
582    cl::desc(
583        "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
584    cl::cat(FileOptions), cl::sub(DumpSubcommand));
585cl::opt<uint32_t> DumpModi("modi", cl::Optional,
586                           cl::desc("For all options that iterate over "
587                                    "modules, limit to the specified module"),
588                           cl::cat(FileOptions), cl::sub(DumpSubcommand));
589cl::opt<bool> JustMyCode("jmc", cl::Optional,
590                         cl::desc("For all options that iterate over modules, "
591                                  "ignore modules from system libraries"),
592                         cl::cat(FileOptions), cl::sub(DumpSubcommand));
593
594// MISCELLANEOUS OPTIONS
595cl::opt<bool> DumpNamedStreams("named-streams",
596                               cl::desc("dump PDB named stream table"),
597                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
598
599cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
600                              cl::cat(MiscOptions), cl::sub(DumpSubcommand));
601cl::opt<bool> DumpStringTableDetails("string-table-details",
602                                     cl::desc("dump PDB String Table Details"),
603                                     cl::cat(MiscOptions),
604                                     cl::sub(DumpSubcommand));
605
606cl::opt<bool> DumpSectionContribs("section-contribs",
607                                  cl::desc("dump section contributions"),
608                                  cl::cat(MiscOptions),
609                                  cl::sub(DumpSubcommand));
610cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
611                             cl::cat(MiscOptions), cl::sub(DumpSubcommand));
612cl::opt<bool> DumpSectionHeaders("section-headers",
613                                 cl::desc("Dump image section headers"),
614                                 cl::cat(MiscOptions), cl::sub(DumpSubcommand));
615
616cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
617                     cl::cat(MiscOptions), cl::sub(DumpSubcommand));
618
619cl::list<std::string> InputFilenames(cl::Positional,
620                                     cl::desc("<input PDB files>"),
621                                     cl::OneOrMore, cl::sub(DumpSubcommand));
622}
623
624namespace yaml2pdb {
625cl::opt<std::string>
626    YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
627                      cl::sub(YamlToPdbSubcommand));
628
629cl::opt<std::string> InputFilename(cl::Positional,
630                                   cl::desc("<input YAML file>"), cl::Required,
631                                   cl::sub(YamlToPdbSubcommand));
632}
633
634namespace pdb2yaml {
635cl::opt<bool> All("all",
636                  cl::desc("Dump everything we know how to dump."),
637                  cl::sub(PdbToYamlSubcommand), cl::init(false));
638cl::opt<bool> NoFileHeaders("no-file-headers",
639                            cl::desc("Do not dump MSF file headers"),
640                            cl::sub(PdbToYamlSubcommand), cl::init(false));
641cl::opt<bool> Minimal("minimal",
642                      cl::desc("Don't write fields with default values"),
643                      cl::sub(PdbToYamlSubcommand), cl::init(false));
644
645cl::opt<bool> StreamMetadata(
646    "stream-metadata",
647    cl::desc("Dump the number of streams and each stream's size"),
648    cl::sub(PdbToYamlSubcommand), cl::init(false));
649cl::opt<bool> StreamDirectory(
650    "stream-directory",
651    cl::desc("Dump each stream's block map (implies -stream-metadata)"),
652    cl::sub(PdbToYamlSubcommand), cl::init(false));
653cl::opt<bool> PdbStream("pdb-stream",
654                        cl::desc("Dump the PDB Stream (Stream 1)"),
655                        cl::sub(PdbToYamlSubcommand), cl::init(false));
656
657cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
658                          cl::sub(PdbToYamlSubcommand), cl::init(false));
659
660cl::opt<bool> DbiStream("dbi-stream",
661                        cl::desc("Dump the DBI Stream Headers (Stream 2)"),
662                        cl::sub(PdbToYamlSubcommand), cl::init(false));
663
664cl::opt<bool> TpiStream("tpi-stream",
665                        cl::desc("Dump the TPI Stream (Stream 3)"),
666                        cl::sub(PdbToYamlSubcommand), cl::init(false));
667
668cl::opt<bool> IpiStream("ipi-stream",
669                        cl::desc("Dump the IPI Stream (Stream 5)"),
670                        cl::sub(PdbToYamlSubcommand), cl::init(false));
671
672cl::opt<bool> PublicsStream("publics-stream",
673                            cl::desc("Dump the Publics Stream"),
674                            cl::sub(PdbToYamlSubcommand), cl::init(false));
675
676// MODULE & FILE OPTIONS
677cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
678                          cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
679cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
680                              cl::cat(FileOptions),
681                              cl::sub(PdbToYamlSubcommand));
682cl::list<ModuleSubsection> DumpModuleSubsections(
683    "subsections", cl::ZeroOrMore, cl::CommaSeparated,
684    cl::desc("dump subsections from each module's debug stream"), ChunkValues,
685    cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
686cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
687                             cl::cat(FileOptions),
688                             cl::sub(PdbToYamlSubcommand));
689
690cl::list<std::string> InputFilename(cl::Positional,
691                                    cl::desc("<input PDB file>"), cl::Required,
692                                    cl::sub(PdbToYamlSubcommand));
693} // namespace pdb2yaml
694
695namespace merge {
696cl::list<std::string> InputFilenames(cl::Positional,
697                                     cl::desc("<input PDB files>"),
698                                     cl::OneOrMore, cl::sub(MergeSubcommand));
699cl::opt<std::string>
700    PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
701                  cl::sub(MergeSubcommand));
702}
703
704namespace explain {
705cl::list<std::string> InputFilename(cl::Positional,
706                                    cl::desc("<input PDB file>"), cl::Required,
707                                    cl::sub(ExplainSubcommand));
708
709cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),
710                           cl::sub(ExplainSubcommand), cl::OneOrMore);
711
712cl::opt<InputFileType> InputType(
713    "input-type", cl::desc("Specify how to interpret the input file"),
714    cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),
715    cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",
716                          "Treat input as a PDB file (default)"),
717               clEnumValN(InputFileType::PDBStream, "pdb-stream",
718                          "Treat input as raw contents of PDB stream"),
719               clEnumValN(InputFileType::DBIStream, "dbi-stream",
720                          "Treat input as raw contents of DBI stream"),
721               clEnumValN(InputFileType::Names, "names-stream",
722                          "Treat input as raw contents of /names named stream"),
723               clEnumValN(InputFileType::ModuleStream, "mod-stream",
724                          "Treat input as raw contents of a module stream")));
725} // namespace explain
726
727namespace exportstream {
728cl::list<std::string> InputFilename(cl::Positional,
729                                    cl::desc("<input PDB file>"), cl::Required,
730                                    cl::sub(ExportSubcommand));
731cl::opt<std::string> OutputFile("out",
732                                cl::desc("The file to write the stream to"),
733                                cl::Required, cl::sub(ExportSubcommand));
734cl::opt<std::string>
735    Stream("stream", cl::Required,
736           cl::desc("The index or name of the stream whose contents to export"),
737           cl::sub(ExportSubcommand));
738cl::opt<bool> ForceName("name",
739                        cl::desc("Force the interpretation of -stream as a "
740                                 "string, even if it is a valid integer"),
741                        cl::sub(ExportSubcommand), cl::Optional,
742                        cl::init(false));
743} // namespace exportstream
744}
745
746static ExitOnError ExitOnErr;
747
748static void yamlToPdb(StringRef Path) {
749  BumpPtrAllocator Allocator;
750  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
751      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
752                                   /*RequiresNullTerminator=*/false);
753
754  if (ErrorOrBuffer.getError()) {
755    ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));
756  }
757
758  std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
759
760  llvm::yaml::Input In(Buffer->getBuffer());
761  pdb::yaml::PdbObject YamlObj(Allocator);
762  In >> YamlObj;
763
764  PDBFileBuilder Builder(Allocator);
765
766  uint32_t BlockSize = 4096;
767  if (YamlObj.Headers.hasValue())
768    BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
769  ExitOnErr(Builder.initialize(BlockSize));
770  // Add each of the reserved streams.  We ignore stream metadata in the
771  // yaml, because we will reconstruct our own view of the streams.  For
772  // example, the YAML may say that there were 20 streams in the original
773  // PDB, but maybe we only dump a subset of those 20 streams, so we will
774  // have fewer, and the ones we do have may end up with different indices
775  // than the ones in the original PDB.  So we just start with a clean slate.
776  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
777    ExitOnErr(Builder.getMsfBuilder().addStream(0));
778
779  StringsAndChecksums Strings;
780  Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
781
782  if (YamlObj.StringTable.hasValue()) {
783    for (auto S : *YamlObj.StringTable)
784      Strings.strings()->insert(S);
785  }
786
787  pdb::yaml::PdbInfoStream DefaultInfoStream;
788  pdb::yaml::PdbDbiStream DefaultDbiStream;
789  pdb::yaml::PdbTpiStream DefaultTpiStream;
790  pdb::yaml::PdbTpiStream DefaultIpiStream;
791
792  const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream);
793
794  auto &InfoBuilder = Builder.getInfoBuilder();
795  InfoBuilder.setAge(Info.Age);
796  InfoBuilder.setGuid(Info.Guid);
797  InfoBuilder.setSignature(Info.Signature);
798  InfoBuilder.setVersion(Info.Version);
799  for (auto F : Info.Features)
800    InfoBuilder.addFeature(F);
801
802  const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
803  auto &DbiBuilder = Builder.getDbiBuilder();
804  DbiBuilder.setAge(Dbi.Age);
805  DbiBuilder.setBuildNumber(Dbi.BuildNumber);
806  DbiBuilder.setFlags(Dbi.Flags);
807  DbiBuilder.setMachineType(Dbi.MachineType);
808  DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
809  DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
810  DbiBuilder.setVersionHeader(Dbi.VerHeader);
811  for (const auto &MI : Dbi.ModInfos) {
812    auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
813    ModiBuilder.setObjFileName(MI.Obj);
814
815    for (auto S : MI.SourceFiles)
816      ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
817    if (MI.Modi.hasValue()) {
818      const auto &ModiStream = *MI.Modi;
819      for (auto Symbol : ModiStream.Symbols) {
820        ModiBuilder.addSymbol(
821            Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
822      }
823    }
824
825    // Each module has its own checksum subsection, so scan for it every time.
826    Strings.setChecksums(nullptr);
827    CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
828
829    auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
830        Allocator, MI.Subsections, Strings));
831    for (auto &SS : CodeViewSubsections) {
832      ModiBuilder.addDebugSubsection(SS);
833    }
834  }
835
836  auto &TpiBuilder = Builder.getTpiBuilder();
837  const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
838  TpiBuilder.setVersionHeader(Tpi.Version);
839  AppendingTypeTableBuilder TS(Allocator);
840  for (const auto &R : Tpi.Records) {
841    CVType Type = R.toCodeViewRecord(TS);
842    TpiBuilder.addTypeRecord(Type.RecordData, None);
843  }
844
845  const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream);
846  auto &IpiBuilder = Builder.getIpiBuilder();
847  IpiBuilder.setVersionHeader(Ipi.Version);
848  for (const auto &R : Ipi.Records) {
849    CVType Type = R.toCodeViewRecord(TS);
850    IpiBuilder.addTypeRecord(Type.RecordData, None);
851  }
852
853  Builder.getStringTableBuilder().setStrings(*Strings.strings());
854
855  codeview::GUID IgnoredOutGuid;
856  ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
857}
858
859static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
860  ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
861
862  NativeSession *NS = static_cast<NativeSession *>(Session.get());
863  return NS->getPDBFile();
864}
865
866static void pdb2Yaml(StringRef Path) {
867  std::unique_ptr<IPDBSession> Session;
868  auto &File = loadPDB(Path, Session);
869
870  auto O = std::make_unique<YAMLOutputStyle>(File);
871  O = std::make_unique<YAMLOutputStyle>(File);
872
873  ExitOnErr(O->dump());
874}
875
876static void dumpRaw(StringRef Path) {
877  InputFile IF = ExitOnErr(InputFile::open(Path));
878
879  auto O = std::make_unique<DumpOutputStyle>(IF);
880  ExitOnErr(O->dump());
881}
882
883static void dumpBytes(StringRef Path) {
884  std::unique_ptr<IPDBSession> Session;
885  auto &File = loadPDB(Path, Session);
886
887  auto O = std::make_unique<BytesOutputStyle>(File);
888
889  ExitOnErr(O->dump());
890}
891
892bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
893  if (SymTypes.empty())
894    return true;
895  if (llvm::find(SymTypes, Search) != SymTypes.end())
896    return true;
897  if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end())
898    return true;
899  return false;
900}
901
902uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
903  auto SymbolType = Symbol.getType();
904  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
905
906  return RawType.getLength();
907}
908
909bool opts::pretty::compareFunctionSymbols(
910    const std::unique_ptr<PDBSymbolFunc> &F1,
911    const std::unique_ptr<PDBSymbolFunc> &F2) {
912  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
913
914  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
915    return F1->getName() < F2->getName();
916
917  // Note that we intentionally sort in descending order on length, since
918  // long functions are more interesting than short functions.
919  return F1->getLength() > F2->getLength();
920}
921
922bool opts::pretty::compareDataSymbols(
923    const std::unique_ptr<PDBSymbolData> &F1,
924    const std::unique_ptr<PDBSymbolData> &F2) {
925  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
926
927  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
928    return F1->getName() < F2->getName();
929
930  // Note that we intentionally sort in descending order on length, since
931  // large types are more interesting than short ones.
932  return getTypeLength(*F1) > getTypeLength(*F2);
933}
934
935static std::string stringOr(std::string Str, std::string IfEmpty) {
936  return (Str.empty()) ? IfEmpty : Str;
937}
938
939static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {
940  auto Sources = Session.getInjectedSources();
941  if (!Sources || !Sources->getChildCount()) {
942    Printer.printLine("There are no injected sources.");
943    return;
944  }
945
946  while (auto IS = Sources->getNext()) {
947    Printer.NewLine();
948    std::string File = stringOr(IS->getFileName(), "<null>");
949    uint64_t Size = IS->getCodeByteSize();
950    std::string Obj = stringOr(IS->getObjectFileName(), "<null>");
951    std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");
952    uint32_t CRC = IS->getCrc32();
953
954    WithColor(Printer, PDB_ColorItem::Path).get() << File;
955    Printer << " (";
956    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;
957    Printer << " bytes): ";
958    WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";
959    Printer << "=";
960    WithColor(Printer, PDB_ColorItem::Path).get() << Obj;
961    Printer << ", ";
962    WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";
963    Printer << "=";
964    WithColor(Printer, PDB_ColorItem::Path).get() << VFName;
965    Printer << ", ";
966    WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";
967    Printer << "=";
968    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;
969    Printer << ", ";
970    WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";
971    Printer << "=";
972    dumpPDBSourceCompression(
973        WithColor(Printer, PDB_ColorItem::LiteralValue).get(),
974        IS->getCompression());
975
976    if (!opts::pretty::ShowInjectedSourceContent)
977      continue;
978
979    // Set the indent level to 0 when printing file content.
980    int Indent = Printer.getIndentLevel();
981    Printer.Unindent(Indent);
982
983    if (IS->getCompression() == PDB_SourceCompression::None)
984      Printer.printLine(IS->getCode());
985    else
986      Printer.formatBinary("Compressed data",
987                           arrayRefFromStringRef(IS->getCode()),
988                           /*StartOffset=*/0);
989
990    // Re-indent back to the original level.
991    Printer.Indent(Indent);
992  }
993}
994
995template <typename OuterT, typename ChildT>
996void diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,
997                     PdbSymbolIdField Recurse) {
998  OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);
999  if (!ConcreteOuter)
1000    return;
1001
1002  auto Children = ConcreteOuter->template findAllChildren<ChildT>();
1003  while (auto Child = Children->getNext()) {
1004    outs() << "  {";
1005    Child->defaultDump(outs(), 4, Ids, Recurse);
1006    outs() << "\n  }\n";
1007  }
1008}
1009
1010static void dumpDia(StringRef Path) {
1011  std::unique_ptr<IPDBSession> Session;
1012
1013  const auto ReaderType =
1014      opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1015  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1016
1017  auto GlobalScope = Session->getGlobalScope();
1018
1019  std::vector<PDB_SymType> SymTypes;
1020
1021  if (opts::diadump::Compilands)
1022    SymTypes.push_back(PDB_SymType::Compiland);
1023  if (opts::diadump::Enums)
1024    SymTypes.push_back(PDB_SymType::Enum);
1025  if (opts::diadump::Pointers)
1026    SymTypes.push_back(PDB_SymType::PointerType);
1027  if (opts::diadump::UDTs)
1028    SymTypes.push_back(PDB_SymType::UDT);
1029  if (opts::diadump::Funcsigs)
1030    SymTypes.push_back(PDB_SymType::FunctionSig);
1031  if (opts::diadump::Arrays)
1032    SymTypes.push_back(PDB_SymType::ArrayType);
1033  if (opts::diadump::VTShapes)
1034    SymTypes.push_back(PDB_SymType::VTableShape);
1035  if (opts::diadump::Typedefs)
1036    SymTypes.push_back(PDB_SymType::Typedef);
1037  PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
1038                                                      : PdbSymbolIdField::All;
1039
1040  PdbSymbolIdField Recurse = PdbSymbolIdField::None;
1041  if (opts::diadump::Recurse)
1042    Recurse = PdbSymbolIdField::All;
1043  if (!opts::diadump::ShowClassHierarchy)
1044    Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);
1045
1046  for (PDB_SymType ST : SymTypes) {
1047    auto Children = GlobalScope->findAllChildren(ST);
1048    while (auto Child = Children->getNext()) {
1049      outs() << "{";
1050      Child->defaultDump(outs(), 2, Ids, Recurse);
1051
1052      diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);
1053      outs() << "\n}\n";
1054    }
1055  }
1056}
1057
1058static void dumpPretty(StringRef Path) {
1059  std::unique_ptr<IPDBSession> Session;
1060
1061  const auto ReaderType =
1062      opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
1063  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
1064
1065  if (opts::pretty::LoadAddress)
1066    Session->setLoadAddress(opts::pretty::LoadAddress);
1067
1068  auto &Stream = outs();
1069  const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
1070                            ? Stream.has_colors()
1071                            : opts::pretty::ColorOutput == cl::BOU_TRUE;
1072  LinePrinter Printer(2, UseColor, Stream);
1073
1074  auto GlobalScope(Session->getGlobalScope());
1075  if (!GlobalScope)
1076    return;
1077  std::string FileName(GlobalScope->getSymbolsFileName());
1078
1079  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
1080  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
1081  Printer.Indent();
1082  uint64_t FileSize = 0;
1083
1084  Printer.NewLine();
1085  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
1086  if (!sys::fs::file_size(FileName, FileSize)) {
1087    Printer << ": " << FileSize << " bytes";
1088  } else {
1089    Printer << ": (Unable to obtain file size)";
1090  }
1091
1092  Printer.NewLine();
1093  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
1094  Printer << ": " << GlobalScope->getGuid();
1095
1096  Printer.NewLine();
1097  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
1098  Printer << ": " << GlobalScope->getAge();
1099
1100  Printer.NewLine();
1101  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
1102  Printer << ": ";
1103  if (GlobalScope->hasCTypes())
1104    outs() << "HasCTypes ";
1105  if (GlobalScope->hasPrivateSymbols())
1106    outs() << "HasPrivateSymbols ";
1107  Printer.Unindent();
1108
1109  if (!opts::pretty::WithName.empty()) {
1110    Printer.NewLine();
1111    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1112        << "---SYMBOLS & TYPES BY NAME---";
1113
1114    for (StringRef Name : opts::pretty::WithName) {
1115      auto Symbols = GlobalScope->findChildren(
1116          PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
1117      if (!Symbols || Symbols->getChildCount() == 0) {
1118        Printer.formatLine("[not found] - {0}", Name);
1119        continue;
1120      }
1121      Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
1122                         Name);
1123
1124      AutoIndent Indent(Printer);
1125      Printer.NewLine();
1126
1127      while (auto Symbol = Symbols->getNext()) {
1128        switch (Symbol->getSymTag()) {
1129        case PDB_SymType::Typedef: {
1130          TypedefDumper TD(Printer);
1131          std::unique_ptr<PDBSymbolTypeTypedef> T =
1132              llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
1133          TD.start(*T);
1134          break;
1135        }
1136        case PDB_SymType::Enum: {
1137          EnumDumper ED(Printer);
1138          std::unique_ptr<PDBSymbolTypeEnum> E =
1139              llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
1140          ED.start(*E);
1141          break;
1142        }
1143        case PDB_SymType::UDT: {
1144          ClassDefinitionDumper CD(Printer);
1145          std::unique_ptr<PDBSymbolTypeUDT> C =
1146              llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
1147          CD.start(*C);
1148          break;
1149        }
1150        case PDB_SymType::BaseClass:
1151        case PDB_SymType::Friend: {
1152          TypeDumper TD(Printer);
1153          Symbol->dump(TD);
1154          break;
1155        }
1156        case PDB_SymType::Function: {
1157          FunctionDumper FD(Printer);
1158          std::unique_ptr<PDBSymbolFunc> F =
1159              llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
1160          FD.start(*F, FunctionDumper::PointerType::None);
1161          break;
1162        }
1163        case PDB_SymType::Data: {
1164          VariableDumper VD(Printer);
1165          std::unique_ptr<PDBSymbolData> D =
1166              llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
1167          VD.start(*D);
1168          break;
1169        }
1170        case PDB_SymType::PublicSymbol: {
1171          ExternalSymbolDumper ED(Printer);
1172          std::unique_ptr<PDBSymbolPublicSymbol> PS =
1173              llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
1174          ED.dump(*PS);
1175          break;
1176        }
1177        default:
1178          llvm_unreachable("Unexpected symbol tag!");
1179        }
1180      }
1181    }
1182    llvm::outs().flush();
1183  }
1184
1185  if (opts::pretty::Compilands) {
1186    Printer.NewLine();
1187    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1188        << "---COMPILANDS---";
1189    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
1190
1191    if (Compilands) {
1192      Printer.Indent();
1193      CompilandDumper Dumper(Printer);
1194      CompilandDumpFlags options = CompilandDumper::Flags::None;
1195      if (opts::pretty::Lines)
1196        options = options | CompilandDumper::Flags::Lines;
1197      while (auto Compiland = Compilands->getNext())
1198        Dumper.start(*Compiland, options);
1199      Printer.Unindent();
1200    }
1201  }
1202
1203  if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
1204      opts::pretty::Funcsigs || opts::pretty::Pointers ||
1205      opts::pretty::Arrays || opts::pretty::VTShapes) {
1206    Printer.NewLine();
1207    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
1208    Printer.Indent();
1209    TypeDumper Dumper(Printer);
1210    Dumper.start(*GlobalScope);
1211    Printer.Unindent();
1212  }
1213
1214  if (opts::pretty::Symbols) {
1215    Printer.NewLine();
1216    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
1217    if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
1218      Printer.Indent();
1219      CompilandDumper Dumper(Printer);
1220      while (auto Compiland = Compilands->getNext())
1221        Dumper.start(*Compiland, true);
1222      Printer.Unindent();
1223    }
1224  }
1225
1226  if (opts::pretty::Globals) {
1227    Printer.NewLine();
1228    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
1229    Printer.Indent();
1230    if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
1231      if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {
1232        FunctionDumper Dumper(Printer);
1233        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1234          while (auto Function = Functions->getNext()) {
1235            Printer.NewLine();
1236            Dumper.start(*Function, FunctionDumper::PointerType::None);
1237          }
1238        } else {
1239          std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
1240          while (auto Func = Functions->getNext())
1241            Funcs.push_back(std::move(Func));
1242          llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);
1243          for (const auto &Func : Funcs) {
1244            Printer.NewLine();
1245            Dumper.start(*Func, FunctionDumper::PointerType::None);
1246          }
1247        }
1248      }
1249    }
1250    if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
1251      if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {
1252        VariableDumper Dumper(Printer);
1253        if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
1254          while (auto Var = Vars->getNext())
1255            Dumper.start(*Var);
1256        } else {
1257          std::vector<std::unique_ptr<PDBSymbolData>> Datas;
1258          while (auto Var = Vars->getNext())
1259            Datas.push_back(std::move(Var));
1260          llvm::sort(Datas, opts::pretty::compareDataSymbols);
1261          for (const auto &Var : Datas)
1262            Dumper.start(*Var);
1263        }
1264      }
1265    }
1266    if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
1267      if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {
1268        CompilandDumper Dumper(Printer);
1269        while (auto Thunk = Thunks->getNext())
1270          Dumper.dump(*Thunk);
1271      }
1272    }
1273    Printer.Unindent();
1274  }
1275  if (opts::pretty::Externals) {
1276    Printer.NewLine();
1277    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
1278    Printer.Indent();
1279    ExternalSymbolDumper Dumper(Printer);
1280    Dumper.start(*GlobalScope);
1281  }
1282  if (opts::pretty::Lines) {
1283    Printer.NewLine();
1284  }
1285  if (opts::pretty::InjectedSources) {
1286    Printer.NewLine();
1287    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
1288        << "---INJECTED SOURCES---";
1289    AutoIndent Indent1(Printer);
1290    dumpInjectedSources(Printer, *Session);
1291  }
1292
1293  Printer.NewLine();
1294  outs().flush();
1295}
1296
1297static void mergePdbs() {
1298  BumpPtrAllocator Allocator;
1299  MergingTypeTableBuilder MergedTpi(Allocator);
1300  MergingTypeTableBuilder MergedIpi(Allocator);
1301
1302  // Create a Tpi and Ipi type table with all types from all input files.
1303  for (const auto &Path : opts::merge::InputFilenames) {
1304    std::unique_ptr<IPDBSession> Session;
1305    auto &File = loadPDB(Path, Session);
1306    SmallVector<TypeIndex, 128> TypeMap;
1307    SmallVector<TypeIndex, 128> IdMap;
1308    if (File.hasPDBTpiStream()) {
1309      auto &Tpi = ExitOnErr(File.getPDBTpiStream());
1310      ExitOnErr(
1311          codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));
1312    }
1313    if (File.hasPDBIpiStream()) {
1314      auto &Ipi = ExitOnErr(File.getPDBIpiStream());
1315      ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
1316                                         Ipi.typeArray()));
1317    }
1318  }
1319
1320  // Then write the PDB.
1321  PDBFileBuilder Builder(Allocator);
1322  ExitOnErr(Builder.initialize(4096));
1323  // Add each of the reserved streams.  We might not put any data in them,
1324  // but at least they have to be present.
1325  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
1326    ExitOnErr(Builder.getMsfBuilder().addStream(0));
1327
1328  auto &DestTpi = Builder.getTpiBuilder();
1329  auto &DestIpi = Builder.getIpiBuilder();
1330  MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
1331    DestTpi.addTypeRecord(Type.RecordData, None);
1332  });
1333  MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
1334    DestIpi.addTypeRecord(Type.RecordData, None);
1335  });
1336  Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
1337
1338  SmallString<64> OutFile(opts::merge::PdbOutputFile);
1339  if (OutFile.empty()) {
1340    OutFile = opts::merge::InputFilenames[0];
1341    llvm::sys::path::replace_extension(OutFile, "merged.pdb");
1342  }
1343
1344  codeview::GUID IgnoredOutGuid;
1345  ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));
1346}
1347
1348static void explain() {
1349  std::unique_ptr<IPDBSession> Session;
1350  InputFile IF =
1351      ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));
1352
1353  for (uint64_t Off : opts::explain::Offsets) {
1354    auto O = std::make_unique<ExplainOutputStyle>(IF, Off);
1355
1356    ExitOnErr(O->dump());
1357  }
1358}
1359
1360static void exportStream() {
1361  std::unique_ptr<IPDBSession> Session;
1362  PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);
1363
1364  std::unique_ptr<MappedBlockStream> SourceStream;
1365  uint32_t Index = 0;
1366  bool Success = false;
1367  std::string OutFileName = opts::exportstream::OutputFile;
1368
1369  if (!opts::exportstream::ForceName) {
1370    // First try to parse it as an integer, if it fails fall back to treating it
1371    // as a named stream.
1372    if (to_integer(opts::exportstream::Stream, Index)) {
1373      if (Index >= File.getNumStreams()) {
1374        errs() << "Error: " << Index << " is not a valid stream index.\n";
1375        exit(1);
1376      }
1377      Success = true;
1378      outs() << "Dumping contents of stream index " << Index << " to file "
1379             << OutFileName << ".\n";
1380    }
1381  }
1382
1383  if (!Success) {
1384    InfoStream &IS = cantFail(File.getPDBInfoStream());
1385    Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));
1386    outs() << "Dumping contents of stream '" << opts::exportstream::Stream
1387           << "' (index " << Index << ") to file " << OutFileName << ".\n";
1388  }
1389
1390  SourceStream = File.createIndexedStream(Index);
1391  auto OutFile = ExitOnErr(
1392      FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
1393  FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
1394  BinaryStreamWriter Writer(DestStream);
1395  ExitOnErr(Writer.writeStreamRef(*SourceStream));
1396  ExitOnErr(DestStream.commit());
1397}
1398
1399static bool parseRange(StringRef Str,
1400                       Optional<opts::bytes::NumberRange> &Parsed) {
1401  if (Str.empty())
1402    return true;
1403
1404  llvm::Regex R("^([^-]+)(-([^-]+))?$");
1405  llvm::SmallVector<llvm::StringRef, 2> Matches;
1406  if (!R.match(Str, &Matches))
1407    return false;
1408
1409  Parsed.emplace();
1410  if (!to_integer(Matches[1], Parsed->Min))
1411    return false;
1412
1413  if (!Matches[3].empty()) {
1414    Parsed->Max.emplace();
1415    if (!to_integer(Matches[3], *Parsed->Max))
1416      return false;
1417  }
1418  return true;
1419}
1420
1421static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {
1422  // If this list contains "All" plus some other stuff, remove the other stuff
1423  // and just keep "All" in the list.
1424  if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))
1425    return;
1426  Chunks.reset();
1427  Chunks.push_back(opts::ModuleSubsection::All);
1428}
1429
1430int main(int Argc, const char **Argv) {
1431  InitLLVM X(Argc, Argv);
1432  ExitOnErr.setBanner("llvm-pdbutil: ");
1433
1434  cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
1435
1436  if (opts::BytesSubcommand) {
1437    if (!parseRange(opts::bytes::DumpBlockRangeOpt,
1438                    opts::bytes::DumpBlockRange)) {
1439      errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt
1440             << "' invalid format.\n";
1441      errs().flush();
1442      exit(1);
1443    }
1444    if (!parseRange(opts::bytes::DumpByteRangeOpt,
1445                    opts::bytes::DumpByteRange)) {
1446      errs() << "Argument '" << opts::bytes::DumpByteRangeOpt
1447             << "' invalid format.\n";
1448      errs().flush();
1449      exit(1);
1450    }
1451  }
1452
1453  if (opts::DumpSubcommand) {
1454    if (opts::dump::RawAll) {
1455      opts::dump::DumpGlobals = true;
1456      opts::dump::DumpFpo = true;
1457      opts::dump::DumpInlineeLines = true;
1458      opts::dump::DumpIds = true;
1459      opts::dump::DumpIdExtras = true;
1460      opts::dump::DumpLines = true;
1461      opts::dump::DumpModules = true;
1462      opts::dump::DumpModuleFiles = true;
1463      opts::dump::DumpPublics = true;
1464      opts::dump::DumpSectionContribs = true;
1465      opts::dump::DumpSectionHeaders = true;
1466      opts::dump::DumpSectionMap = true;
1467      opts::dump::DumpStreams = true;
1468      opts::dump::DumpStreamBlocks = true;
1469      opts::dump::DumpStringTable = true;
1470      opts::dump::DumpStringTableDetails = true;
1471      opts::dump::DumpSummary = true;
1472      opts::dump::DumpSymbols = true;
1473      opts::dump::DumpSymbolStats = true;
1474      opts::dump::DumpTypes = true;
1475      opts::dump::DumpTypeExtras = true;
1476      opts::dump::DumpUdtStats = true;
1477      opts::dump::DumpXme = true;
1478      opts::dump::DumpXmi = true;
1479    }
1480  }
1481  if (opts::PdbToYamlSubcommand) {
1482    if (opts::pdb2yaml::All) {
1483      opts::pdb2yaml::StreamMetadata = true;
1484      opts::pdb2yaml::StreamDirectory = true;
1485      opts::pdb2yaml::PdbStream = true;
1486      opts::pdb2yaml::StringTable = true;
1487      opts::pdb2yaml::DbiStream = true;
1488      opts::pdb2yaml::TpiStream = true;
1489      opts::pdb2yaml::IpiStream = true;
1490      opts::pdb2yaml::PublicsStream = true;
1491      opts::pdb2yaml::DumpModules = true;
1492      opts::pdb2yaml::DumpModuleFiles = true;
1493      opts::pdb2yaml::DumpModuleSyms = true;
1494      opts::pdb2yaml::DumpModuleSubsections.push_back(
1495          opts::ModuleSubsection::All);
1496    }
1497    simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);
1498
1499    if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
1500      opts::pdb2yaml::DumpModules = true;
1501
1502    if (opts::pdb2yaml::DumpModules)
1503      opts::pdb2yaml::DbiStream = true;
1504  }
1505
1506  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
1507
1508  if (opts::PdbToYamlSubcommand) {
1509    pdb2Yaml(opts::pdb2yaml::InputFilename.front());
1510  } else if (opts::YamlToPdbSubcommand) {
1511    if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
1512      SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
1513      sys::path::replace_extension(OutputFilename, ".pdb");
1514      opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename.str());
1515    }
1516    yamlToPdb(opts::yaml2pdb::InputFilename);
1517  } else if (opts::DiaDumpSubcommand) {
1518    llvm::for_each(opts::diadump::InputFilenames, dumpDia);
1519  } else if (opts::PrettySubcommand) {
1520    if (opts::pretty::Lines)
1521      opts::pretty::Compilands = true;
1522
1523    if (opts::pretty::All) {
1524      opts::pretty::Compilands = true;
1525      opts::pretty::Symbols = true;
1526      opts::pretty::Globals = true;
1527      opts::pretty::Types = true;
1528      opts::pretty::Externals = true;
1529      opts::pretty::Lines = true;
1530    }
1531
1532    if (opts::pretty::Types) {
1533      opts::pretty::Classes = true;
1534      opts::pretty::Typedefs = true;
1535      opts::pretty::Enums = true;
1536      opts::pretty::Pointers = true;
1537      opts::pretty::Funcsigs = true;
1538    }
1539
1540    // When adding filters for excluded compilands and types, we need to
1541    // remember that these are regexes.  So special characters such as * and \
1542    // need to be escaped in the regex.  In the case of a literal \, this means
1543    // it needs to be escaped again in the C++.  So matching a single \ in the
1544    // input requires 4 \es in the C++.
1545    if (opts::pretty::ExcludeCompilerGenerated) {
1546      opts::pretty::ExcludeTypes.push_back("__vc_attributes");
1547      opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
1548    }
1549    if (opts::pretty::ExcludeSystemLibraries) {
1550      opts::pretty::ExcludeCompilands.push_back(
1551          "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
1552      opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
1553      opts::pretty::ExcludeCompilands.push_back(
1554          "d:\\\\th.obj.x86fre\\\\minkernel");
1555    }
1556    llvm::for_each(opts::pretty::InputFilenames, dumpPretty);
1557  } else if (opts::DumpSubcommand) {
1558    llvm::for_each(opts::dump::InputFilenames, dumpRaw);
1559  } else if (opts::BytesSubcommand) {
1560    llvm::for_each(opts::bytes::InputFilenames, dumpBytes);
1561  } else if (opts::MergeSubcommand) {
1562    if (opts::merge::InputFilenames.size() < 2) {
1563      errs() << "merge subcommand requires at least 2 input files.\n";
1564      exit(1);
1565    }
1566    mergePdbs();
1567  } else if (opts::ExplainSubcommand) {
1568    explain();
1569  } else if (opts::ExportSubcommand) {
1570    exportStream();
1571  }
1572
1573  outs().flush();
1574  return 0;
1575}
1576