• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
66 using namespace llvm;
67 using namespace llvm::codeview;
68 using namespace llvm::pdb;
69 
70 namespace {
71 // A simple adapter that acts like a ByteStream but holds ownership over
72 // and underlying FileOutputBuffer.
73 class FileBufferByteStream : public ByteStream<true> {
74 public:
FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)75   FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
76       : ByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
77                                             Buffer->getBufferEnd())),
78         FileBuffer(std::move(Buffer)) {}
79 
commit() const80   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 
86 private:
87   std::unique_ptr<FileOutputBuffer> FileBuffer;
88 };
89 }
90 
91 namespace opts {
92 
93 cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
94 cl::SubCommand
95     PrettySubcommand("pretty",
96                      "Dump semantic information about types and symbols");
97 cl::SubCommand
98     YamlToPdbSubcommand("yaml2pdb",
99                         "Generate a PDB file from a YAML description");
100 cl::SubCommand
101     PdbToYamlSubcommand("pdb2yaml",
102                         "Generate a detailed YAML description of a PDB File");
103 
104 cl::OptionCategory TypeCategory("Symbol Type Options");
105 cl::OptionCategory FilterCategory("Filtering Options");
106 cl::OptionCategory OtherOptions("Other Options");
107 
108 namespace pretty {
109 cl::list<std::string> InputFilenames(cl::Positional,
110                                      cl::desc("<input PDB files>"),
111                                      cl::OneOrMore, cl::sub(PrettySubcommand));
112 
113 cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
114                          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
115 cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
116                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
117 cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
118                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
119 cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
120                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
121 cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
122                     cl::sub(PrettySubcommand));
123 cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
124                     cl::sub(PrettySubcommand));
125 cl::opt<bool>
126     All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
127         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
128 
129 cl::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));
133 cl::list<std::string> ExcludeTypes(
134     "exclude-types", cl::desc("Exclude types by regular expression"),
135     cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
136 cl::list<std::string> ExcludeSymbols(
137     "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
138     cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
139 cl::list<std::string> ExcludeCompilands(
140     "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
141     cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
142 
143 cl::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));
147 cl::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));
151 cl::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 
156 cl::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));
160 cl::opt<bool>
161     ExcludeSystemLibraries("no-system-libs",
162                            cl::desc("Don't show symbols from system libraries"),
163                            cl::cat(FilterCategory), cl::sub(PrettySubcommand));
164 cl::opt<bool> NoClassDefs("no-class-definitions",
165                           cl::desc("Don't display full class definitions"),
166                           cl::cat(FilterCategory), cl::sub(PrettySubcommand));
167 cl::opt<bool> NoEnumDefs("no-enum-definitions",
168                          cl::desc("Don't display full enum definitions"),
169                          cl::cat(FilterCategory), cl::sub(PrettySubcommand));
170 }
171 
172 namespace raw {
173 
174 cl::OptionCategory MsfOptions("MSF Container Options");
175 cl::OptionCategory TypeOptions("Type Record Options");
176 cl::OptionCategory FileOptions("Module & File Options");
177 cl::OptionCategory SymbolOptions("Symbol Options");
178 cl::OptionCategory MiscOptions("Miscellaneous Options");
179 
180 // MSF OPTIONS
181 cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
182                           cl::cat(MsfOptions), cl::sub(RawSubcommand));
183 cl::opt<bool> DumpStreamBlocks("stream-blocks",
184                                cl::desc("dump PDB stream blocks"),
185                                cl::cat(MsfOptions), cl::sub(RawSubcommand));
186 cl::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
191 cl::opt<bool>
192     DumpTpiRecords("tpi-records",
193                    cl::desc("dump CodeView type records from TPI stream"),
194                    cl::cat(TypeOptions), cl::sub(RawSubcommand));
195 cl::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));
199 cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
200                           cl::cat(TypeOptions), cl::sub(RawSubcommand));
201 cl::opt<bool>
202     DumpIpiRecords("ipi-records",
203                    cl::desc("dump CodeView type records from IPI stream"),
204                    cl::cat(TypeOptions), cl::sub(RawSubcommand));
205 cl::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
211 cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
212                           cl::cat(FileOptions), cl::sub(RawSubcommand));
213 cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
214                               cl::cat(FileOptions), cl::sub(RawSubcommand));
215 cl::opt<bool> DumpLineInfo("line-info",
216                            cl::desc("dump file and line information"),
217                            cl::cat(FileOptions), cl::sub(RawSubcommand));
218 
219 // SYMBOL OPTIONS
220 cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
221                              cl::cat(SymbolOptions), cl::sub(RawSubcommand));
222 cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
223                           cl::cat(SymbolOptions), cl::sub(RawSubcommand));
224 cl::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
230 cl::opt<bool> DumpSectionContribs("section-contribs",
231                                   cl::desc("dump section contributions"),
232                                   cl::cat(MiscOptions), cl::sub(RawSubcommand));
233 cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
234                              cl::cat(MiscOptions), cl::sub(RawSubcommand));
235 cl::opt<bool> DumpSectionHeaders("section-headers",
236                                  cl::desc("dump section headers"),
237                                  cl::cat(MiscOptions), cl::sub(RawSubcommand));
238 cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
239                       cl::sub(RawSubcommand));
240 
241 cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
242                                        cl::cat(MiscOptions),
243                                        cl::sub(RawSubcommand));
244 cl::opt<std::string> DumpStreamDataName("stream-name",
245                                         cl::desc("dump stream data"),
246                                         cl::cat(MiscOptions),
247                                         cl::sub(RawSubcommand));
248 
249 cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
250                      cl::cat(MiscOptions), cl::sub(RawSubcommand));
251 
252 cl::list<std::string> InputFilenames(cl::Positional,
253                                      cl::desc("<input PDB files>"),
254                                      cl::OneOrMore, cl::sub(RawSubcommand));
255 }
256 
257 namespace yaml2pdb {
258 cl::opt<std::string>
259     YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
260                       cl::sub(YamlToPdbSubcommand));
261 
262 cl::list<std::string> InputFilename(cl::Positional,
263                                     cl::desc("<input YAML file>"), cl::Required,
264                                     cl::sub(YamlToPdbSubcommand));
265 }
266 
267 namespace pdb2yaml {
268 cl::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 
274 cl::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));
278 cl::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));
282 cl::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));
286 cl::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 
291 cl::list<std::string> InputFilename(cl::Positional,
292                                     cl::desc("<input PDB file>"), cl::Required,
293                                     cl::sub(PdbToYamlSubcommand));
294 }
295 }
296 
297 static ExitOnError ExitOnErr;
298 
yamlToPdb(StringRef Path)299 static 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 
pdb2Yaml(StringRef Path)369 static 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 
dumpRaw(StringRef Path)381 static 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 
dumpPretty(StringRef Path)392 static 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 
main(int argc_,const char * argv_[])509 int 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