1319780Sdim//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===// 2319780Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6319780Sdim// 7319780Sdim//===----------------------------------------------------------------------===// 8319780Sdim// 9319780Sdim// Dumps debug information present in PDB files. 10319780Sdim// 11319780Sdim//===----------------------------------------------------------------------===// 12319780Sdim 13319780Sdim#include "llvm-pdbutil.h" 14319780Sdim 15320397Sdim#include "BytesOutputStyle.h" 16320397Sdim#include "DumpOutputStyle.h" 17341825Sdim#include "ExplainOutputStyle.h" 18327952Sdim#include "InputFile.h" 19319780Sdim#include "LinePrinter.h" 20319780Sdim#include "OutputStyle.h" 21341825Sdim#include "PrettyClassDefinitionDumper.h" 22319780Sdim#include "PrettyCompilandDumper.h" 23341825Sdim#include "PrettyEnumDumper.h" 24319780Sdim#include "PrettyExternalSymbolDumper.h" 25319780Sdim#include "PrettyFunctionDumper.h" 26319780Sdim#include "PrettyTypeDumper.h" 27341825Sdim#include "PrettyTypedefDumper.h" 28319780Sdim#include "PrettyVariableDumper.h" 29319780Sdim#include "YAMLOutputStyle.h" 30319780Sdim 31319780Sdim#include "llvm/ADT/ArrayRef.h" 32319780Sdim#include "llvm/ADT/BitVector.h" 33319780Sdim#include "llvm/ADT/DenseMap.h" 34319780Sdim#include "llvm/ADT/STLExtras.h" 35319780Sdim#include "llvm/ADT/StringExtras.h" 36327952Sdim#include "llvm/BinaryFormat/Magic.h" 37319780Sdim#include "llvm/Config/config.h" 38327952Sdim#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h" 39319780Sdim#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 40319780Sdim#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" 41319780Sdim#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 42319780Sdim#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 43327952Sdim#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" 44320041Sdim#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" 45319780Sdim#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" 46319780Sdim#include "llvm/DebugInfo/MSF/MSFBuilder.h" 47319780Sdim#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 48341825Sdim#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" 49319780Sdim#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" 50319780Sdim#include "llvm/DebugInfo/PDB/IPDBSession.h" 51319780Sdim#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" 52319780Sdim#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" 53341825Sdim#include "llvm/DebugInfo/PDB/Native/InfoStream.h" 54319780Sdim#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" 55319780Sdim#include "llvm/DebugInfo/PDB/Native/NativeSession.h" 56319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBFile.h" 57319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" 58319780Sdim#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" 59319780Sdim#include "llvm/DebugInfo/PDB/Native/RawConstants.h" 60319780Sdim#include "llvm/DebugInfo/PDB/Native/RawError.h" 61319780Sdim#include "llvm/DebugInfo/PDB/Native/TpiStream.h" 62319780Sdim#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" 63319780Sdim#include "llvm/DebugInfo/PDB/PDB.h" 64319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 65319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolData.h" 66319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 67319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 68341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" 69319780Sdim#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" 70341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 71344779Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" 72344779Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 73341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 74341825Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 75319780Sdim#include "llvm/Support/BinaryByteStream.h" 76319780Sdim#include "llvm/Support/COM.h" 77319780Sdim#include "llvm/Support/CommandLine.h" 78319780Sdim#include "llvm/Support/ConvertUTF.h" 79319780Sdim#include "llvm/Support/FileOutputBuffer.h" 80319780Sdim#include "llvm/Support/FileSystem.h" 81319780Sdim#include "llvm/Support/Format.h" 82341825Sdim#include "llvm/Support/InitLLVM.h" 83327952Sdim#include "llvm/Support/LineIterator.h" 84319780Sdim#include "llvm/Support/ManagedStatic.h" 85319780Sdim#include "llvm/Support/MemoryBuffer.h" 86319780Sdim#include "llvm/Support/Path.h" 87319780Sdim#include "llvm/Support/PrettyStackTrace.h" 88319780Sdim#include "llvm/Support/Process.h" 89319780Sdim#include "llvm/Support/Regex.h" 90319780Sdim#include "llvm/Support/ScopedPrinter.h" 91319780Sdim#include "llvm/Support/Signals.h" 92319780Sdim#include "llvm/Support/raw_ostream.h" 93319780Sdim 94319780Sdimusing namespace llvm; 95319780Sdimusing namespace llvm::codeview; 96319780Sdimusing namespace llvm::msf; 97319780Sdimusing namespace llvm::pdb; 98319780Sdim 99319780Sdimnamespace opts { 100319780Sdim 101320397Sdimcl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info"); 102320397Sdimcl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file"); 103320397Sdim 104344779Sdimcl::SubCommand DiaDumpSubcommand("diadump", 105344779Sdim "Dump debug information using a DIA-like API"); 106344779Sdim 107319780Sdimcl::SubCommand 108319780Sdim PrettySubcommand("pretty", 109319780Sdim "Dump semantic information about types and symbols"); 110319780Sdim 111319780Sdimcl::SubCommand 112319780Sdim YamlToPdbSubcommand("yaml2pdb", 113319780Sdim "Generate a PDB file from a YAML description"); 114319780Sdimcl::SubCommand 115319780Sdim PdbToYamlSubcommand("pdb2yaml", 116319780Sdim "Generate a detailed YAML description of a PDB File"); 117319780Sdim 118319780Sdimcl::SubCommand MergeSubcommand("merge", 119319780Sdim "Merge multiple PDBs into a single PDB"); 120319780Sdim 121341825Sdimcl::SubCommand ExplainSubcommand("explain", 122341825Sdim "Explain the meaning of a file offset"); 123341825Sdim 124341825Sdimcl::SubCommand ExportSubcommand("export", 125341825Sdim "Write binary data from a stream to a file"); 126341825Sdim 127319780Sdimcl::OptionCategory TypeCategory("Symbol Type Options"); 128319780Sdimcl::OptionCategory FilterCategory("Filtering and Sorting Options"); 129319780Sdimcl::OptionCategory OtherOptions("Other Options"); 130319780Sdim 131320397Sdimcl::ValuesClass ChunkValues = cl::values( 132320397Sdim clEnumValN(ModuleSubsection::CrossScopeExports, "cme", 133320397Sdim "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"), 134320397Sdim clEnumValN(ModuleSubsection::CrossScopeImports, "cmi", 135320397Sdim "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"), 136320397Sdim clEnumValN(ModuleSubsection::FileChecksums, "fc", 137320397Sdim "File checksums (DEBUG_S_CHECKSUMS subsection)"), 138320397Sdim clEnumValN(ModuleSubsection::InlineeLines, "ilines", 139320397Sdim "Inlinee lines (DEBUG_S_INLINEELINES subsection)"), 140320397Sdim clEnumValN(ModuleSubsection::Lines, "lines", 141320397Sdim "Lines (DEBUG_S_LINES subsection)"), 142320397Sdim clEnumValN(ModuleSubsection::StringTable, "strings", 143320397Sdim "String Table (DEBUG_S_STRINGTABLE subsection) (not " 144320397Sdim "typically present in PDB file)"), 145320397Sdim clEnumValN(ModuleSubsection::FrameData, "frames", 146320397Sdim "Frame Data (DEBUG_S_FRAMEDATA subsection)"), 147320397Sdim clEnumValN(ModuleSubsection::Symbols, "symbols", 148320397Sdim "Symbols (DEBUG_S_SYMBOLS subsection) (not typically " 149320397Sdim "present in PDB file)"), 150320397Sdim clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas", 151320397Sdim "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"), 152320397Sdim clEnumValN(ModuleSubsection::Unknown, "unknown", 153320397Sdim "Any subsection not covered by another option"), 154320397Sdim clEnumValN(ModuleSubsection::All, "all", "All known subsections")); 155320397Sdim 156344779Sdimnamespace diadump { 157344779Sdimcl::list<std::string> InputFilenames(cl::Positional, 158344779Sdim cl::desc("<input PDB files>"), 159344779Sdim cl::OneOrMore, cl::sub(DiaDumpSubcommand)); 160344779Sdim 161344779Sdimcl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"), 162344779Sdim cl::sub(DiaDumpSubcommand)); 163344779Sdim 164344779Sdimstatic cl::opt<bool> 165344779Sdim ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"), 166344779Sdim cl::sub(DiaDumpSubcommand)); 167344779Sdimstatic cl::opt<bool> NoSymIndexIds( 168344779Sdim "no-ids", 169344779Sdim cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"), 170344779Sdim cl::sub(DiaDumpSubcommand)); 171344779Sdim 172344779Sdimstatic cl::opt<bool> 173344779Sdim Recurse("recurse", 174344779Sdim cl::desc("When dumping a SymIndexId, dump the full details of the " 175344779Sdim "corresponding record"), 176344779Sdim cl::sub(DiaDumpSubcommand)); 177344779Sdim 178344779Sdimstatic cl::opt<bool> Enums("enums", cl::desc("Dump enum types"), 179344779Sdim cl::sub(DiaDumpSubcommand)); 180344779Sdimstatic cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"), 181344779Sdim cl::sub(DiaDumpSubcommand)); 182344779Sdimstatic cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"), 183344779Sdim cl::sub(DiaDumpSubcommand)); 184344779Sdimstatic cl::opt<bool> Compilands("compilands", 185344779Sdim cl::desc("Dump compiland information"), 186344779Sdim cl::sub(DiaDumpSubcommand)); 187344779Sdimstatic cl::opt<bool> Funcsigs("funcsigs", 188344779Sdim cl::desc("Dump function signature information"), 189344779Sdim cl::sub(DiaDumpSubcommand)); 190344779Sdimstatic cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"), 191344779Sdim cl::sub(DiaDumpSubcommand)); 192344779Sdimstatic cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"), 193344779Sdim cl::sub(DiaDumpSubcommand)); 194344779Sdimstatic cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"), 195344779Sdim cl::sub(DiaDumpSubcommand)); 196344779Sdim} // namespace diadump 197344779Sdim 198319780Sdimnamespace pretty { 199319780Sdimcl::list<std::string> InputFilenames(cl::Positional, 200319780Sdim cl::desc("<input PDB files>"), 201319780Sdim cl::OneOrMore, cl::sub(PrettySubcommand)); 202319780Sdim 203341825Sdimcl::opt<bool> InjectedSources("injected-sources", 204341825Sdim cl::desc("Display injected sources"), 205341825Sdim cl::cat(OtherOptions), cl::sub(PrettySubcommand)); 206341825Sdimcl::opt<bool> ShowInjectedSourceContent( 207341825Sdim "injected-source-content", 208341825Sdim cl::desc("When displaying an injected source, display the file content"), 209341825Sdim cl::cat(OtherOptions), cl::sub(PrettySubcommand)); 210341825Sdim 211341825Sdimcl::list<std::string> WithName( 212341825Sdim "with-name", 213341825Sdim cl::desc("Display any symbol or type with the specified exact name"), 214341825Sdim cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand)); 215341825Sdim 216319780Sdimcl::opt<bool> Compilands("compilands", cl::desc("Display compilands"), 217319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 218319780Sdimcl::opt<bool> Symbols("module-syms", 219319780Sdim cl::desc("Display symbols for each compiland"), 220319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 221319780Sdimcl::opt<bool> Globals("globals", cl::desc("Dump global symbols"), 222319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 223319780Sdimcl::opt<bool> Externals("externals", cl::desc("Dump external symbols"), 224319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 225319780Sdimcl::list<SymLevel> SymTypes( 226319780Sdim "sym-types", cl::desc("Type of symbols to dump (default all)"), 227319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore, 228319780Sdim cl::values( 229319780Sdim clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"), 230319780Sdim clEnumValN(SymLevel::Data, "data", "Display data symbols"), 231319780Sdim clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"), 232319780Sdim clEnumValN(SymLevel::All, "all", "Display all symbols (default)"))); 233319780Sdim 234319780Sdimcl::opt<bool> 235319780Sdim Types("types", 236319780Sdim cl::desc("Display all types (implies -classes, -enums, -typedefs)"), 237319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 238319780Sdimcl::opt<bool> Classes("classes", cl::desc("Display class types"), 239319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 240319780Sdimcl::opt<bool> Enums("enums", cl::desc("Display enum types"), 241319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 242319780Sdimcl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"), 243319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 244344779Sdimcl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"), 245344779Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 246344779Sdimcl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"), 247344779Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 248344779Sdimcl::opt<bool> Arrays("arrays", cl::desc("Display arrays"), 249344779Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 250344779Sdimcl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"), 251344779Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 252344779Sdim 253319780Sdimcl::opt<SymbolSortMode> SymbolOrder( 254319780Sdim "symbol-order", cl::desc("symbol sort order"), 255319780Sdim cl::init(SymbolSortMode::None), 256319780Sdim cl::values(clEnumValN(SymbolSortMode::None, "none", 257319780Sdim "Undefined / no particular sort order"), 258319780Sdim clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"), 259319780Sdim clEnumValN(SymbolSortMode::Size, "size", 260319780Sdim "Sort symbols by size")), 261319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 262319780Sdim 263319780Sdimcl::opt<ClassSortMode> ClassOrder( 264319780Sdim "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None), 265319780Sdim cl::values( 266319780Sdim clEnumValN(ClassSortMode::None, "none", 267319780Sdim "Undefined / no particular sort order"), 268319780Sdim clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"), 269319780Sdim clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"), 270319780Sdim clEnumValN(ClassSortMode::Padding, "padding", 271319780Sdim "Sort classes by amount of padding"), 272319780Sdim clEnumValN(ClassSortMode::PaddingPct, "padding-pct", 273319780Sdim "Sort classes by percentage of space consumed by padding"), 274319780Sdim clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm", 275319780Sdim "Sort classes by amount of immediate padding"), 276319780Sdim clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm", 277319780Sdim "Sort classes by percentage of space consumed by immediate " 278319780Sdim "padding")), 279319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 280319780Sdim 281319780Sdimcl::opt<ClassDefinitionFormat> ClassFormat( 282319780Sdim "class-definitions", cl::desc("Class definition format"), 283319780Sdim cl::init(ClassDefinitionFormat::All), 284319780Sdim cl::values( 285319780Sdim clEnumValN(ClassDefinitionFormat::All, "all", 286319780Sdim "Display all class members including data, constants, " 287319780Sdim "typedefs, functions, etc"), 288319780Sdim clEnumValN(ClassDefinitionFormat::Layout, "layout", 289319780Sdim "Only display members that contribute to class size."), 290319780Sdim clEnumValN(ClassDefinitionFormat::None, "none", 291319780Sdim "Don't display class definitions")), 292319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 293319780Sdimcl::opt<uint32_t> ClassRecursionDepth( 294319780Sdim "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"), 295319780Sdim cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 296319780Sdim 297319780Sdimcl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory), 298319780Sdim cl::sub(PrettySubcommand)); 299319780Sdimcl::opt<bool> 300319780Sdim All("all", cl::desc("Implies all other options in 'Symbol Types' category"), 301319780Sdim cl::cat(TypeCategory), cl::sub(PrettySubcommand)); 302319780Sdim 303319780Sdimcl::opt<uint64_t> LoadAddress( 304319780Sdim "load-address", 305319780Sdim cl::desc("Assume the module is loaded at the specified address"), 306319780Sdim cl::cat(OtherOptions), cl::sub(PrettySubcommand)); 307319780Sdimcl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"), 308319780Sdim cl::cat(OtherOptions), cl::sub(PrettySubcommand)); 309319780Sdimcl::opt<cl::boolOrDefault> 310319780Sdim ColorOutput("color-output", 311319780Sdim cl::desc("Override use of color (default = isatty)"), 312319780Sdim cl::cat(OtherOptions), cl::sub(PrettySubcommand)); 313319780Sdimcl::list<std::string> ExcludeTypes( 314319780Sdim "exclude-types", cl::desc("Exclude types by regular expression"), 315319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 316319780Sdimcl::list<std::string> ExcludeSymbols( 317319780Sdim "exclude-symbols", cl::desc("Exclude symbols by regular expression"), 318319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 319319780Sdimcl::list<std::string> ExcludeCompilands( 320319780Sdim "exclude-compilands", cl::desc("Exclude compilands by regular expression"), 321319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 322319780Sdim 323319780Sdimcl::list<std::string> IncludeTypes( 324319780Sdim "include-types", 325319780Sdim cl::desc("Include only types which match a regular expression"), 326319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 327319780Sdimcl::list<std::string> IncludeSymbols( 328319780Sdim "include-symbols", 329319780Sdim cl::desc("Include only symbols which match a regular expression"), 330319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 331319780Sdimcl::list<std::string> IncludeCompilands( 332319780Sdim "include-compilands", 333319780Sdim cl::desc("Include only compilands those which match a regular expression"), 334319780Sdim cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 335319780Sdimcl::opt<uint32_t> SizeThreshold( 336319780Sdim "min-type-size", cl::desc("Displays only those types which are greater " 337319780Sdim "than or equal to the specified size."), 338319780Sdim cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 339319780Sdimcl::opt<uint32_t> PaddingThreshold( 340319780Sdim "min-class-padding", cl::desc("Displays only those classes which have at " 341319780Sdim "least the specified amount of padding."), 342319780Sdim cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 343319780Sdimcl::opt<uint32_t> ImmediatePaddingThreshold( 344319780Sdim "min-class-padding-imm", 345319780Sdim cl::desc("Displays only those classes which have at least the specified " 346319780Sdim "amount of immediate padding, ignoring padding internal to bases " 347319780Sdim "and aggregates."), 348319780Sdim cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 349319780Sdim 350319780Sdimcl::opt<bool> ExcludeCompilerGenerated( 351319780Sdim "no-compiler-generated", 352319780Sdim cl::desc("Don't show compiler generated types and symbols"), 353319780Sdim cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 354319780Sdimcl::opt<bool> 355319780Sdim ExcludeSystemLibraries("no-system-libs", 356319780Sdim cl::desc("Don't show symbols from system libraries"), 357319780Sdim cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 358319780Sdim 359319780Sdimcl::opt<bool> NoEnumDefs("no-enum-definitions", 360319780Sdim cl::desc("Don't display full enum definitions"), 361319780Sdim cl::cat(FilterCategory), cl::sub(PrettySubcommand)); 362319780Sdim} 363319780Sdim 364320041Sdimcl::OptionCategory FileOptions("Module & File Options"); 365320041Sdim 366320397Sdimnamespace bytes { 367320397Sdimcl::OptionCategory MsfBytes("MSF File Options"); 368320397Sdimcl::OptionCategory DbiBytes("Dbi Stream Options"); 369320397Sdimcl::OptionCategory PdbBytes("PDB Stream Options"); 370320397Sdimcl::OptionCategory Types("Type Options"); 371320397Sdimcl::OptionCategory ModuleCategory("Module Options"); 372319780Sdim 373320397Sdimllvm::Optional<NumberRange> DumpBlockRange; 374320397Sdimllvm::Optional<NumberRange> DumpByteRange; 375320397Sdim 376320397Sdimcl::opt<std::string> DumpBlockRangeOpt( 377320397Sdim "block-range", cl::value_desc("start[-end]"), 378320397Sdim cl::desc("Dump binary data from specified range of blocks."), 379320397Sdim cl::sub(BytesSubcommand), cl::cat(MsfBytes)); 380320397Sdim 381320397Sdimcl::opt<std::string> 382320397Sdim DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"), 383320397Sdim cl::desc("Dump binary data from specified range of bytes"), 384320397Sdim cl::sub(BytesSubcommand), cl::cat(MsfBytes)); 385320397Sdim 386320397Sdimcl::list<std::string> 387320397Sdim DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, 388320397Sdim cl::desc("Dump binary data from specified streams. Format " 389320397Sdim "is SN[:Start][@Size]"), 390320397Sdim cl::sub(BytesSubcommand), cl::cat(MsfBytes)); 391320397Sdim 392320397Sdimcl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"), 393320397Sdim cl::sub(BytesSubcommand), cl::cat(PdbBytes)); 394327952Sdimcl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"), 395327952Sdim cl::sub(BytesSubcommand), cl::cat(MsfBytes)); 396320397Sdim 397320397Sdimcl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"), 398320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 399320397Sdimcl::opt<bool> SectionMap("sm", cl::desc("Dump section map"), 400320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 401320397Sdimcl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"), 402320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 403320397Sdimcl::opt<bool> FileInfo("files", cl::desc("Dump source file info"), 404320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 405320397Sdimcl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"), 406320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 407320397Sdimcl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"), 408320397Sdim cl::sub(BytesSubcommand), cl::cat(DbiBytes)); 409320397Sdim 410320397Sdimcl::list<uint32_t> 411320397Sdim TypeIndex("type", 412320397Sdim cl::desc("Dump the type record with the given type index"), 413320397Sdim cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand), 414320397Sdim cl::cat(TypeCategory)); 415320397Sdimcl::list<uint32_t> 416320397Sdim IdIndex("id", cl::desc("Dump the id record with the given type index"), 417320397Sdim cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand), 418320397Sdim cl::cat(TypeCategory)); 419320397Sdim 420320397Sdimcl::opt<uint32_t> ModuleIndex( 421320397Sdim "mod", 422320397Sdim cl::desc( 423320397Sdim "Limit options in the Modules category to the specified module index"), 424320397Sdim cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); 425320397Sdimcl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"), 426320397Sdim cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); 427320397Sdimcl::opt<bool> ModuleC11("c11-chunks", cl::Hidden, 428320397Sdim cl::desc("Dump C11 CodeView debug chunks"), 429320397Sdim cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); 430320397Sdimcl::opt<bool> ModuleC13("chunks", 431320397Sdim cl::desc("Dump C13 CodeView debug chunk subsection"), 432320397Sdim cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); 433320397Sdimcl::opt<bool> SplitChunks( 434320397Sdim "split-chunks", 435320397Sdim cl::desc( 436320397Sdim "When dumping debug chunks, show a different section for each chunk"), 437320397Sdim cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); 438320397Sdimcl::list<std::string> InputFilenames(cl::Positional, 439320397Sdim cl::desc("<input PDB files>"), 440320397Sdim cl::OneOrMore, cl::sub(BytesSubcommand)); 441320397Sdim 442320397Sdim} // namespace bytes 443320397Sdim 444320397Sdimnamespace dump { 445320397Sdim 446319780Sdimcl::OptionCategory MsfOptions("MSF Container Options"); 447319780Sdimcl::OptionCategory TypeOptions("Type Record Options"); 448319780Sdimcl::OptionCategory SymbolOptions("Symbol Options"); 449319780Sdimcl::OptionCategory MiscOptions("Miscellaneous Options"); 450319780Sdim 451319780Sdim// MSF OPTIONS 452320041Sdimcl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"), 453320397Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 454320041Sdimcl::opt<bool> DumpStreams("streams", 455320041Sdim cl::desc("dump summary of the PDB streams"), 456320397Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 457320397Sdimcl::opt<bool> DumpStreamBlocks( 458320397Sdim "stream-blocks", 459320397Sdim cl::desc("Add block information to the output of -streams"), 460320397Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 461327952Sdimcl::opt<bool> DumpSymbolStats( 462327952Sdim "sym-stats", 463327952Sdim cl::desc("Dump a detailed breakdown of symbol usage/size for each module"), 464327952Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 465353358Sdimcl::opt<bool> DumpTypeStats( 466353358Sdim "type-stats", 467353358Sdim cl::desc("Dump a detailed breakdown of type usage/size"), 468353358Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 469327952Sdimcl::opt<bool> DumpUdtStats( 470327952Sdim "udt-stats", 471327952Sdim cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"), 472327952Sdim cl::cat(MsfOptions), cl::sub(DumpSubcommand)); 473327952Sdim 474319780Sdim// TYPE OPTIONS 475320041Sdimcl::opt<bool> DumpTypes("types", 476320041Sdim cl::desc("dump CodeView type records from TPI stream"), 477320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 478320041Sdimcl::opt<bool> DumpTypeData( 479320041Sdim "type-data", 480319780Sdim cl::desc("dump CodeView type record raw bytes from TPI stream"), 481320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 482353358Sdimcl::opt<bool> 483353358Sdim DumpTypeRefStats("type-ref-stats", 484353358Sdim cl::desc("dump statistics on the number and size of types " 485353358Sdim "transitively referenced by symbol records"), 486353358Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 487320041Sdim 488320041Sdimcl::opt<bool> DumpTypeExtras("type-extras", 489320041Sdim cl::desc("dump type hashes and index offsets"), 490320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 491320041Sdim 492344779Sdimcl::opt<bool> DontResolveForwardRefs( 493344779Sdim "dont-resolve-forward-refs", 494344779Sdim cl::desc("When dumping type records for classes, unions, enums, and " 495344779Sdim "structs, don't try to resolve forward references"), 496344779Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 497344779Sdim 498320397Sdimcl::list<uint32_t> DumpTypeIndex( 499320970Sdim "type-index", cl::ZeroOrMore, cl::CommaSeparated, 500320397Sdim cl::desc("only dump types with the specified hexadecimal type index"), 501320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 502320397Sdim 503320041Sdimcl::opt<bool> DumpIds("ids", 504320041Sdim cl::desc("dump CodeView type records from IPI stream"), 505320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 506319780Sdimcl::opt<bool> 507320041Sdim DumpIdData("id-data", 508320041Sdim cl::desc("dump CodeView type record raw bytes from IPI stream"), 509320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 510319780Sdim 511320041Sdimcl::opt<bool> DumpIdExtras("id-extras", 512320041Sdim cl::desc("dump id hashes and index offsets"), 513320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 514320397Sdimcl::list<uint32_t> DumpIdIndex( 515320970Sdim "id-index", cl::ZeroOrMore, cl::CommaSeparated, 516320397Sdim cl::desc("only dump ids with the specified hexadecimal type index"), 517320397Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 518320041Sdim 519320572Sdimcl::opt<bool> DumpTypeDependents( 520320572Sdim "dependents", 521320572Sdim cl::desc("In conjunection with -type-index and -id-index, dumps the entire " 522320572Sdim "dependency graph for the specified index instead of " 523320572Sdim "just the single record with the specified index"), 524320572Sdim cl::cat(TypeOptions), cl::sub(DumpSubcommand)); 525320572Sdim 526319780Sdim// SYMBOL OPTIONS 527327952Sdimcl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"), 528327952Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 529327952Sdimcl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"), 530327952Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 531344779Sdimcl::list<std::string> DumpGlobalNames( 532344779Sdim "global-name", 533344779Sdim cl::desc( 534344779Sdim "With -globals, only dump globals whose name matches the given value"), 535344779Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand), cl::ZeroOrMore); 536319780Sdimcl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"), 537320397Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 538327952Sdimcl::opt<bool> DumpPublicExtras("public-extras", 539327952Sdim cl::desc("dump Publics hashes and address maps"), 540327952Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 541341825Sdimcl::opt<bool> 542341825Sdim DumpGSIRecords("gsi-records", 543341825Sdim cl::desc("dump public / global common record stream"), 544341825Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 545320041Sdimcl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"), 546320397Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 547320041Sdim 548319780Sdimcl::opt<bool> 549320041Sdim DumpSymRecordBytes("sym-data", 550319780Sdim cl::desc("dump CodeView symbol record raw bytes"), 551320397Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 552319780Sdim 553344779Sdimcl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), 554344779Sdim cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); 555344779Sdim 556320041Sdim// MODULE & FILE OPTIONS 557320041Sdimcl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"), 558320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 559320041Sdimcl::opt<bool> DumpModuleFiles( 560320041Sdim "files", 561320041Sdim cl::desc("Dump the source files that contribute to each module's."), 562320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 563320041Sdimcl::opt<bool> DumpLines( 564320041Sdim "l", 565320041Sdim cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"), 566320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 567320041Sdimcl::opt<bool> DumpInlineeLines( 568320041Sdim "il", 569320041Sdim cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"), 570320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 571320041Sdimcl::opt<bool> DumpXmi( 572320041Sdim "xmi", 573320041Sdim cl::desc( 574320041Sdim "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"), 575320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 576320041Sdimcl::opt<bool> DumpXme( 577320041Sdim "xme", 578320041Sdim cl::desc( 579320041Sdim "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"), 580320397Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 581327952Sdimcl::opt<uint32_t> DumpModi("modi", cl::Optional, 582327952Sdim cl::desc("For all options that iterate over " 583327952Sdim "modules, limit to the specified module"), 584327952Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 585327952Sdimcl::opt<bool> JustMyCode("jmc", cl::Optional, 586327952Sdim cl::desc("For all options that iterate over modules, " 587327952Sdim "ignore modules from system libraries"), 588327952Sdim cl::cat(FileOptions), cl::sub(DumpSubcommand)); 589320041Sdim 590319780Sdim// MISCELLANEOUS OPTIONS 591341825Sdimcl::opt<bool> DumpNamedStreams("named-streams", 592341825Sdim cl::desc("dump PDB named stream table"), 593341825Sdim cl::cat(MiscOptions), cl::sub(DumpSubcommand)); 594341825Sdim 595319780Sdimcl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"), 596320397Sdim cl::cat(MiscOptions), cl::sub(DumpSubcommand)); 597341825Sdimcl::opt<bool> DumpStringTableDetails("string-table-details", 598341825Sdim cl::desc("dump PDB String Table Details"), 599341825Sdim cl::cat(MiscOptions), 600341825Sdim cl::sub(DumpSubcommand)); 601319780Sdim 602319780Sdimcl::opt<bool> DumpSectionContribs("section-contribs", 603319780Sdim cl::desc("dump section contributions"), 604320397Sdim cl::cat(MiscOptions), 605320397Sdim cl::sub(DumpSubcommand)); 606319780Sdimcl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"), 607320397Sdim cl::cat(MiscOptions), cl::sub(DumpSubcommand)); 608327952Sdimcl::opt<bool> DumpSectionHeaders("section-headers", 609327952Sdim cl::desc("Dump image section headers"), 610327952Sdim cl::cat(MiscOptions), cl::sub(DumpSubcommand)); 611319780Sdim 612319780Sdimcl::opt<bool> RawAll("all", cl::desc("Implies most other options."), 613320397Sdim cl::cat(MiscOptions), cl::sub(DumpSubcommand)); 614319780Sdim 615319780Sdimcl::list<std::string> InputFilenames(cl::Positional, 616319780Sdim cl::desc("<input PDB files>"), 617320397Sdim cl::OneOrMore, cl::sub(DumpSubcommand)); 618319780Sdim} 619319780Sdim 620319780Sdimnamespace yaml2pdb { 621319780Sdimcl::opt<std::string> 622319780Sdim YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), 623319780Sdim cl::sub(YamlToPdbSubcommand)); 624319780Sdim 625319780Sdimcl::opt<std::string> InputFilename(cl::Positional, 626319780Sdim cl::desc("<input YAML file>"), cl::Required, 627319780Sdim cl::sub(YamlToPdbSubcommand)); 628319780Sdim} 629319780Sdim 630319780Sdimnamespace pdb2yaml { 631319780Sdimcl::opt<bool> All("all", 632319780Sdim cl::desc("Dump everything we know how to dump."), 633319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 634319780Sdimcl::opt<bool> NoFileHeaders("no-file-headers", 635319780Sdim cl::desc("Do not dump MSF file headers"), 636319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 637319780Sdimcl::opt<bool> Minimal("minimal", 638319780Sdim cl::desc("Don't write fields with default values"), 639319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 640319780Sdim 641319780Sdimcl::opt<bool> StreamMetadata( 642319780Sdim "stream-metadata", 643319780Sdim cl::desc("Dump the number of streams and each stream's size"), 644319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 645319780Sdimcl::opt<bool> StreamDirectory( 646319780Sdim "stream-directory", 647319780Sdim cl::desc("Dump each stream's block map (implies -stream-metadata)"), 648319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 649319780Sdimcl::opt<bool> PdbStream("pdb-stream", 650319780Sdim cl::desc("Dump the PDB Stream (Stream 1)"), 651319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 652319780Sdim 653319780Sdimcl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"), 654319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 655319780Sdim 656319780Sdimcl::opt<bool> DbiStream("dbi-stream", 657319780Sdim cl::desc("Dump the DBI Stream Headers (Stream 2)"), 658319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 659319780Sdim 660319780Sdimcl::opt<bool> TpiStream("tpi-stream", 661319780Sdim cl::desc("Dump the TPI Stream (Stream 3)"), 662319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 663319780Sdim 664319780Sdimcl::opt<bool> IpiStream("ipi-stream", 665319780Sdim cl::desc("Dump the IPI Stream (Stream 5)"), 666319780Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 667319780Sdim 668344779Sdimcl::opt<bool> PublicsStream("publics-stream", 669344779Sdim cl::desc("Dump the Publics Stream"), 670344779Sdim cl::sub(PdbToYamlSubcommand), cl::init(false)); 671344779Sdim 672319780Sdim// MODULE & FILE OPTIONS 673319780Sdimcl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"), 674320041Sdim cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand)); 675319780Sdimcl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"), 676320041Sdim cl::cat(FileOptions), 677319780Sdim cl::sub(PdbToYamlSubcommand)); 678319780Sdimcl::list<ModuleSubsection> DumpModuleSubsections( 679319780Sdim "subsections", cl::ZeroOrMore, cl::CommaSeparated, 680320397Sdim cl::desc("dump subsections from each module's debug stream"), ChunkValues, 681320041Sdim cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand)); 682319780Sdimcl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"), 683320041Sdim cl::cat(FileOptions), 684319780Sdim cl::sub(PdbToYamlSubcommand)); 685319780Sdim 686320041Sdimcl::list<std::string> InputFilename(cl::Positional, 687320041Sdim cl::desc("<input PDB file>"), cl::Required, 688320041Sdim cl::sub(PdbToYamlSubcommand)); 689320041Sdim} // namespace pdb2yaml 690320041Sdim 691319780Sdimnamespace merge { 692319780Sdimcl::list<std::string> InputFilenames(cl::Positional, 693319780Sdim cl::desc("<input PDB files>"), 694319780Sdim cl::OneOrMore, cl::sub(MergeSubcommand)); 695319780Sdimcl::opt<std::string> 696319780Sdim PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), 697319780Sdim cl::sub(MergeSubcommand)); 698319780Sdim} 699341825Sdim 700341825Sdimnamespace explain { 701341825Sdimcl::list<std::string> InputFilename(cl::Positional, 702341825Sdim cl::desc("<input PDB file>"), cl::Required, 703341825Sdim cl::sub(ExplainSubcommand)); 704341825Sdim 705341825Sdimcl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"), 706341825Sdim cl::sub(ExplainSubcommand), cl::OneOrMore); 707341825Sdim 708341825Sdimcl::opt<InputFileType> InputType( 709341825Sdim "input-type", cl::desc("Specify how to interpret the input file"), 710341825Sdim cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand), 711341825Sdim cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file", 712341825Sdim "Treat input as a PDB file (default)"), 713341825Sdim clEnumValN(InputFileType::PDBStream, "pdb-stream", 714341825Sdim "Treat input as raw contents of PDB stream"), 715341825Sdim clEnumValN(InputFileType::DBIStream, "dbi-stream", 716341825Sdim "Treat input as raw contents of DBI stream"), 717341825Sdim clEnumValN(InputFileType::Names, "names-stream", 718341825Sdim "Treat input as raw contents of /names named stream"), 719341825Sdim clEnumValN(InputFileType::ModuleStream, "mod-stream", 720341825Sdim "Treat input as raw contents of a module stream"))); 721341825Sdim} // namespace explain 722341825Sdim 723341825Sdimnamespace exportstream { 724341825Sdimcl::list<std::string> InputFilename(cl::Positional, 725341825Sdim cl::desc("<input PDB file>"), cl::Required, 726341825Sdim cl::sub(ExportSubcommand)); 727341825Sdimcl::opt<std::string> OutputFile("out", 728341825Sdim cl::desc("The file to write the stream to"), 729341825Sdim cl::Required, cl::sub(ExportSubcommand)); 730341825Sdimcl::opt<std::string> 731341825Sdim Stream("stream", cl::Required, 732341825Sdim cl::desc("The index or name of the stream whose contents to export"), 733341825Sdim cl::sub(ExportSubcommand)); 734341825Sdimcl::opt<bool> ForceName("name", 735341825Sdim cl::desc("Force the interpretation of -stream as a " 736341825Sdim "string, even if it is a valid integer"), 737341825Sdim cl::sub(ExportSubcommand), cl::Optional, 738341825Sdim cl::init(false)); 739341825Sdim} // namespace exportstream 740319780Sdim} 741319780Sdim 742319780Sdimstatic ExitOnError ExitOnErr; 743319780Sdim 744319780Sdimstatic void yamlToPdb(StringRef Path) { 745319780Sdim BumpPtrAllocator Allocator; 746319780Sdim ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = 747319780Sdim MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, 748319780Sdim /*RequiresNullTerminator=*/false); 749319780Sdim 750319780Sdim if (ErrorOrBuffer.getError()) { 751344779Sdim ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError()))); 752319780Sdim } 753319780Sdim 754319780Sdim std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get(); 755319780Sdim 756319780Sdim llvm::yaml::Input In(Buffer->getBuffer()); 757319780Sdim pdb::yaml::PdbObject YamlObj(Allocator); 758319780Sdim In >> YamlObj; 759319780Sdim 760319780Sdim PDBFileBuilder Builder(Allocator); 761319780Sdim 762319780Sdim uint32_t BlockSize = 4096; 763319780Sdim if (YamlObj.Headers.hasValue()) 764319780Sdim BlockSize = YamlObj.Headers->SuperBlock.BlockSize; 765319780Sdim ExitOnErr(Builder.initialize(BlockSize)); 766319780Sdim // Add each of the reserved streams. We ignore stream metadata in the 767319780Sdim // yaml, because we will reconstruct our own view of the streams. For 768319780Sdim // example, the YAML may say that there were 20 streams in the original 769319780Sdim // PDB, but maybe we only dump a subset of those 20 streams, so we will 770319780Sdim // have fewer, and the ones we do have may end up with different indices 771319780Sdim // than the ones in the original PDB. So we just start with a clean slate. 772319780Sdim for (uint32_t I = 0; I < kSpecialStreamCount; ++I) 773319780Sdim ExitOnErr(Builder.getMsfBuilder().addStream(0)); 774319780Sdim 775320041Sdim StringsAndChecksums Strings; 776320041Sdim Strings.setStrings(std::make_shared<DebugStringTableSubsection>()); 777320041Sdim 778319780Sdim if (YamlObj.StringTable.hasValue()) { 779319780Sdim for (auto S : *YamlObj.StringTable) 780320041Sdim Strings.strings()->insert(S); 781319780Sdim } 782319780Sdim 783319780Sdim pdb::yaml::PdbInfoStream DefaultInfoStream; 784319780Sdim pdb::yaml::PdbDbiStream DefaultDbiStream; 785319780Sdim pdb::yaml::PdbTpiStream DefaultTpiStream; 786319780Sdim pdb::yaml::PdbTpiStream DefaultIpiStream; 787319780Sdim 788319780Sdim const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream); 789319780Sdim 790319780Sdim auto &InfoBuilder = Builder.getInfoBuilder(); 791319780Sdim InfoBuilder.setAge(Info.Age); 792319780Sdim InfoBuilder.setGuid(Info.Guid); 793319780Sdim InfoBuilder.setSignature(Info.Signature); 794319780Sdim InfoBuilder.setVersion(Info.Version); 795319780Sdim for (auto F : Info.Features) 796319780Sdim InfoBuilder.addFeature(F); 797319780Sdim 798319780Sdim const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream); 799319780Sdim auto &DbiBuilder = Builder.getDbiBuilder(); 800319780Sdim DbiBuilder.setAge(Dbi.Age); 801319780Sdim DbiBuilder.setBuildNumber(Dbi.BuildNumber); 802319780Sdim DbiBuilder.setFlags(Dbi.Flags); 803319780Sdim DbiBuilder.setMachineType(Dbi.MachineType); 804319780Sdim DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld); 805319780Sdim DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion); 806319780Sdim DbiBuilder.setVersionHeader(Dbi.VerHeader); 807319780Sdim for (const auto &MI : Dbi.ModInfos) { 808319780Sdim auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod)); 809319780Sdim ModiBuilder.setObjFileName(MI.Obj); 810319780Sdim 811319780Sdim for (auto S : MI.SourceFiles) 812327952Sdim ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S)); 813319780Sdim if (MI.Modi.hasValue()) { 814319780Sdim const auto &ModiStream = *MI.Modi; 815319780Sdim for (auto Symbol : ModiStream.Symbols) { 816319780Sdim ModiBuilder.addSymbol( 817319780Sdim Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb)); 818319780Sdim } 819319780Sdim } 820319780Sdim 821320041Sdim // Each module has its own checksum subsection, so scan for it every time. 822320041Sdim Strings.setChecksums(nullptr); 823320041Sdim CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings); 824320041Sdim 825319780Sdim auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList( 826319780Sdim Allocator, MI.Subsections, Strings)); 827319780Sdim for (auto &SS : CodeViewSubsections) { 828320041Sdim ModiBuilder.addDebugSubsection(SS); 829319780Sdim } 830319780Sdim } 831319780Sdim 832319780Sdim auto &TpiBuilder = Builder.getTpiBuilder(); 833319780Sdim const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream); 834319780Sdim TpiBuilder.setVersionHeader(Tpi.Version); 835327952Sdim AppendingTypeTableBuilder TS(Allocator); 836319780Sdim for (const auto &R : Tpi.Records) { 837327952Sdim CVType Type = R.toCodeViewRecord(TS); 838319780Sdim TpiBuilder.addTypeRecord(Type.RecordData, None); 839319780Sdim } 840319780Sdim 841319780Sdim const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream); 842319780Sdim auto &IpiBuilder = Builder.getIpiBuilder(); 843319780Sdim IpiBuilder.setVersionHeader(Ipi.Version); 844319780Sdim for (const auto &R : Ipi.Records) { 845327952Sdim CVType Type = R.toCodeViewRecord(TS); 846319780Sdim IpiBuilder.addTypeRecord(Type.RecordData, None); 847319780Sdim } 848319780Sdim 849320041Sdim Builder.getStringTableBuilder().setStrings(*Strings.strings()); 850320041Sdim 851344779Sdim codeview::GUID IgnoredOutGuid; 852344779Sdim ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid)); 853319780Sdim} 854319780Sdim 855319780Sdimstatic PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) { 856319780Sdim ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session)); 857319780Sdim 858319780Sdim NativeSession *NS = static_cast<NativeSession *>(Session.get()); 859319780Sdim return NS->getPDBFile(); 860319780Sdim} 861319780Sdim 862319780Sdimstatic void pdb2Yaml(StringRef Path) { 863319780Sdim std::unique_ptr<IPDBSession> Session; 864319780Sdim auto &File = loadPDB(Path, Session); 865319780Sdim 866360784Sdim auto O = std::make_unique<YAMLOutputStyle>(File); 867360784Sdim O = std::make_unique<YAMLOutputStyle>(File); 868319780Sdim 869319780Sdim ExitOnErr(O->dump()); 870319780Sdim} 871319780Sdim 872319780Sdimstatic void dumpRaw(StringRef Path) { 873327952Sdim InputFile IF = ExitOnErr(InputFile::open(Path)); 874319780Sdim 875360784Sdim auto O = std::make_unique<DumpOutputStyle>(IF); 876319780Sdim ExitOnErr(O->dump()); 877319780Sdim} 878319780Sdim 879320397Sdimstatic void dumpBytes(StringRef Path) { 880320397Sdim std::unique_ptr<IPDBSession> Session; 881320397Sdim auto &File = loadPDB(Path, Session); 882320397Sdim 883360784Sdim auto O = std::make_unique<BytesOutputStyle>(File); 884320397Sdim 885320397Sdim ExitOnErr(O->dump()); 886320397Sdim} 887320397Sdim 888319780Sdimbool opts::pretty::shouldDumpSymLevel(SymLevel Search) { 889319780Sdim if (SymTypes.empty()) 890319780Sdim return true; 891319780Sdim if (llvm::find(SymTypes, Search) != SymTypes.end()) 892319780Sdim return true; 893319780Sdim if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end()) 894319780Sdim return true; 895319780Sdim return false; 896319780Sdim} 897319780Sdim 898319780Sdimuint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) { 899319780Sdim auto SymbolType = Symbol.getType(); 900319780Sdim const IPDBRawSymbol &RawType = SymbolType->getRawSymbol(); 901319780Sdim 902319780Sdim return RawType.getLength(); 903319780Sdim} 904319780Sdim 905319780Sdimbool opts::pretty::compareFunctionSymbols( 906319780Sdim const std::unique_ptr<PDBSymbolFunc> &F1, 907319780Sdim const std::unique_ptr<PDBSymbolFunc> &F2) { 908319780Sdim assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); 909319780Sdim 910319780Sdim if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) 911319780Sdim return F1->getName() < F2->getName(); 912319780Sdim 913319780Sdim // Note that we intentionally sort in descending order on length, since 914319780Sdim // long functions are more interesting than short functions. 915319780Sdim return F1->getLength() > F2->getLength(); 916319780Sdim} 917319780Sdim 918319780Sdimbool opts::pretty::compareDataSymbols( 919319780Sdim const std::unique_ptr<PDBSymbolData> &F1, 920319780Sdim const std::unique_ptr<PDBSymbolData> &F2) { 921319780Sdim assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); 922319780Sdim 923319780Sdim if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) 924319780Sdim return F1->getName() < F2->getName(); 925319780Sdim 926319780Sdim // Note that we intentionally sort in descending order on length, since 927319780Sdim // large types are more interesting than short ones. 928319780Sdim return getTypeLength(*F1) > getTypeLength(*F2); 929319780Sdim} 930319780Sdim 931341825Sdimstatic std::string stringOr(std::string Str, std::string IfEmpty) { 932341825Sdim return (Str.empty()) ? IfEmpty : Str; 933341825Sdim} 934341825Sdim 935341825Sdimstatic void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) { 936341825Sdim auto Sources = Session.getInjectedSources(); 937353358Sdim if (!Sources || !Sources->getChildCount()) { 938341825Sdim Printer.printLine("There are no injected sources."); 939341825Sdim return; 940341825Sdim } 941341825Sdim 942341825Sdim while (auto IS = Sources->getNext()) { 943341825Sdim Printer.NewLine(); 944341825Sdim std::string File = stringOr(IS->getFileName(), "<null>"); 945341825Sdim uint64_t Size = IS->getCodeByteSize(); 946341825Sdim std::string Obj = stringOr(IS->getObjectFileName(), "<null>"); 947341825Sdim std::string VFName = stringOr(IS->getVirtualFileName(), "<null>"); 948341825Sdim uint32_t CRC = IS->getCrc32(); 949341825Sdim 950341825Sdim WithColor(Printer, PDB_ColorItem::Path).get() << File; 951341825Sdim Printer << " ("; 952341825Sdim WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size; 953341825Sdim Printer << " bytes): "; 954341825Sdim WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj"; 955341825Sdim Printer << "="; 956341825Sdim WithColor(Printer, PDB_ColorItem::Path).get() << Obj; 957341825Sdim Printer << ", "; 958341825Sdim WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname"; 959341825Sdim Printer << "="; 960341825Sdim WithColor(Printer, PDB_ColorItem::Path).get() << VFName; 961341825Sdim Printer << ", "; 962341825Sdim WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc"; 963341825Sdim Printer << "="; 964341825Sdim WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC; 965341825Sdim Printer << ", "; 966341825Sdim WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression"; 967341825Sdim Printer << "="; 968353358Sdim dumpPDBSourceCompression( 969353358Sdim WithColor(Printer, PDB_ColorItem::LiteralValue).get(), 970353358Sdim IS->getCompression()); 971341825Sdim 972341825Sdim if (!opts::pretty::ShowInjectedSourceContent) 973341825Sdim continue; 974341825Sdim 975341825Sdim // Set the indent level to 0 when printing file content. 976341825Sdim int Indent = Printer.getIndentLevel(); 977341825Sdim Printer.Unindent(Indent); 978341825Sdim 979353358Sdim if (IS->getCompression() == PDB_SourceCompression::None) 980353358Sdim Printer.printLine(IS->getCode()); 981353358Sdim else 982353358Sdim Printer.formatBinary("Compressed data", 983353358Sdim arrayRefFromStringRef(IS->getCode()), 984353358Sdim /*StartOffset=*/0); 985341825Sdim 986341825Sdim // Re-indent back to the original level. 987341825Sdim Printer.Indent(Indent); 988341825Sdim } 989341825Sdim} 990341825Sdim 991344779Sdimtemplate <typename OuterT, typename ChildT> 992344779Sdimvoid diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids, 993344779Sdim PdbSymbolIdField Recurse) { 994344779Sdim OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer); 995344779Sdim if (!ConcreteOuter) 996344779Sdim return; 997344779Sdim 998344779Sdim auto Children = ConcreteOuter->template findAllChildren<ChildT>(); 999344779Sdim while (auto Child = Children->getNext()) { 1000344779Sdim outs() << " {"; 1001344779Sdim Child->defaultDump(outs(), 4, Ids, Recurse); 1002344779Sdim outs() << "\n }\n"; 1003344779Sdim } 1004344779Sdim} 1005344779Sdim 1006344779Sdimstatic void dumpDia(StringRef Path) { 1007344779Sdim std::unique_ptr<IPDBSession> Session; 1008344779Sdim 1009344779Sdim const auto ReaderType = 1010344779Sdim opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA; 1011344779Sdim ExitOnErr(loadDataForPDB(ReaderType, Path, Session)); 1012344779Sdim 1013344779Sdim auto GlobalScope = Session->getGlobalScope(); 1014344779Sdim 1015344779Sdim std::vector<PDB_SymType> SymTypes; 1016344779Sdim 1017344779Sdim if (opts::diadump::Compilands) 1018344779Sdim SymTypes.push_back(PDB_SymType::Compiland); 1019344779Sdim if (opts::diadump::Enums) 1020344779Sdim SymTypes.push_back(PDB_SymType::Enum); 1021344779Sdim if (opts::diadump::Pointers) 1022344779Sdim SymTypes.push_back(PDB_SymType::PointerType); 1023344779Sdim if (opts::diadump::UDTs) 1024344779Sdim SymTypes.push_back(PDB_SymType::UDT); 1025344779Sdim if (opts::diadump::Funcsigs) 1026344779Sdim SymTypes.push_back(PDB_SymType::FunctionSig); 1027344779Sdim if (opts::diadump::Arrays) 1028344779Sdim SymTypes.push_back(PDB_SymType::ArrayType); 1029344779Sdim if (opts::diadump::VTShapes) 1030344779Sdim SymTypes.push_back(PDB_SymType::VTableShape); 1031344779Sdim if (opts::diadump::Typedefs) 1032344779Sdim SymTypes.push_back(PDB_SymType::Typedef); 1033344779Sdim PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None 1034344779Sdim : PdbSymbolIdField::All; 1035344779Sdim 1036344779Sdim PdbSymbolIdField Recurse = PdbSymbolIdField::None; 1037344779Sdim if (opts::diadump::Recurse) 1038344779Sdim Recurse = PdbSymbolIdField::All; 1039344779Sdim if (!opts::diadump::ShowClassHierarchy) 1040344779Sdim Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent); 1041344779Sdim 1042344779Sdim for (PDB_SymType ST : SymTypes) { 1043344779Sdim auto Children = GlobalScope->findAllChildren(ST); 1044344779Sdim while (auto Child = Children->getNext()) { 1045344779Sdim outs() << "{"; 1046344779Sdim Child->defaultDump(outs(), 2, Ids, Recurse); 1047344779Sdim 1048344779Sdim diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse); 1049344779Sdim outs() << "\n}\n"; 1050344779Sdim } 1051344779Sdim } 1052344779Sdim} 1053344779Sdim 1054319780Sdimstatic void dumpPretty(StringRef Path) { 1055319780Sdim std::unique_ptr<IPDBSession> Session; 1056319780Sdim 1057319780Sdim const auto ReaderType = 1058319780Sdim opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA; 1059319780Sdim ExitOnErr(loadDataForPDB(ReaderType, Path, Session)); 1060319780Sdim 1061319780Sdim if (opts::pretty::LoadAddress) 1062319780Sdim Session->setLoadAddress(opts::pretty::LoadAddress); 1063319780Sdim 1064319780Sdim auto &Stream = outs(); 1065319780Sdim const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET 1066319780Sdim ? Stream.has_colors() 1067319780Sdim : opts::pretty::ColorOutput == cl::BOU_TRUE; 1068319780Sdim LinePrinter Printer(2, UseColor, Stream); 1069319780Sdim 1070319780Sdim auto GlobalScope(Session->getGlobalScope()); 1071341825Sdim if (!GlobalScope) 1072341825Sdim return; 1073319780Sdim std::string FileName(GlobalScope->getSymbolsFileName()); 1074319780Sdim 1075319780Sdim WithColor(Printer, PDB_ColorItem::None).get() << "Summary for "; 1076319780Sdim WithColor(Printer, PDB_ColorItem::Path).get() << FileName; 1077319780Sdim Printer.Indent(); 1078319780Sdim uint64_t FileSize = 0; 1079319780Sdim 1080319780Sdim Printer.NewLine(); 1081319780Sdim WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size"; 1082319780Sdim if (!sys::fs::file_size(FileName, FileSize)) { 1083319780Sdim Printer << ": " << FileSize << " bytes"; 1084319780Sdim } else { 1085319780Sdim Printer << ": (Unable to obtain file size)"; 1086319780Sdim } 1087319780Sdim 1088319780Sdim Printer.NewLine(); 1089319780Sdim WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid"; 1090319780Sdim Printer << ": " << GlobalScope->getGuid(); 1091319780Sdim 1092319780Sdim Printer.NewLine(); 1093319780Sdim WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age"; 1094319780Sdim Printer << ": " << GlobalScope->getAge(); 1095319780Sdim 1096319780Sdim Printer.NewLine(); 1097319780Sdim WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes"; 1098319780Sdim Printer << ": "; 1099319780Sdim if (GlobalScope->hasCTypes()) 1100319780Sdim outs() << "HasCTypes "; 1101319780Sdim if (GlobalScope->hasPrivateSymbols()) 1102319780Sdim outs() << "HasPrivateSymbols "; 1103319780Sdim Printer.Unindent(); 1104319780Sdim 1105341825Sdim if (!opts::pretty::WithName.empty()) { 1106341825Sdim Printer.NewLine(); 1107341825Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() 1108341825Sdim << "---SYMBOLS & TYPES BY NAME---"; 1109341825Sdim 1110341825Sdim for (StringRef Name : opts::pretty::WithName) { 1111341825Sdim auto Symbols = GlobalScope->findChildren( 1112341825Sdim PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive); 1113341825Sdim if (!Symbols || Symbols->getChildCount() == 0) { 1114341825Sdim Printer.formatLine("[not found] - {0}", Name); 1115341825Sdim continue; 1116341825Sdim } 1117341825Sdim Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(), 1118341825Sdim Name); 1119341825Sdim 1120341825Sdim AutoIndent Indent(Printer); 1121341825Sdim Printer.NewLine(); 1122341825Sdim 1123341825Sdim while (auto Symbol = Symbols->getNext()) { 1124341825Sdim switch (Symbol->getSymTag()) { 1125341825Sdim case PDB_SymType::Typedef: { 1126341825Sdim TypedefDumper TD(Printer); 1127341825Sdim std::unique_ptr<PDBSymbolTypeTypedef> T = 1128341825Sdim llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol)); 1129341825Sdim TD.start(*T); 1130341825Sdim break; 1131341825Sdim } 1132341825Sdim case PDB_SymType::Enum: { 1133341825Sdim EnumDumper ED(Printer); 1134341825Sdim std::unique_ptr<PDBSymbolTypeEnum> E = 1135341825Sdim llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol)); 1136341825Sdim ED.start(*E); 1137341825Sdim break; 1138341825Sdim } 1139341825Sdim case PDB_SymType::UDT: { 1140341825Sdim ClassDefinitionDumper CD(Printer); 1141341825Sdim std::unique_ptr<PDBSymbolTypeUDT> C = 1142341825Sdim llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol)); 1143341825Sdim CD.start(*C); 1144341825Sdim break; 1145341825Sdim } 1146341825Sdim case PDB_SymType::BaseClass: 1147341825Sdim case PDB_SymType::Friend: { 1148341825Sdim TypeDumper TD(Printer); 1149341825Sdim Symbol->dump(TD); 1150341825Sdim break; 1151341825Sdim } 1152341825Sdim case PDB_SymType::Function: { 1153341825Sdim FunctionDumper FD(Printer); 1154341825Sdim std::unique_ptr<PDBSymbolFunc> F = 1155341825Sdim llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol)); 1156341825Sdim FD.start(*F, FunctionDumper::PointerType::None); 1157341825Sdim break; 1158341825Sdim } 1159341825Sdim case PDB_SymType::Data: { 1160341825Sdim VariableDumper VD(Printer); 1161341825Sdim std::unique_ptr<PDBSymbolData> D = 1162341825Sdim llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol)); 1163341825Sdim VD.start(*D); 1164341825Sdim break; 1165341825Sdim } 1166341825Sdim case PDB_SymType::PublicSymbol: { 1167341825Sdim ExternalSymbolDumper ED(Printer); 1168341825Sdim std::unique_ptr<PDBSymbolPublicSymbol> PS = 1169341825Sdim llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol)); 1170341825Sdim ED.dump(*PS); 1171341825Sdim break; 1172341825Sdim } 1173341825Sdim default: 1174341825Sdim llvm_unreachable("Unexpected symbol tag!"); 1175341825Sdim } 1176341825Sdim } 1177341825Sdim } 1178341825Sdim llvm::outs().flush(); 1179341825Sdim } 1180341825Sdim 1181319780Sdim if (opts::pretty::Compilands) { 1182319780Sdim Printer.NewLine(); 1183319780Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() 1184319780Sdim << "---COMPILANDS---"; 1185344779Sdim auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>(); 1186344779Sdim 1187344779Sdim if (Compilands) { 1188341825Sdim Printer.Indent(); 1189341825Sdim CompilandDumper Dumper(Printer); 1190341825Sdim CompilandDumpFlags options = CompilandDumper::Flags::None; 1191341825Sdim if (opts::pretty::Lines) 1192341825Sdim options = options | CompilandDumper::Flags::Lines; 1193341825Sdim while (auto Compiland = Compilands->getNext()) 1194341825Sdim Dumper.start(*Compiland, options); 1195341825Sdim Printer.Unindent(); 1196341825Sdim } 1197319780Sdim } 1198319780Sdim 1199344779Sdim if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs || 1200344779Sdim opts::pretty::Funcsigs || opts::pretty::Pointers || 1201344779Sdim opts::pretty::Arrays || opts::pretty::VTShapes) { 1202319780Sdim Printer.NewLine(); 1203319780Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---"; 1204319780Sdim Printer.Indent(); 1205319780Sdim TypeDumper Dumper(Printer); 1206319780Sdim Dumper.start(*GlobalScope); 1207319780Sdim Printer.Unindent(); 1208319780Sdim } 1209319780Sdim 1210319780Sdim if (opts::pretty::Symbols) { 1211319780Sdim Printer.NewLine(); 1212319780Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---"; 1213341825Sdim if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) { 1214341825Sdim Printer.Indent(); 1215341825Sdim CompilandDumper Dumper(Printer); 1216341825Sdim while (auto Compiland = Compilands->getNext()) 1217341825Sdim Dumper.start(*Compiland, true); 1218341825Sdim Printer.Unindent(); 1219341825Sdim } 1220319780Sdim } 1221319780Sdim 1222319780Sdim if (opts::pretty::Globals) { 1223319780Sdim Printer.NewLine(); 1224319780Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---"; 1225319780Sdim Printer.Indent(); 1226319780Sdim if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) { 1227341825Sdim if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) { 1228341825Sdim FunctionDumper Dumper(Printer); 1229341825Sdim if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { 1230341825Sdim while (auto Function = Functions->getNext()) { 1231341825Sdim Printer.NewLine(); 1232341825Sdim Dumper.start(*Function, FunctionDumper::PointerType::None); 1233341825Sdim } 1234341825Sdim } else { 1235341825Sdim std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs; 1236341825Sdim while (auto Func = Functions->getNext()) 1237341825Sdim Funcs.push_back(std::move(Func)); 1238344779Sdim llvm::sort(Funcs, opts::pretty::compareFunctionSymbols); 1239341825Sdim for (const auto &Func : Funcs) { 1240341825Sdim Printer.NewLine(); 1241341825Sdim Dumper.start(*Func, FunctionDumper::PointerType::None); 1242341825Sdim } 1243319780Sdim } 1244319780Sdim } 1245319780Sdim } 1246319780Sdim if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) { 1247341825Sdim if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) { 1248341825Sdim VariableDumper Dumper(Printer); 1249341825Sdim if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { 1250341825Sdim while (auto Var = Vars->getNext()) 1251341825Sdim Dumper.start(*Var); 1252341825Sdim } else { 1253341825Sdim std::vector<std::unique_ptr<PDBSymbolData>> Datas; 1254341825Sdim while (auto Var = Vars->getNext()) 1255341825Sdim Datas.push_back(std::move(Var)); 1256344779Sdim llvm::sort(Datas, opts::pretty::compareDataSymbols); 1257341825Sdim for (const auto &Var : Datas) 1258341825Sdim Dumper.start(*Var); 1259341825Sdim } 1260319780Sdim } 1261319780Sdim } 1262319780Sdim if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) { 1263341825Sdim if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) { 1264341825Sdim CompilandDumper Dumper(Printer); 1265341825Sdim while (auto Thunk = Thunks->getNext()) 1266341825Sdim Dumper.dump(*Thunk); 1267341825Sdim } 1268319780Sdim } 1269319780Sdim Printer.Unindent(); 1270319780Sdim } 1271319780Sdim if (opts::pretty::Externals) { 1272319780Sdim Printer.NewLine(); 1273319780Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---"; 1274319780Sdim Printer.Indent(); 1275319780Sdim ExternalSymbolDumper Dumper(Printer); 1276319780Sdim Dumper.start(*GlobalScope); 1277319780Sdim } 1278319780Sdim if (opts::pretty::Lines) { 1279319780Sdim Printer.NewLine(); 1280319780Sdim } 1281341825Sdim if (opts::pretty::InjectedSources) { 1282341825Sdim Printer.NewLine(); 1283341825Sdim WithColor(Printer, PDB_ColorItem::SectionHeader).get() 1284341825Sdim << "---INJECTED SOURCES---"; 1285341825Sdim AutoIndent Indent1(Printer); 1286353358Sdim dumpInjectedSources(Printer, *Session); 1287341825Sdim } 1288341825Sdim 1289344779Sdim Printer.NewLine(); 1290319780Sdim outs().flush(); 1291319780Sdim} 1292319780Sdim 1293319780Sdimstatic void mergePdbs() { 1294319780Sdim BumpPtrAllocator Allocator; 1295327952Sdim MergingTypeTableBuilder MergedTpi(Allocator); 1296327952Sdim MergingTypeTableBuilder MergedIpi(Allocator); 1297319780Sdim 1298319780Sdim // Create a Tpi and Ipi type table with all types from all input files. 1299319780Sdim for (const auto &Path : opts::merge::InputFilenames) { 1300319780Sdim std::unique_ptr<IPDBSession> Session; 1301319780Sdim auto &File = loadPDB(Path, Session); 1302319780Sdim SmallVector<TypeIndex, 128> TypeMap; 1303319780Sdim SmallVector<TypeIndex, 128> IdMap; 1304319780Sdim if (File.hasPDBTpiStream()) { 1305319780Sdim auto &Tpi = ExitOnErr(File.getPDBTpiStream()); 1306321238Sdim ExitOnErr( 1307321238Sdim codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray())); 1308319780Sdim } 1309319780Sdim if (File.hasPDBIpiStream()) { 1310319780Sdim auto &Ipi = ExitOnErr(File.getPDBIpiStream()); 1311319780Sdim ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap, 1312319780Sdim Ipi.typeArray())); 1313319780Sdim } 1314319780Sdim } 1315319780Sdim 1316319780Sdim // Then write the PDB. 1317319780Sdim PDBFileBuilder Builder(Allocator); 1318319780Sdim ExitOnErr(Builder.initialize(4096)); 1319319780Sdim // Add each of the reserved streams. We might not put any data in them, 1320319780Sdim // but at least they have to be present. 1321319780Sdim for (uint32_t I = 0; I < kSpecialStreamCount; ++I) 1322319780Sdim ExitOnErr(Builder.getMsfBuilder().addStream(0)); 1323319780Sdim 1324319780Sdim auto &DestTpi = Builder.getTpiBuilder(); 1325319780Sdim auto &DestIpi = Builder.getIpiBuilder(); 1326327952Sdim MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) { 1327327952Sdim DestTpi.addTypeRecord(Type.RecordData, None); 1328319780Sdim }); 1329327952Sdim MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) { 1330327952Sdim DestIpi.addTypeRecord(Type.RecordData, None); 1331319780Sdim }); 1332320041Sdim Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140); 1333319780Sdim 1334319780Sdim SmallString<64> OutFile(opts::merge::PdbOutputFile); 1335319780Sdim if (OutFile.empty()) { 1336319780Sdim OutFile = opts::merge::InputFilenames[0]; 1337319780Sdim llvm::sys::path::replace_extension(OutFile, "merged.pdb"); 1338319780Sdim } 1339344779Sdim 1340344779Sdim codeview::GUID IgnoredOutGuid; 1341344779Sdim ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid)); 1342319780Sdim} 1343319780Sdim 1344341825Sdimstatic void explain() { 1345341825Sdim std::unique_ptr<IPDBSession> Session; 1346341825Sdim InputFile IF = 1347341825Sdim ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true)); 1348341825Sdim 1349341825Sdim for (uint64_t Off : opts::explain::Offsets) { 1350360784Sdim auto O = std::make_unique<ExplainOutputStyle>(IF, Off); 1351341825Sdim 1352341825Sdim ExitOnErr(O->dump()); 1353341825Sdim } 1354341825Sdim} 1355341825Sdim 1356341825Sdimstatic void exportStream() { 1357341825Sdim std::unique_ptr<IPDBSession> Session; 1358341825Sdim PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session); 1359341825Sdim 1360341825Sdim std::unique_ptr<MappedBlockStream> SourceStream; 1361341825Sdim uint32_t Index = 0; 1362341825Sdim bool Success = false; 1363341825Sdim std::string OutFileName = opts::exportstream::OutputFile; 1364341825Sdim 1365341825Sdim if (!opts::exportstream::ForceName) { 1366341825Sdim // First try to parse it as an integer, if it fails fall back to treating it 1367341825Sdim // as a named stream. 1368341825Sdim if (to_integer(opts::exportstream::Stream, Index)) { 1369341825Sdim if (Index >= File.getNumStreams()) { 1370341825Sdim errs() << "Error: " << Index << " is not a valid stream index.\n"; 1371341825Sdim exit(1); 1372341825Sdim } 1373341825Sdim Success = true; 1374341825Sdim outs() << "Dumping contents of stream index " << Index << " to file " 1375341825Sdim << OutFileName << ".\n"; 1376341825Sdim } 1377341825Sdim } 1378341825Sdim 1379341825Sdim if (!Success) { 1380341825Sdim InfoStream &IS = cantFail(File.getPDBInfoStream()); 1381341825Sdim Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream)); 1382341825Sdim outs() << "Dumping contents of stream '" << opts::exportstream::Stream 1383341825Sdim << "' (index " << Index << ") to file " << OutFileName << ".\n"; 1384341825Sdim } 1385341825Sdim 1386353358Sdim SourceStream = File.createIndexedStream(Index); 1387341825Sdim auto OutFile = ExitOnErr( 1388341825Sdim FileOutputBuffer::create(OutFileName, SourceStream->getLength())); 1389341825Sdim FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little); 1390341825Sdim BinaryStreamWriter Writer(DestStream); 1391341825Sdim ExitOnErr(Writer.writeStreamRef(*SourceStream)); 1392341825Sdim ExitOnErr(DestStream.commit()); 1393341825Sdim} 1394341825Sdim 1395320397Sdimstatic bool parseRange(StringRef Str, 1396320397Sdim Optional<opts::bytes::NumberRange> &Parsed) { 1397320397Sdim if (Str.empty()) 1398320397Sdim return true; 1399320397Sdim 1400320397Sdim llvm::Regex R("^([^-]+)(-([^-]+))?$"); 1401320397Sdim llvm::SmallVector<llvm::StringRef, 2> Matches; 1402320397Sdim if (!R.match(Str, &Matches)) 1403320397Sdim return false; 1404320397Sdim 1405320397Sdim Parsed.emplace(); 1406320397Sdim if (!to_integer(Matches[1], Parsed->Min)) 1407320397Sdim return false; 1408320397Sdim 1409320397Sdim if (!Matches[3].empty()) { 1410320397Sdim Parsed->Max.emplace(); 1411320397Sdim if (!to_integer(Matches[3], *Parsed->Max)) 1412320397Sdim return false; 1413320397Sdim } 1414320397Sdim return true; 1415320397Sdim} 1416320397Sdim 1417320397Sdimstatic void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) { 1418320397Sdim // If this list contains "All" plus some other stuff, remove the other stuff 1419320397Sdim // and just keep "All" in the list. 1420320397Sdim if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All)) 1421320397Sdim return; 1422320397Sdim Chunks.reset(); 1423320397Sdim Chunks.push_back(opts::ModuleSubsection::All); 1424320397Sdim} 1425320397Sdim 1426341825Sdimint main(int Argc, const char **Argv) { 1427341825Sdim InitLLVM X(Argc, Argv); 1428319780Sdim ExitOnErr.setBanner("llvm-pdbutil: "); 1429319780Sdim 1430341825Sdim cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n"); 1431319780Sdim 1432320397Sdim if (opts::BytesSubcommand) { 1433320397Sdim if (!parseRange(opts::bytes::DumpBlockRangeOpt, 1434320397Sdim opts::bytes::DumpBlockRange)) { 1435320397Sdim errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt 1436319780Sdim << "' invalid format.\n"; 1437319780Sdim errs().flush(); 1438319780Sdim exit(1); 1439319780Sdim } 1440320397Sdim if (!parseRange(opts::bytes::DumpByteRangeOpt, 1441320397Sdim opts::bytes::DumpByteRange)) { 1442320397Sdim errs() << "Argument '" << opts::bytes::DumpByteRangeOpt 1443320397Sdim << "' invalid format.\n"; 1444320397Sdim errs().flush(); 1445320397Sdim exit(1); 1446319780Sdim } 1447319780Sdim } 1448319780Sdim 1449320397Sdim if (opts::DumpSubcommand) { 1450320397Sdim if (opts::dump::RawAll) { 1451327952Sdim opts::dump::DumpGlobals = true; 1452344779Sdim opts::dump::DumpFpo = true; 1453320397Sdim opts::dump::DumpInlineeLines = true; 1454320397Sdim opts::dump::DumpIds = true; 1455327952Sdim opts::dump::DumpIdExtras = true; 1456327952Sdim opts::dump::DumpLines = true; 1457327952Sdim opts::dump::DumpModules = true; 1458327952Sdim opts::dump::DumpModuleFiles = true; 1459320397Sdim opts::dump::DumpPublics = true; 1460320397Sdim opts::dump::DumpSectionContribs = true; 1461327952Sdim opts::dump::DumpSectionHeaders = true; 1462320397Sdim opts::dump::DumpSectionMap = true; 1463320397Sdim opts::dump::DumpStreams = true; 1464320397Sdim opts::dump::DumpStreamBlocks = true; 1465320397Sdim opts::dump::DumpStringTable = true; 1466341825Sdim opts::dump::DumpStringTableDetails = true; 1467320397Sdim opts::dump::DumpSummary = true; 1468320397Sdim opts::dump::DumpSymbols = true; 1469327952Sdim opts::dump::DumpSymbolStats = true; 1470320397Sdim opts::dump::DumpTypes = true; 1471320397Sdim opts::dump::DumpTypeExtras = true; 1472327952Sdim opts::dump::DumpUdtStats = true; 1473327952Sdim opts::dump::DumpXme = true; 1474327952Sdim opts::dump::DumpXmi = true; 1475319780Sdim } 1476319780Sdim } 1477319780Sdim if (opts::PdbToYamlSubcommand) { 1478319780Sdim if (opts::pdb2yaml::All) { 1479319780Sdim opts::pdb2yaml::StreamMetadata = true; 1480319780Sdim opts::pdb2yaml::StreamDirectory = true; 1481319780Sdim opts::pdb2yaml::PdbStream = true; 1482319780Sdim opts::pdb2yaml::StringTable = true; 1483319780Sdim opts::pdb2yaml::DbiStream = true; 1484319780Sdim opts::pdb2yaml::TpiStream = true; 1485319780Sdim opts::pdb2yaml::IpiStream = true; 1486344779Sdim opts::pdb2yaml::PublicsStream = true; 1487320041Sdim opts::pdb2yaml::DumpModules = true; 1488320041Sdim opts::pdb2yaml::DumpModuleFiles = true; 1489320041Sdim opts::pdb2yaml::DumpModuleSyms = true; 1490320041Sdim opts::pdb2yaml::DumpModuleSubsections.push_back( 1491320041Sdim opts::ModuleSubsection::All); 1492319780Sdim } 1493320397Sdim simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections); 1494320041Sdim 1495320041Sdim if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles) 1496320041Sdim opts::pdb2yaml::DumpModules = true; 1497320041Sdim 1498320041Sdim if (opts::pdb2yaml::DumpModules) 1499320041Sdim opts::pdb2yaml::DbiStream = true; 1500319780Sdim } 1501319780Sdim 1502319780Sdim llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); 1503319780Sdim 1504319780Sdim if (opts::PdbToYamlSubcommand) { 1505319780Sdim pdb2Yaml(opts::pdb2yaml::InputFilename.front()); 1506319780Sdim } else if (opts::YamlToPdbSubcommand) { 1507319780Sdim if (opts::yaml2pdb::YamlPdbOutputFile.empty()) { 1508319780Sdim SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue()); 1509319780Sdim sys::path::replace_extension(OutputFilename, ".pdb"); 1510319780Sdim opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str(); 1511319780Sdim } 1512319780Sdim yamlToPdb(opts::yaml2pdb::InputFilename); 1513344779Sdim } else if (opts::DiaDumpSubcommand) { 1514344779Sdim llvm::for_each(opts::diadump::InputFilenames, dumpDia); 1515319780Sdim } else if (opts::PrettySubcommand) { 1516319780Sdim if (opts::pretty::Lines) 1517319780Sdim opts::pretty::Compilands = true; 1518319780Sdim 1519319780Sdim if (opts::pretty::All) { 1520319780Sdim opts::pretty::Compilands = true; 1521319780Sdim opts::pretty::Symbols = true; 1522319780Sdim opts::pretty::Globals = true; 1523319780Sdim opts::pretty::Types = true; 1524319780Sdim opts::pretty::Externals = true; 1525319780Sdim opts::pretty::Lines = true; 1526319780Sdim } 1527319780Sdim 1528319780Sdim if (opts::pretty::Types) { 1529319780Sdim opts::pretty::Classes = true; 1530319780Sdim opts::pretty::Typedefs = true; 1531319780Sdim opts::pretty::Enums = true; 1532344779Sdim opts::pretty::Pointers = true; 1533344779Sdim opts::pretty::Funcsigs = true; 1534319780Sdim } 1535319780Sdim 1536319780Sdim // When adding filters for excluded compilands and types, we need to 1537319780Sdim // remember that these are regexes. So special characters such as * and \ 1538319780Sdim // need to be escaped in the regex. In the case of a literal \, this means 1539319780Sdim // it needs to be escaped again in the C++. So matching a single \ in the 1540319780Sdim // input requires 4 \es in the C++. 1541319780Sdim if (opts::pretty::ExcludeCompilerGenerated) { 1542319780Sdim opts::pretty::ExcludeTypes.push_back("__vc_attributes"); 1543319780Sdim opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*"); 1544319780Sdim } 1545319780Sdim if (opts::pretty::ExcludeSystemLibraries) { 1546319780Sdim opts::pretty::ExcludeCompilands.push_back( 1547319780Sdim "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld"); 1548319780Sdim opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt"); 1549319780Sdim opts::pretty::ExcludeCompilands.push_back( 1550319780Sdim "d:\\\\th.obj.x86fre\\\\minkernel"); 1551319780Sdim } 1552327952Sdim llvm::for_each(opts::pretty::InputFilenames, dumpPretty); 1553320397Sdim } else if (opts::DumpSubcommand) { 1554327952Sdim llvm::for_each(opts::dump::InputFilenames, dumpRaw); 1555320397Sdim } else if (opts::BytesSubcommand) { 1556327952Sdim llvm::for_each(opts::bytes::InputFilenames, dumpBytes); 1557319780Sdim } else if (opts::MergeSubcommand) { 1558319780Sdim if (opts::merge::InputFilenames.size() < 2) { 1559319780Sdim errs() << "merge subcommand requires at least 2 input files.\n"; 1560319780Sdim exit(1); 1561319780Sdim } 1562319780Sdim mergePdbs(); 1563341825Sdim } else if (opts::ExplainSubcommand) { 1564341825Sdim explain(); 1565341825Sdim } else if (opts::ExportSubcommand) { 1566341825Sdim exportStream(); 1567319780Sdim } 1568319780Sdim 1569319780Sdim outs().flush(); 1570319780Sdim return 0; 1571319780Sdim} 1572