brintos

brintos / llvm-project-archived public Read only

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