1//===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Dumps debug information present in PDB files.  This utility makes use of
11// the Microsoft Windows SDK, so will not compile or run on non-Windows
12// platforms.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm-pdbdump.h"
17#include "CompilandDumper.h"
18#include "ExternalSymbolDumper.h"
19#include "FunctionDumper.h"
20#include "LLVMOutputStyle.h"
21#include "LinePrinter.h"
22#include "OutputStyle.h"
23#include "TypeDumper.h"
24#include "VariableDumper.h"
25#include "YAMLOutputStyle.h"
26
27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/BitVector.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/Config/config.h"
32#include "llvm/DebugInfo/CodeView/ByteStream.h"
33#include "llvm/DebugInfo/PDB/GenericError.h"
34#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
35#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
36#include "llvm/DebugInfo/PDB/IPDBSession.h"
37#include "llvm/DebugInfo/PDB/PDB.h"
38#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
39#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
40#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
41#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
42#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
43#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
44#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
45#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
46#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
47#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
48#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h"
49#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
50#include "llvm/DebugInfo/PDB/Raw/RawError.h"
51#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
52#include "llvm/Support/COM.h"
53#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/ConvertUTF.h"
55#include "llvm/Support/FileOutputBuffer.h"
56#include "llvm/Support/FileSystem.h"
57#include "llvm/Support/Format.h"
58#include "llvm/Support/ManagedStatic.h"
59#include "llvm/Support/MemoryBuffer.h"
60#include "llvm/Support/PrettyStackTrace.h"
61#include "llvm/Support/Process.h"
62#include "llvm/Support/ScopedPrinter.h"
63#include "llvm/Support/Signals.h"
64#include "llvm/Support/raw_ostream.h"
65
66using namespace llvm;
67using namespace llvm::codeview;
68using namespace llvm::pdb;
69
70namespace {
71// A simple adapter that acts like a ByteStream but holds ownership over
72// and underlying FileOutputBuffer.
73class FileBufferByteStream : public ByteStream<true> {
74public:
75  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
76      : ByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
77                                            Buffer->getBufferEnd())),
78        FileBuffer(std::move(Buffer)) {}
79
80  Error commit() const override {
81    if (FileBuffer->commit())
82      return llvm::make_error<RawError>(raw_error_code::not_writable);
83    return Error::success();
84  }
85
86private:
87  std::unique_ptr<FileOutputBuffer> FileBuffer;
88};
89}
90
91namespace opts {
92
93cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
94cl::SubCommand
95    PrettySubcommand("pretty",
96                     "Dump semantic information about types and symbols");
97cl::SubCommand
98    YamlToPdbSubcommand("yaml2pdb",
99                        "Generate a PDB file from a YAML description");
100cl::SubCommand
101    PdbToYamlSubcommand("pdb2yaml",
102                        "Generate a detailed YAML description of a PDB File");
103
104cl::OptionCategory TypeCategory("Symbol Type Options");
105cl::OptionCategory FilterCategory("Filtering Options");
106cl::OptionCategory OtherOptions("Other Options");
107
108namespace pretty {
109cl::list<std::string> InputFilenames(cl::Positional,
110                                     cl::desc("<input PDB files>"),
111                                     cl::OneOrMore, cl::sub(PrettySubcommand));
112
113cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
114                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
115cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
116                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
117cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
118                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
119cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
120                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
121cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
122                    cl::sub(PrettySubcommand));
123cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
124                    cl::sub(PrettySubcommand));
125cl::opt<bool>
126    All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
127        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
128
129cl::opt<uint64_t> LoadAddress(
130    "load-address",
131    cl::desc("Assume the module is loaded at the specified address"),
132    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
133cl::list<std::string> ExcludeTypes(
134    "exclude-types", cl::desc("Exclude types by regular expression"),
135    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
136cl::list<std::string> ExcludeSymbols(
137    "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
138    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
139cl::list<std::string> ExcludeCompilands(
140    "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
141    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
142
143cl::list<std::string> IncludeTypes(
144    "include-types",
145    cl::desc("Include only types which match a regular expression"),
146    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
147cl::list<std::string> IncludeSymbols(
148    "include-symbols",
149    cl::desc("Include only symbols which match a regular expression"),
150    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
151cl::list<std::string> IncludeCompilands(
152    "include-compilands",
153    cl::desc("Include only compilands those which match a regular expression"),
154    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
155
156cl::opt<bool> ExcludeCompilerGenerated(
157    "no-compiler-generated",
158    cl::desc("Don't show compiler generated types and symbols"),
159    cl::cat(FilterCategory), cl::sub(PrettySubcommand));
160cl::opt<bool>
161    ExcludeSystemLibraries("no-system-libs",
162                           cl::desc("Don't show symbols from system libraries"),
163                           cl::cat(FilterCategory), cl::sub(PrettySubcommand));
164cl::opt<bool> NoClassDefs("no-class-definitions",
165                          cl::desc("Don't display full class definitions"),
166                          cl::cat(FilterCategory), cl::sub(PrettySubcommand));
167cl::opt<bool> NoEnumDefs("no-enum-definitions",
168                         cl::desc("Don't display full enum definitions"),
169                         cl::cat(FilterCategory), cl::sub(PrettySubcommand));
170}
171
172namespace raw {
173
174cl::OptionCategory MsfOptions("MSF Container Options");
175cl::OptionCategory TypeOptions("Type Record Options");
176cl::OptionCategory FileOptions("Module & File Options");
177cl::OptionCategory SymbolOptions("Symbol Options");
178cl::OptionCategory MiscOptions("Miscellaneous Options");
179
180// MSF OPTIONS
181cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
182                          cl::cat(MsfOptions), cl::sub(RawSubcommand));
183cl::opt<bool> DumpStreamBlocks("stream-blocks",
184                               cl::desc("dump PDB stream blocks"),
185                               cl::cat(MsfOptions), cl::sub(RawSubcommand));
186cl::opt<bool> DumpStreamSummary("stream-summary",
187                                cl::desc("dump summary of the PDB streams"),
188                                cl::cat(MsfOptions), cl::sub(RawSubcommand));
189
190// TYPE OPTIONS
191cl::opt<bool>
192    DumpTpiRecords("tpi-records",
193                   cl::desc("dump CodeView type records from TPI stream"),
194                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
195cl::opt<bool> DumpTpiRecordBytes(
196    "tpi-record-bytes",
197    cl::desc("dump CodeView type record raw bytes from TPI stream"),
198    cl::cat(TypeOptions), cl::sub(RawSubcommand));
199cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
200                          cl::cat(TypeOptions), cl::sub(RawSubcommand));
201cl::opt<bool>
202    DumpIpiRecords("ipi-records",
203                   cl::desc("dump CodeView type records from IPI stream"),
204                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
205cl::opt<bool> DumpIpiRecordBytes(
206    "ipi-record-bytes",
207    cl::desc("dump CodeView type record raw bytes from IPI stream"),
208    cl::cat(TypeOptions), cl::sub(RawSubcommand));
209
210// MODULE & FILE OPTIONS
211cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
212                          cl::cat(FileOptions), cl::sub(RawSubcommand));
213cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
214                              cl::cat(FileOptions), cl::sub(RawSubcommand));
215cl::opt<bool> DumpLineInfo("line-info",
216                           cl::desc("dump file and line information"),
217                           cl::cat(FileOptions), cl::sub(RawSubcommand));
218
219// SYMBOL OPTIONS
220cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
221                             cl::cat(SymbolOptions), cl::sub(RawSubcommand));
222cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
223                          cl::cat(SymbolOptions), cl::sub(RawSubcommand));
224cl::opt<bool>
225    DumpSymRecordBytes("sym-record-bytes",
226                       cl::desc("dump CodeView symbol record raw bytes"),
227                       cl::cat(SymbolOptions), cl::sub(RawSubcommand));
228
229// MISCELLANEOUS OPTIONS
230cl::opt<bool> DumpSectionContribs("section-contribs",
231                                  cl::desc("dump section contributions"),
232                                  cl::cat(MiscOptions), cl::sub(RawSubcommand));
233cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
234                             cl::cat(MiscOptions), cl::sub(RawSubcommand));
235cl::opt<bool> DumpSectionHeaders("section-headers",
236                                 cl::desc("dump section headers"),
237                                 cl::cat(MiscOptions), cl::sub(RawSubcommand));
238cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
239                      cl::sub(RawSubcommand));
240
241cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
242                                       cl::cat(MiscOptions),
243                                       cl::sub(RawSubcommand));
244cl::opt<std::string> DumpStreamDataName("stream-name",
245                                        cl::desc("dump stream data"),
246                                        cl::cat(MiscOptions),
247                                        cl::sub(RawSubcommand));
248
249cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
250                     cl::cat(MiscOptions), cl::sub(RawSubcommand));
251
252cl::list<std::string> InputFilenames(cl::Positional,
253                                     cl::desc("<input PDB files>"),
254                                     cl::OneOrMore, cl::sub(RawSubcommand));
255}
256
257namespace yaml2pdb {
258cl::opt<std::string>
259    YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
260                      cl::sub(YamlToPdbSubcommand));
261
262cl::list<std::string> InputFilename(cl::Positional,
263                                    cl::desc("<input YAML file>"), cl::Required,
264                                    cl::sub(YamlToPdbSubcommand));
265}
266
267namespace pdb2yaml {
268cl::opt<bool>
269    NoFileHeaders("no-file-headers",
270                  cl::desc("Do not dump MSF file headers (you will not be able "
271                           "to generate a fresh PDB from the resulting YAML)"),
272                  cl::sub(PdbToYamlSubcommand), cl::init(false));
273
274cl::opt<bool> StreamMetadata(
275    "stream-metadata",
276    cl::desc("Dump the number of streams and each stream's size"),
277    cl::sub(PdbToYamlSubcommand), cl::init(false));
278cl::opt<bool> StreamDirectory(
279    "stream-directory",
280    cl::desc("Dump each stream's block map (implies -stream-metadata)"),
281    cl::sub(PdbToYamlSubcommand), cl::init(false));
282cl::opt<bool> PdbStream(
283    "pdb-stream",
284    cl::desc("Dump the PDB Stream (Stream 1) (implies -stream-metadata)"),
285    cl::sub(PdbToYamlSubcommand), cl::init(false));
286cl::opt<bool> DbiStream(
287    "dbi-stream",
288    cl::desc("Dump the DBI Stream (Stream 2) (implies -stream-metadata)"),
289    cl::sub(PdbToYamlSubcommand), cl::init(false));
290
291cl::list<std::string> InputFilename(cl::Positional,
292                                    cl::desc("<input PDB file>"), cl::Required,
293                                    cl::sub(PdbToYamlSubcommand));
294}
295}
296
297static ExitOnError ExitOnErr;
298
299static void yamlToPdb(StringRef Path) {
300  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
301      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
302                                   /*RequiresNullTerminator=*/false);
303
304  if (ErrorOrBuffer.getError()) {
305    ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path, Path));
306  }
307
308  std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
309
310  llvm::yaml::Input In(Buffer->getBuffer());
311  pdb::yaml::PdbObject YamlObj;
312  In >> YamlObj;
313  if (!YamlObj.Headers.hasValue())
314    ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
315                                       "Yaml does not contain MSF headers"));
316
317  auto OutFileOrError = FileOutputBuffer::create(
318      opts::yaml2pdb::YamlPdbOutputFile, YamlObj.Headers->FileSize);
319  if (OutFileOrError.getError())
320    ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path,
321                                       opts::yaml2pdb::YamlPdbOutputFile));
322
323  auto FileByteStream =
324      llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
325  PDBFileBuilder Builder(std::move(FileByteStream));
326
327  ExitOnErr(Builder.setSuperBlock(YamlObj.Headers->SuperBlock));
328  if (YamlObj.StreamSizes.hasValue()) {
329    Builder.setStreamSizes(YamlObj.StreamSizes.getValue());
330  }
331  Builder.setDirectoryBlocks(YamlObj.Headers->DirectoryBlocks);
332
333  if (YamlObj.StreamMap.hasValue()) {
334    std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
335    for (auto &E : YamlObj.StreamMap.getValue()) {
336      StreamMap.push_back(E.Blocks);
337    }
338    Builder.setStreamMap(StreamMap);
339  } else {
340    ExitOnErr(Builder.generateSimpleStreamMap());
341  }
342
343  if (YamlObj.PdbStream.hasValue()) {
344    auto &InfoBuilder = Builder.getInfoBuilder();
345    InfoBuilder.setAge(YamlObj.PdbStream->Age);
346    InfoBuilder.setGuid(YamlObj.PdbStream->Guid);
347    InfoBuilder.setSignature(YamlObj.PdbStream->Signature);
348    InfoBuilder.setVersion(YamlObj.PdbStream->Version);
349  }
350
351  if (YamlObj.DbiStream.hasValue()) {
352    auto &DbiBuilder = Builder.getDbiBuilder();
353    DbiBuilder.setAge(YamlObj.DbiStream->Age);
354    DbiBuilder.setBuildNumber(YamlObj.DbiStream->BuildNumber);
355    DbiBuilder.setFlags(YamlObj.DbiStream->Flags);
356    DbiBuilder.setMachineType(YamlObj.DbiStream->MachineType);
357    DbiBuilder.setPdbDllRbld(YamlObj.DbiStream->PdbDllRbld);
358    DbiBuilder.setPdbDllVersion(YamlObj.DbiStream->PdbDllVersion);
359    DbiBuilder.setVersionHeader(YamlObj.DbiStream->VerHeader);
360  }
361
362  auto Pdb = Builder.build();
363  ExitOnErr(Pdb.takeError());
364
365  auto &PdbFile = *Pdb;
366  ExitOnErr(PdbFile->commit());
367}
368
369static void pdb2Yaml(StringRef Path) {
370  std::unique_ptr<IPDBSession> Session;
371  ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
372
373  RawSession *RS = static_cast<RawSession *>(Session.get());
374  PDBFile &File = RS->getPDBFile();
375  auto O = llvm::make_unique<YAMLOutputStyle>(File);
376  O = llvm::make_unique<YAMLOutputStyle>(File);
377
378  ExitOnErr(O->dump());
379}
380
381static void dumpRaw(StringRef Path) {
382  std::unique_ptr<IPDBSession> Session;
383  ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
384
385  RawSession *RS = static_cast<RawSession *>(Session.get());
386  PDBFile &File = RS->getPDBFile();
387  auto O = llvm::make_unique<LLVMOutputStyle>(File);
388
389  ExitOnErr(O->dump());
390}
391
392static void dumpPretty(StringRef Path) {
393  std::unique_ptr<IPDBSession> Session;
394
395  ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, Session));
396
397  if (opts::pretty::LoadAddress)
398    Session->setLoadAddress(opts::pretty::LoadAddress);
399
400  LinePrinter Printer(2, outs());
401
402  auto GlobalScope(Session->getGlobalScope());
403  std::string FileName(GlobalScope->getSymbolsFileName());
404
405  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
406  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
407  Printer.Indent();
408  uint64_t FileSize = 0;
409
410  Printer.NewLine();
411  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
412  if (!sys::fs::file_size(FileName, FileSize)) {
413    Printer << ": " << FileSize << " bytes";
414  } else {
415    Printer << ": (Unable to obtain file size)";
416  }
417
418  Printer.NewLine();
419  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
420  Printer << ": " << GlobalScope->getGuid();
421
422  Printer.NewLine();
423  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
424  Printer << ": " << GlobalScope->getAge();
425
426  Printer.NewLine();
427  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
428  Printer << ": ";
429  if (GlobalScope->hasCTypes())
430    outs() << "HasCTypes ";
431  if (GlobalScope->hasPrivateSymbols())
432    outs() << "HasPrivateSymbols ";
433  Printer.Unindent();
434
435  if (opts::pretty::Compilands) {
436    Printer.NewLine();
437    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
438        << "---COMPILANDS---";
439    Printer.Indent();
440    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
441    CompilandDumper Dumper(Printer);
442    CompilandDumpFlags options = CompilandDumper::Flags::None;
443    if (opts::pretty::Lines)
444      options = options | CompilandDumper::Flags::Lines;
445    while (auto Compiland = Compilands->getNext())
446      Dumper.start(*Compiland, options);
447    Printer.Unindent();
448  }
449
450  if (opts::pretty::Types) {
451    Printer.NewLine();
452    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
453    Printer.Indent();
454    TypeDumper Dumper(Printer);
455    Dumper.start(*GlobalScope);
456    Printer.Unindent();
457  }
458
459  if (opts::pretty::Symbols) {
460    Printer.NewLine();
461    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
462    Printer.Indent();
463    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
464    CompilandDumper Dumper(Printer);
465    while (auto Compiland = Compilands->getNext())
466      Dumper.start(*Compiland, true);
467    Printer.Unindent();
468  }
469
470  if (opts::pretty::Globals) {
471    Printer.NewLine();
472    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
473    Printer.Indent();
474    {
475      FunctionDumper Dumper(Printer);
476      auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
477      while (auto Function = Functions->getNext()) {
478        Printer.NewLine();
479        Dumper.start(*Function, FunctionDumper::PointerType::None);
480      }
481    }
482    {
483      auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
484      VariableDumper Dumper(Printer);
485      while (auto Var = Vars->getNext())
486        Dumper.start(*Var);
487    }
488    {
489      auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
490      CompilandDumper Dumper(Printer);
491      while (auto Thunk = Thunks->getNext())
492        Dumper.dump(*Thunk);
493    }
494    Printer.Unindent();
495  }
496  if (opts::pretty::Externals) {
497    Printer.NewLine();
498    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
499    Printer.Indent();
500    ExternalSymbolDumper Dumper(Printer);
501    Dumper.start(*GlobalScope);
502  }
503  if (opts::pretty::Lines) {
504    Printer.NewLine();
505  }
506  outs().flush();
507}
508
509int main(int argc_, const char *argv_[]) {
510  // Print a stack trace if we signal out.
511  sys::PrintStackTraceOnErrorSignal(argv_[0]);
512  PrettyStackTraceProgram X(argc_, argv_);
513
514  ExitOnErr.setBanner("llvm-pdbdump: ");
515
516  SmallVector<const char *, 256> argv;
517  SpecificBumpPtrAllocator<char> ArgAllocator;
518  ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
519      argv, makeArrayRef(argv_, argc_), ArgAllocator)));
520
521  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
522
523  cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
524
525  // These options are shared by two subcommands.
526  if ((opts::PdbToYamlSubcommand || opts::RawSubcommand) && opts::raw::RawAll) {
527    opts::raw::DumpHeaders = true;
528    opts::raw::DumpModules = true;
529    opts::raw::DumpModuleFiles = true;
530    opts::raw::DumpModuleSyms = true;
531    opts::raw::DumpPublics = true;
532    opts::raw::DumpSectionHeaders = true;
533    opts::raw::DumpStreamSummary = true;
534    opts::raw::DumpStreamBlocks = true;
535    opts::raw::DumpTpiRecords = true;
536    opts::raw::DumpTpiHash = true;
537    opts::raw::DumpIpiRecords = true;
538    opts::raw::DumpSectionMap = true;
539    opts::raw::DumpSectionContribs = true;
540    opts::raw::DumpLineInfo = true;
541    opts::raw::DumpFpo = true;
542  }
543
544  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
545
546  if (opts::PdbToYamlSubcommand) {
547    pdb2Yaml(opts::pdb2yaml::InputFilename.front());
548  } else if (opts::YamlToPdbSubcommand) {
549    yamlToPdb(opts::yaml2pdb::InputFilename.front());
550  } else if (opts::PrettySubcommand) {
551    if (opts::pretty::Lines)
552      opts::pretty::Compilands = true;
553
554    if (opts::pretty::All) {
555      opts::pretty::Compilands = true;
556      opts::pretty::Symbols = true;
557      opts::pretty::Globals = true;
558      opts::pretty::Types = true;
559      opts::pretty::Externals = true;
560      opts::pretty::Lines = true;
561    }
562
563    // When adding filters for excluded compilands and types, we need to
564    // remember
565    // that these are regexes.  So special characters such as * and \ need to be
566    // escaped in the regex.  In the case of a literal \, this means it needs to
567    // be escaped again in the C++.  So matching a single \ in the input
568    // requires
569    // 4 \es in the C++.
570    if (opts::pretty::ExcludeCompilerGenerated) {
571      opts::pretty::ExcludeTypes.push_back("__vc_attributes");
572      opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
573    }
574    if (opts::pretty::ExcludeSystemLibraries) {
575      opts::pretty::ExcludeCompilands.push_back(
576          "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
577      opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
578      opts::pretty::ExcludeCompilands.push_back(
579          "d:\\\\th.obj.x86fre\\\\minkernel");
580    }
581    std::for_each(opts::pretty::InputFilenames.begin(),
582                  opts::pretty::InputFilenames.end(), dumpPretty);
583  } else if (opts::RawSubcommand) {
584    std::for_each(opts::raw::InputFilenames.begin(),
585                  opts::raw::InputFilenames.end(), dumpRaw);
586  }
587
588  outs().flush();
589  return 0;
590}
591