Home | History | Annotate | Download | only in llvm-pdbdump
      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:
     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 
     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 
    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 
    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 
    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 
    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 
    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