Path: blob/main/contrib/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
35259 views
//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Dumps debug information present in PDB files.9//10//===----------------------------------------------------------------------===//1112#include "llvm-pdbutil.h"1314#include "BytesOutputStyle.h"15#include "DumpOutputStyle.h"16#include "ExplainOutputStyle.h"17#include "OutputStyle.h"18#include "PrettyClassDefinitionDumper.h"19#include "PrettyCompilandDumper.h"20#include "PrettyEnumDumper.h"21#include "PrettyExternalSymbolDumper.h"22#include "PrettyFunctionDumper.h"23#include "PrettyTypeDumper.h"24#include "PrettyTypedefDumper.h"25#include "PrettyVariableDumper.h"26#include "YAMLOutputStyle.h"2728#include "llvm/ADT/ArrayRef.h"29#include "llvm/ADT/STLExtras.h"30#include "llvm/ADT/StringExtras.h"31#include "llvm/BinaryFormat/Magic.h"32#include "llvm/Config/config.h"33#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"34#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"35#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"36#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"37#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"38#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"39#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"40#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"41#include "llvm/DebugInfo/MSF/MSFBuilder.h"42#include "llvm/DebugInfo/MSF/MappedBlockStream.h"43#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"44#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"45#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"46#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"47#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"48#include "llvm/DebugInfo/PDB/IPDBSession.h"49#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"50#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"51#include "llvm/DebugInfo/PDB/Native/InfoStream.h"52#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"53#include "llvm/DebugInfo/PDB/Native/InputFile.h"54#include "llvm/DebugInfo/PDB/Native/NativeSession.h"55#include "llvm/DebugInfo/PDB/Native/PDBFile.h"56#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"57#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"58#include "llvm/DebugInfo/PDB/Native/RawConstants.h"59#include "llvm/DebugInfo/PDB/Native/RawError.h"60#include "llvm/DebugInfo/PDB/Native/TpiStream.h"61#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"62#include "llvm/DebugInfo/PDB/PDB.h"63#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"64#include "llvm/DebugInfo/PDB/PDBSymbolData.h"65#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"66#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"67#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"68#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"69#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"70#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"71#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"72#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"73#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"74#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"75#include "llvm/Support/BinaryByteStream.h"76#include "llvm/Support/COM.h"77#include "llvm/Support/CommandLine.h"78#include "llvm/Support/ConvertUTF.h"79#include "llvm/Support/FileOutputBuffer.h"80#include "llvm/Support/FileSystem.h"81#include "llvm/Support/Format.h"82#include "llvm/Support/InitLLVM.h"83#include "llvm/Support/LineIterator.h"84#include "llvm/Support/MemoryBuffer.h"85#include "llvm/Support/Path.h"86#include "llvm/Support/PrettyStackTrace.h"87#include "llvm/Support/Process.h"88#include "llvm/Support/Regex.h"89#include "llvm/Support/ScopedPrinter.h"90#include "llvm/Support/Signals.h"91#include "llvm/Support/raw_ostream.h"9293using namespace llvm;94using namespace llvm::codeview;95using namespace llvm::msf;96using namespace llvm::pdb;9798namespace opts {99100cl::SubCommand DumpSubcommand("dump", "Dump MSF and CodeView debug info");101cl::SubCommand BytesSubcommand("bytes", "Dump raw bytes from the PDB file");102103cl::SubCommand DiaDumpSubcommand("diadump",104"Dump debug information using a DIA-like API");105106cl::SubCommand107PrettySubcommand("pretty",108"Dump semantic information about types and symbols");109110cl::SubCommand111YamlToPdbSubcommand("yaml2pdb",112"Generate a PDB file from a YAML description");113cl::SubCommand114PdbToYamlSubcommand("pdb2yaml",115"Generate a detailed YAML description of a PDB File");116117cl::SubCommand MergeSubcommand("merge",118"Merge multiple PDBs into a single PDB");119120cl::SubCommand ExplainSubcommand("explain",121"Explain the meaning of a file offset");122123cl::SubCommand ExportSubcommand("export",124"Write binary data from a stream to a file");125126cl::OptionCategory TypeCategory("Symbol Type Options");127cl::OptionCategory FilterCategory("Filtering and Sorting Options");128cl::OptionCategory OtherOptions("Other Options");129130cl::ValuesClass ChunkValues = cl::values(131clEnumValN(ModuleSubsection::CrossScopeExports, "cme",132"Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),133clEnumValN(ModuleSubsection::CrossScopeImports, "cmi",134"Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),135clEnumValN(ModuleSubsection::FileChecksums, "fc",136"File checksums (DEBUG_S_CHECKSUMS subsection)"),137clEnumValN(ModuleSubsection::InlineeLines, "ilines",138"Inlinee lines (DEBUG_S_INLINEELINES subsection)"),139clEnumValN(ModuleSubsection::Lines, "lines",140"Lines (DEBUG_S_LINES subsection)"),141clEnumValN(ModuleSubsection::StringTable, "strings",142"String Table (DEBUG_S_STRINGTABLE subsection) (not "143"typically present in PDB file)"),144clEnumValN(ModuleSubsection::FrameData, "frames",145"Frame Data (DEBUG_S_FRAMEDATA subsection)"),146clEnumValN(ModuleSubsection::Symbols, "symbols",147"Symbols (DEBUG_S_SYMBOLS subsection) (not typically "148"present in PDB file)"),149clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas",150"COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"),151clEnumValN(ModuleSubsection::Unknown, "unknown",152"Any subsection not covered by another option"),153clEnumValN(ModuleSubsection::All, "all", "All known subsections"));154155namespace diadump {156cl::list<std::string> InputFilenames(cl::Positional,157cl::desc("<input PDB files>"),158cl::OneOrMore, cl::sub(DiaDumpSubcommand));159160cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),161cl::sub(DiaDumpSubcommand));162163static cl::opt<bool>164ShowClassHierarchy("hierarchy", cl::desc("Show lexical and class parents"),165cl::sub(DiaDumpSubcommand));166static cl::opt<bool> NoSymIndexIds(167"no-ids",168cl::desc("Don't show any SymIndexId fields (overrides -hierarchy)"),169cl::sub(DiaDumpSubcommand));170171static cl::opt<bool>172Recurse("recurse",173cl::desc("When dumping a SymIndexId, dump the full details of the "174"corresponding record"),175cl::sub(DiaDumpSubcommand));176177static cl::opt<bool> Enums("enums", cl::desc("Dump enum types"),178cl::sub(DiaDumpSubcommand));179static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),180cl::sub(DiaDumpSubcommand));181static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),182cl::sub(DiaDumpSubcommand));183static cl::opt<bool> Compilands("compilands",184cl::desc("Dump compiland information"),185cl::sub(DiaDumpSubcommand));186static cl::opt<bool> Funcsigs("funcsigs",187cl::desc("Dump function signature information"),188cl::sub(DiaDumpSubcommand));189static cl::opt<bool> Arrays("arrays", cl::desc("Dump array types"),190cl::sub(DiaDumpSubcommand));191static cl::opt<bool> VTShapes("vtshapes", cl::desc("Dump virtual table shapes"),192cl::sub(DiaDumpSubcommand));193static cl::opt<bool> Typedefs("typedefs", cl::desc("Dump typedefs"),194cl::sub(DiaDumpSubcommand));195} // namespace diadump196197FilterOptions Filters;198199namespace pretty {200cl::list<std::string> InputFilenames(cl::Positional,201cl::desc("<input PDB files>"),202cl::OneOrMore, cl::sub(PrettySubcommand));203204cl::opt<bool> InjectedSources("injected-sources",205cl::desc("Display injected sources"),206cl::cat(OtherOptions), cl::sub(PrettySubcommand));207cl::opt<bool> ShowInjectedSourceContent(208"injected-source-content",209cl::desc("When displaying an injected source, display the file content"),210cl::cat(OtherOptions), cl::sub(PrettySubcommand));211212cl::list<std::string> WithName(213"with-name",214cl::desc("Display any symbol or type with the specified exact name"),215cl::cat(TypeCategory), cl::sub(PrettySubcommand));216217cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),218cl::cat(TypeCategory), cl::sub(PrettySubcommand));219cl::opt<bool> Symbols("module-syms",220cl::desc("Display symbols for each compiland"),221cl::cat(TypeCategory), cl::sub(PrettySubcommand));222cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),223cl::cat(TypeCategory), cl::sub(PrettySubcommand));224cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),225cl::cat(TypeCategory), cl::sub(PrettySubcommand));226cl::list<SymLevel> SymTypes(227"sym-types", cl::desc("Type of symbols to dump (default all)"),228cl::cat(TypeCategory), cl::sub(PrettySubcommand),229cl::values(230clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),231clEnumValN(SymLevel::Data, "data", "Display data symbols"),232clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),233clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));234235cl::opt<bool>236Types("types",237cl::desc("Display all types (implies -classes, -enums, -typedefs)"),238cl::cat(TypeCategory), cl::sub(PrettySubcommand));239cl::opt<bool> Classes("classes", cl::desc("Display class types"),240cl::cat(TypeCategory), cl::sub(PrettySubcommand));241cl::opt<bool> Enums("enums", cl::desc("Display enum types"),242cl::cat(TypeCategory), cl::sub(PrettySubcommand));243cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),244cl::cat(TypeCategory), cl::sub(PrettySubcommand));245cl::opt<bool> Funcsigs("funcsigs", cl::desc("Display function signatures"),246cl::cat(TypeCategory), cl::sub(PrettySubcommand));247cl::opt<bool> Pointers("pointers", cl::desc("Display pointer types"),248cl::cat(TypeCategory), cl::sub(PrettySubcommand));249cl::opt<bool> Arrays("arrays", cl::desc("Display arrays"),250cl::cat(TypeCategory), cl::sub(PrettySubcommand));251cl::opt<bool> VTShapes("vtshapes", cl::desc("Display vftable shapes"),252cl::cat(TypeCategory), cl::sub(PrettySubcommand));253254cl::opt<SymbolSortMode> SymbolOrder(255"symbol-order", cl::desc("symbol sort order"),256cl::init(SymbolSortMode::None),257cl::values(clEnumValN(SymbolSortMode::None, "none",258"Undefined / no particular sort order"),259clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),260clEnumValN(SymbolSortMode::Size, "size",261"Sort symbols by size")),262cl::cat(TypeCategory), cl::sub(PrettySubcommand));263264cl::opt<ClassSortMode> ClassOrder(265"class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),266cl::values(267clEnumValN(ClassSortMode::None, "none",268"Undefined / no particular sort order"),269clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),270clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),271clEnumValN(ClassSortMode::Padding, "padding",272"Sort classes by amount of padding"),273clEnumValN(ClassSortMode::PaddingPct, "padding-pct",274"Sort classes by percentage of space consumed by padding"),275clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",276"Sort classes by amount of immediate padding"),277clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",278"Sort classes by percentage of space consumed by immediate "279"padding")),280cl::cat(TypeCategory), cl::sub(PrettySubcommand));281282cl::opt<ClassDefinitionFormat> ClassFormat(283"class-definitions", cl::desc("Class definition format"),284cl::init(ClassDefinitionFormat::All),285cl::values(286clEnumValN(ClassDefinitionFormat::All, "all",287"Display all class members including data, constants, "288"typedefs, functions, etc"),289clEnumValN(ClassDefinitionFormat::Layout, "layout",290"Only display members that contribute to class size."),291clEnumValN(ClassDefinitionFormat::None, "none",292"Don't display class definitions")),293cl::cat(TypeCategory), cl::sub(PrettySubcommand));294cl::opt<uint32_t> ClassRecursionDepth(295"class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),296cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));297298cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),299cl::sub(PrettySubcommand));300cl::opt<bool>301All("all", cl::desc("Implies all other options in 'Symbol Types' category"),302cl::cat(TypeCategory), cl::sub(PrettySubcommand));303304cl::opt<uint64_t> LoadAddress(305"load-address",306cl::desc("Assume the module is loaded at the specified address"),307cl::cat(OtherOptions), cl::sub(PrettySubcommand));308cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),309cl::cat(OtherOptions), cl::sub(PrettySubcommand));310cl::opt<cl::boolOrDefault>311ColorOutput("color-output",312cl::desc("Override use of color (default = isatty)"),313cl::cat(OtherOptions), cl::sub(PrettySubcommand));314cl::list<std::string>315ExcludeTypes("exclude-types",316cl::desc("Exclude types by regular expression"),317cl::cat(FilterCategory), cl::sub(PrettySubcommand));318cl::list<std::string>319ExcludeSymbols("exclude-symbols",320cl::desc("Exclude symbols by regular expression"),321cl::cat(FilterCategory), cl::sub(PrettySubcommand));322cl::list<std::string>323ExcludeCompilands("exclude-compilands",324cl::desc("Exclude compilands by regular expression"),325cl::cat(FilterCategory), cl::sub(PrettySubcommand));326327cl::list<std::string> IncludeTypes(328"include-types",329cl::desc("Include only types which match a regular expression"),330cl::cat(FilterCategory), cl::sub(PrettySubcommand));331cl::list<std::string> IncludeSymbols(332"include-symbols",333cl::desc("Include only symbols which match a regular expression"),334cl::cat(FilterCategory), cl::sub(PrettySubcommand));335cl::list<std::string> IncludeCompilands(336"include-compilands",337cl::desc("Include only compilands those which match a regular expression"),338cl::cat(FilterCategory), cl::sub(PrettySubcommand));339cl::opt<uint32_t> SizeThreshold(340"min-type-size", cl::desc("Displays only those types which are greater "341"than or equal to the specified size."),342cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));343cl::opt<uint32_t> PaddingThreshold(344"min-class-padding", cl::desc("Displays only those classes which have at "345"least the specified amount of padding."),346cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));347cl::opt<uint32_t> ImmediatePaddingThreshold(348"min-class-padding-imm",349cl::desc("Displays only those classes which have at least the specified "350"amount of immediate padding, ignoring padding internal to bases "351"and aggregates."),352cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));353354cl::opt<bool> ExcludeCompilerGenerated(355"no-compiler-generated",356cl::desc("Don't show compiler generated types and symbols"),357cl::cat(FilterCategory), cl::sub(PrettySubcommand));358cl::opt<bool>359ExcludeSystemLibraries("no-system-libs",360cl::desc("Don't show symbols from system libraries"),361cl::cat(FilterCategory), cl::sub(PrettySubcommand));362363cl::opt<bool> NoEnumDefs("no-enum-definitions",364cl::desc("Don't display full enum definitions"),365cl::cat(FilterCategory), cl::sub(PrettySubcommand));366}367368cl::OptionCategory FileOptions("Module & File Options");369370namespace bytes {371cl::OptionCategory MsfBytes("MSF File Options");372cl::OptionCategory DbiBytes("Dbi Stream Options");373cl::OptionCategory PdbBytes("PDB Stream Options");374cl::OptionCategory Types("Type Options");375cl::OptionCategory ModuleCategory("Module Options");376377std::optional<NumberRange> DumpBlockRange;378std::optional<NumberRange> DumpByteRange;379380cl::opt<std::string> DumpBlockRangeOpt(381"block-range", cl::value_desc("start[-end]"),382cl::desc("Dump binary data from specified range of blocks."),383cl::sub(BytesSubcommand), cl::cat(MsfBytes));384385cl::opt<std::string>386DumpByteRangeOpt("byte-range", cl::value_desc("start[-end]"),387cl::desc("Dump binary data from specified range of bytes"),388cl::sub(BytesSubcommand), cl::cat(MsfBytes));389390cl::list<std::string>391DumpStreamData("stream-data", cl::CommaSeparated,392cl::desc("Dump binary data from specified streams. Format "393"is SN[:Start][@Size]"),394cl::sub(BytesSubcommand), cl::cat(MsfBytes));395396cl::opt<bool> NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),397cl::sub(BytesSubcommand), cl::cat(PdbBytes));398cl::opt<bool> Fpm("fpm", cl::desc("Dump free page map"),399cl::sub(BytesSubcommand), cl::cat(MsfBytes));400401cl::opt<bool> SectionContributions("sc", cl::desc("Dump section contributions"),402cl::sub(BytesSubcommand), cl::cat(DbiBytes));403cl::opt<bool> SectionMap("sm", cl::desc("Dump section map"),404cl::sub(BytesSubcommand), cl::cat(DbiBytes));405cl::opt<bool> ModuleInfos("modi", cl::desc("Dump module info"),406cl::sub(BytesSubcommand), cl::cat(DbiBytes));407cl::opt<bool> FileInfo("files", cl::desc("Dump source file info"),408cl::sub(BytesSubcommand), cl::cat(DbiBytes));409cl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),410cl::sub(BytesSubcommand), cl::cat(DbiBytes));411cl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),412cl::sub(BytesSubcommand), cl::cat(DbiBytes));413414cl::list<uint32_t> TypeIndex(415"type", cl::desc("Dump the type record with the given type index"),416cl::CommaSeparated, cl::sub(BytesSubcommand), cl::cat(TypeCategory));417cl::list<uint32_t>418IdIndex("id", cl::desc("Dump the id record with the given type index"),419cl::CommaSeparated, cl::sub(BytesSubcommand),420cl::cat(TypeCategory));421422cl::opt<uint32_t> ModuleIndex(423"mod",424cl::desc(425"Limit options in the Modules category to the specified module index"),426cl::Optional, cl::sub(BytesSubcommand), cl::cat(ModuleCategory));427cl::opt<bool> ModuleSyms("syms", cl::desc("Dump symbol record substream"),428cl::sub(BytesSubcommand), cl::cat(ModuleCategory));429cl::opt<bool> ModuleC11("c11-chunks", cl::Hidden,430cl::desc("Dump C11 CodeView debug chunks"),431cl::sub(BytesSubcommand), cl::cat(ModuleCategory));432cl::opt<bool> ModuleC13("chunks",433cl::desc("Dump C13 CodeView debug chunk subsection"),434cl::sub(BytesSubcommand), cl::cat(ModuleCategory));435cl::opt<bool> SplitChunks(436"split-chunks",437cl::desc(438"When dumping debug chunks, show a different section for each chunk"),439cl::sub(BytesSubcommand), cl::cat(ModuleCategory));440cl::list<std::string> InputFilenames(cl::Positional,441cl::desc("<input PDB files>"),442cl::OneOrMore, cl::sub(BytesSubcommand));443444} // namespace bytes445446namespace dump {447448cl::OptionCategory MsfOptions("MSF Container Options");449cl::OptionCategory TypeOptions("Type Record Options");450cl::OptionCategory SymbolOptions("Symbol Options");451cl::OptionCategory MiscOptions("Miscellaneous Options");452453// MSF OPTIONS454cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),455cl::cat(MsfOptions), cl::sub(DumpSubcommand));456cl::opt<bool> DumpStreams("streams",457cl::desc("dump summary of the PDB streams"),458cl::cat(MsfOptions), cl::sub(DumpSubcommand));459cl::opt<bool> DumpStreamBlocks(460"stream-blocks",461cl::desc("Add block information to the output of -streams"),462cl::cat(MsfOptions), cl::sub(DumpSubcommand));463cl::opt<bool> DumpSymbolStats(464"sym-stats",465cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),466cl::cat(MsfOptions), cl::sub(DumpSubcommand));467cl::opt<bool> DumpTypeStats(468"type-stats",469cl::desc("Dump a detailed breakdown of type usage/size"),470cl::cat(MsfOptions), cl::sub(DumpSubcommand));471cl::opt<bool> DumpIDStats(472"id-stats",473cl::desc("Dump a detailed breakdown of IPI types usage/size"),474cl::cat(MsfOptions), cl::sub(DumpSubcommand));475cl::opt<bool> DumpUdtStats(476"udt-stats",477cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),478cl::cat(MsfOptions), cl::sub(DumpSubcommand));479480// TYPE OPTIONS481cl::opt<bool> DumpTypes("types",482cl::desc("dump CodeView type records from TPI stream"),483cl::cat(TypeOptions), cl::sub(DumpSubcommand));484cl::opt<bool> DumpTypeData(485"type-data",486cl::desc("dump CodeView type record raw bytes from TPI stream"),487cl::cat(TypeOptions), cl::sub(DumpSubcommand));488cl::opt<bool>489DumpTypeRefStats("type-ref-stats",490cl::desc("dump statistics on the number and size of types "491"transitively referenced by symbol records"),492cl::cat(TypeOptions), cl::sub(DumpSubcommand));493494cl::opt<bool> DumpTypeExtras("type-extras",495cl::desc("dump type hashes and index offsets"),496cl::cat(TypeOptions), cl::sub(DumpSubcommand));497498cl::opt<bool> DontResolveForwardRefs(499"dont-resolve-forward-refs",500cl::desc("When dumping type records for classes, unions, enums, and "501"structs, don't try to resolve forward references"),502cl::cat(TypeOptions), cl::sub(DumpSubcommand));503504cl::list<uint32_t> DumpTypeIndex(505"type-index", cl::CommaSeparated,506cl::desc("only dump types with the specified hexadecimal type index"),507cl::cat(TypeOptions), cl::sub(DumpSubcommand));508509cl::opt<bool> DumpIds("ids",510cl::desc("dump CodeView type records from IPI stream"),511cl::cat(TypeOptions), cl::sub(DumpSubcommand));512cl::opt<bool>513DumpIdData("id-data",514cl::desc("dump CodeView type record raw bytes from IPI stream"),515cl::cat(TypeOptions), cl::sub(DumpSubcommand));516517cl::opt<bool> DumpIdExtras("id-extras",518cl::desc("dump id hashes and index offsets"),519cl::cat(TypeOptions), cl::sub(DumpSubcommand));520cl::list<uint32_t> DumpIdIndex(521"id-index", cl::CommaSeparated,522cl::desc("only dump ids with the specified hexadecimal type index"),523cl::cat(TypeOptions), cl::sub(DumpSubcommand));524525cl::opt<bool> DumpTypeDependents(526"dependents",527cl::desc("In conjunection with -type-index and -id-index, dumps the entire "528"dependency graph for the specified index instead of "529"just the single record with the specified index"),530cl::cat(TypeOptions), cl::sub(DumpSubcommand));531532// SYMBOL OPTIONS533cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),534cl::cat(SymbolOptions), cl::sub(DumpSubcommand));535cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),536cl::cat(SymbolOptions), cl::sub(DumpSubcommand));537cl::list<std::string> DumpGlobalNames(538"global-name",539cl::desc(540"With -globals, only dump globals whose name matches the given value"),541cl::cat(SymbolOptions), cl::sub(DumpSubcommand));542cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),543cl::cat(SymbolOptions), cl::sub(DumpSubcommand));544cl::opt<bool> DumpPublicExtras("public-extras",545cl::desc("dump Publics hashes and address maps"),546cl::cat(SymbolOptions), cl::sub(DumpSubcommand));547cl::opt<bool>548DumpGSIRecords("gsi-records",549cl::desc("dump public / global common record stream"),550cl::cat(SymbolOptions), cl::sub(DumpSubcommand));551cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),552cl::cat(SymbolOptions), cl::sub(DumpSubcommand));553554cl::opt<bool>555DumpSymRecordBytes("sym-data",556cl::desc("dump CodeView symbol record raw bytes"),557cl::cat(SymbolOptions), cl::sub(DumpSubcommand));558559cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),560cl::cat(SymbolOptions), cl::sub(DumpSubcommand));561562cl::opt<uint32_t> DumpSymbolOffset(563"symbol-offset", cl::Optional,564cl::desc("only dump symbol record with the specified symbol offset"),565cl::cat(SymbolOptions), cl::sub(DumpSubcommand));566cl::opt<bool> DumpParents("show-parents",567cl::desc("dump the symbols record's all parents."),568cl::cat(SymbolOptions), cl::sub(DumpSubcommand));569cl::opt<uint32_t>570DumpParentDepth("parent-recurse-depth", cl::Optional, cl::init(-1U),571cl::desc("only recurse to a depth of N when displaying "572"parents of a symbol record."),573cl::cat(SymbolOptions), cl::sub(DumpSubcommand));574cl::opt<bool> DumpChildren("show-children",575cl::desc("dump the symbols record's all children."),576cl::cat(SymbolOptions), cl::sub(DumpSubcommand));577cl::opt<uint32_t>578DumpChildrenDepth("children-recurse-depth", cl::Optional, cl::init(-1U),579cl::desc("only recurse to a depth of N when displaying "580"children of a symbol record."),581cl::cat(SymbolOptions), cl::sub(DumpSubcommand));582583// MODULE & FILE OPTIONS584cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),585cl::cat(FileOptions), cl::sub(DumpSubcommand));586cl::opt<bool> DumpModuleFiles(587"files",588cl::desc("Dump the source files that contribute to each module's."),589cl::cat(FileOptions), cl::sub(DumpSubcommand));590cl::opt<bool> DumpLines(591"l",592cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),593cl::cat(FileOptions), cl::sub(DumpSubcommand));594cl::opt<bool> DumpInlineeLines(595"il",596cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),597cl::cat(FileOptions), cl::sub(DumpSubcommand));598cl::opt<bool> DumpXmi(599"xmi",600cl::desc(601"dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),602cl::cat(FileOptions), cl::sub(DumpSubcommand));603cl::opt<bool> DumpXme(604"xme",605cl::desc(606"dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),607cl::cat(FileOptions), cl::sub(DumpSubcommand));608cl::opt<uint32_t> DumpModi("modi", cl::Optional,609cl::desc("For all options that iterate over "610"modules, limit to the specified module"),611cl::cat(FileOptions), cl::sub(DumpSubcommand));612cl::opt<bool> JustMyCode("jmc", cl::Optional,613cl::desc("For all options that iterate over modules, "614"ignore modules from system libraries"),615cl::cat(FileOptions), cl::sub(DumpSubcommand));616617// MISCELLANEOUS OPTIONS618cl::opt<bool> DumpNamedStreams("named-streams",619cl::desc("dump PDB named stream table"),620cl::cat(MiscOptions), cl::sub(DumpSubcommand));621622cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),623cl::cat(MiscOptions), cl::sub(DumpSubcommand));624cl::opt<bool> DumpStringTableDetails("string-table-details",625cl::desc("dump PDB String Table Details"),626cl::cat(MiscOptions),627cl::sub(DumpSubcommand));628629cl::opt<bool> DumpSectionContribs("section-contribs",630cl::desc("dump section contributions"),631cl::cat(MiscOptions),632cl::sub(DumpSubcommand));633cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),634cl::cat(MiscOptions), cl::sub(DumpSubcommand));635cl::opt<bool> DumpSectionHeaders("section-headers",636cl::desc("Dump image section headers"),637cl::cat(MiscOptions), cl::sub(DumpSubcommand));638639cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),640cl::cat(MiscOptions), cl::sub(DumpSubcommand));641642cl::list<std::string> InputFilenames(cl::Positional,643cl::desc("<input PDB files>"),644cl::OneOrMore, cl::sub(DumpSubcommand));645}646647namespace yaml2pdb {648cl::opt<std::string>649YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),650cl::sub(YamlToPdbSubcommand));651652cl::opt<std::string> InputFilename(cl::Positional,653cl::desc("<input YAML file>"), cl::Required,654cl::sub(YamlToPdbSubcommand));655}656657namespace pdb2yaml {658cl::opt<bool> All("all",659cl::desc("Dump everything we know how to dump."),660cl::sub(PdbToYamlSubcommand), cl::init(false));661cl::opt<bool> NoFileHeaders("no-file-headers",662cl::desc("Do not dump MSF file headers"),663cl::sub(PdbToYamlSubcommand), cl::init(false));664cl::opt<bool> Minimal("minimal",665cl::desc("Don't write fields with default values"),666cl::sub(PdbToYamlSubcommand), cl::init(false));667668cl::opt<bool> StreamMetadata(669"stream-metadata",670cl::desc("Dump the number of streams and each stream's size"),671cl::sub(PdbToYamlSubcommand), cl::init(false));672cl::opt<bool> StreamDirectory(673"stream-directory",674cl::desc("Dump each stream's block map (implies -stream-metadata)"),675cl::sub(PdbToYamlSubcommand), cl::init(false));676cl::opt<bool> PdbStream("pdb-stream",677cl::desc("Dump the PDB Stream (Stream 1)"),678cl::sub(PdbToYamlSubcommand), cl::init(false));679680cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),681cl::sub(PdbToYamlSubcommand), cl::init(false));682683cl::opt<bool> DbiStream("dbi-stream",684cl::desc("Dump the DBI Stream Headers (Stream 2)"),685cl::sub(PdbToYamlSubcommand), cl::init(false));686687cl::opt<bool> TpiStream("tpi-stream",688cl::desc("Dump the TPI Stream (Stream 3)"),689cl::sub(PdbToYamlSubcommand), cl::init(false));690691cl::opt<bool> IpiStream("ipi-stream",692cl::desc("Dump the IPI Stream (Stream 5)"),693cl::sub(PdbToYamlSubcommand), cl::init(false));694695cl::opt<bool> PublicsStream("publics-stream",696cl::desc("Dump the Publics Stream"),697cl::sub(PdbToYamlSubcommand), cl::init(false));698699// MODULE & FILE OPTIONS700cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),701cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));702cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),703cl::cat(FileOptions),704cl::sub(PdbToYamlSubcommand));705cl::list<ModuleSubsection> DumpModuleSubsections(706"subsections", cl::CommaSeparated,707cl::desc("dump subsections from each module's debug stream"), ChunkValues,708cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));709cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),710cl::cat(FileOptions),711cl::sub(PdbToYamlSubcommand));712713cl::list<std::string> InputFilename(cl::Positional,714cl::desc("<input PDB file>"), cl::Required,715cl::sub(PdbToYamlSubcommand));716} // namespace pdb2yaml717718namespace merge {719cl::list<std::string> InputFilenames(cl::Positional,720cl::desc("<input PDB files>"),721cl::OneOrMore, cl::sub(MergeSubcommand));722cl::opt<std::string>723PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),724cl::sub(MergeSubcommand));725}726727namespace explain {728cl::list<std::string> InputFilename(cl::Positional,729cl::desc("<input PDB file>"), cl::Required,730cl::sub(ExplainSubcommand));731732cl::list<uint64_t> Offsets("offset", cl::desc("The file offset to explain"),733cl::sub(ExplainSubcommand), cl::OneOrMore);734735cl::opt<InputFileType> InputType(736"input-type", cl::desc("Specify how to interpret the input file"),737cl::init(InputFileType::PDBFile), cl::Optional, cl::sub(ExplainSubcommand),738cl::values(clEnumValN(InputFileType::PDBFile, "pdb-file",739"Treat input as a PDB file (default)"),740clEnumValN(InputFileType::PDBStream, "pdb-stream",741"Treat input as raw contents of PDB stream"),742clEnumValN(InputFileType::DBIStream, "dbi-stream",743"Treat input as raw contents of DBI stream"),744clEnumValN(InputFileType::Names, "names-stream",745"Treat input as raw contents of /names named stream"),746clEnumValN(InputFileType::ModuleStream, "mod-stream",747"Treat input as raw contents of a module stream")));748} // namespace explain749750namespace exportstream {751cl::list<std::string> InputFilename(cl::Positional,752cl::desc("<input PDB file>"), cl::Required,753cl::sub(ExportSubcommand));754cl::opt<std::string> OutputFile("out",755cl::desc("The file to write the stream to"),756cl::Required, cl::sub(ExportSubcommand));757cl::opt<std::string>758Stream("stream", cl::Required,759cl::desc("The index or name of the stream whose contents to export"),760cl::sub(ExportSubcommand));761cl::opt<bool> ForceName("name",762cl::desc("Force the interpretation of -stream as a "763"string, even if it is a valid integer"),764cl::sub(ExportSubcommand), cl::Optional,765cl::init(false));766} // namespace exportstream767}768769static ExitOnError ExitOnErr;770771static void yamlToPdb(StringRef Path) {772BumpPtrAllocator Allocator;773ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =774MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/false,775/*RequiresNullTerminator=*/false);776777if (ErrorOrBuffer.getError()) {778ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError())));779}780781std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();782783llvm::yaml::Input In(Buffer->getBuffer());784pdb::yaml::PdbObject YamlObj(Allocator);785In >> YamlObj;786787PDBFileBuilder Builder(Allocator);788789uint32_t BlockSize = 4096;790if (YamlObj.Headers)791BlockSize = YamlObj.Headers->SuperBlock.BlockSize;792ExitOnErr(Builder.initialize(BlockSize));793// Add each of the reserved streams. We ignore stream metadata in the794// yaml, because we will reconstruct our own view of the streams. For795// example, the YAML may say that there were 20 streams in the original796// PDB, but maybe we only dump a subset of those 20 streams, so we will797// have fewer, and the ones we do have may end up with different indices798// than the ones in the original PDB. So we just start with a clean slate.799for (uint32_t I = 0; I < kSpecialStreamCount; ++I)800ExitOnErr(Builder.getMsfBuilder().addStream(0));801802StringsAndChecksums Strings;803Strings.setStrings(std::make_shared<DebugStringTableSubsection>());804805if (YamlObj.StringTable) {806for (auto S : *YamlObj.StringTable)807Strings.strings()->insert(S);808}809810pdb::yaml::PdbInfoStream DefaultInfoStream;811pdb::yaml::PdbDbiStream DefaultDbiStream;812pdb::yaml::PdbTpiStream DefaultTpiStream;813pdb::yaml::PdbTpiStream DefaultIpiStream;814815const auto &Info = YamlObj.PdbStream.value_or(DefaultInfoStream);816817auto &InfoBuilder = Builder.getInfoBuilder();818InfoBuilder.setAge(Info.Age);819InfoBuilder.setGuid(Info.Guid);820InfoBuilder.setSignature(Info.Signature);821InfoBuilder.setVersion(Info.Version);822for (auto F : Info.Features)823InfoBuilder.addFeature(F);824825const auto &Dbi = YamlObj.DbiStream.value_or(DefaultDbiStream);826auto &DbiBuilder = Builder.getDbiBuilder();827DbiBuilder.setAge(Dbi.Age);828DbiBuilder.setBuildNumber(Dbi.BuildNumber);829DbiBuilder.setFlags(Dbi.Flags);830DbiBuilder.setMachineType(Dbi.MachineType);831DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);832DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);833DbiBuilder.setVersionHeader(Dbi.VerHeader);834for (const auto &MI : Dbi.ModInfos) {835auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));836ModiBuilder.setObjFileName(MI.Obj);837838for (auto S : MI.SourceFiles)839ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));840if (MI.Modi) {841const auto &ModiStream = *MI.Modi;842for (const auto &Symbol : ModiStream.Symbols) {843ModiBuilder.addSymbol(844Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));845}846}847848// Each module has its own checksum subsection, so scan for it every time.849Strings.setChecksums(nullptr);850CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);851852auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(853Allocator, MI.Subsections, Strings));854for (auto &SS : CodeViewSubsections) {855ModiBuilder.addDebugSubsection(SS);856}857}858859auto &TpiBuilder = Builder.getTpiBuilder();860const auto &Tpi = YamlObj.TpiStream.value_or(DefaultTpiStream);861TpiBuilder.setVersionHeader(Tpi.Version);862AppendingTypeTableBuilder TS(Allocator);863for (const auto &R : Tpi.Records) {864CVType Type = R.toCodeViewRecord(TS);865TpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);866}867868const auto &Ipi = YamlObj.IpiStream.value_or(DefaultIpiStream);869auto &IpiBuilder = Builder.getIpiBuilder();870IpiBuilder.setVersionHeader(Ipi.Version);871for (const auto &R : Ipi.Records) {872CVType Type = R.toCodeViewRecord(TS);873IpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);874}875876Builder.getStringTableBuilder().setStrings(*Strings.strings());877878codeview::GUID IgnoredOutGuid;879ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));880}881882static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {883ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));884885NativeSession *NS = static_cast<NativeSession *>(Session.get());886return NS->getPDBFile();887}888889static void pdb2Yaml(StringRef Path) {890std::unique_ptr<IPDBSession> Session;891auto &File = loadPDB(Path, Session);892893auto O = std::make_unique<YAMLOutputStyle>(File);894895ExitOnErr(O->dump());896}897898static void dumpRaw(StringRef Path) {899InputFile IF = ExitOnErr(InputFile::open(Path));900901auto O = std::make_unique<DumpOutputStyle>(IF);902ExitOnErr(O->dump());903}904905static void dumpBytes(StringRef Path) {906std::unique_ptr<IPDBSession> Session;907auto &File = loadPDB(Path, Session);908909auto O = std::make_unique<BytesOutputStyle>(File);910911ExitOnErr(O->dump());912}913914bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {915if (SymTypes.empty())916return true;917if (llvm::is_contained(SymTypes, Search))918return true;919if (llvm::is_contained(SymTypes, SymLevel::All))920return true;921return false;922}923924uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {925auto SymbolType = Symbol.getType();926const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();927928return RawType.getLength();929}930931bool opts::pretty::compareFunctionSymbols(932const std::unique_ptr<PDBSymbolFunc> &F1,933const std::unique_ptr<PDBSymbolFunc> &F2) {934assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);935936if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)937return F1->getName() < F2->getName();938939// Note that we intentionally sort in descending order on length, since940// long functions are more interesting than short functions.941return F1->getLength() > F2->getLength();942}943944bool opts::pretty::compareDataSymbols(945const std::unique_ptr<PDBSymbolData> &F1,946const std::unique_ptr<PDBSymbolData> &F2) {947assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);948949if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)950return F1->getName() < F2->getName();951952// Note that we intentionally sort in descending order on length, since953// large types are more interesting than short ones.954return getTypeLength(*F1) > getTypeLength(*F2);955}956957static std::string stringOr(std::string Str, std::string IfEmpty) {958return (Str.empty()) ? IfEmpty : Str;959}960961static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) {962auto Sources = Session.getInjectedSources();963if (!Sources || !Sources->getChildCount()) {964Printer.printLine("There are no injected sources.");965return;966}967968while (auto IS = Sources->getNext()) {969Printer.NewLine();970std::string File = stringOr(IS->getFileName(), "<null>");971uint64_t Size = IS->getCodeByteSize();972std::string Obj = stringOr(IS->getObjectFileName(), "<null>");973std::string VFName = stringOr(IS->getVirtualFileName(), "<null>");974uint32_t CRC = IS->getCrc32();975976WithColor(Printer, PDB_ColorItem::Path).get() << File;977Printer << " (";978WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size;979Printer << " bytes): ";980WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj";981Printer << "=";982WithColor(Printer, PDB_ColorItem::Path).get() << Obj;983Printer << ", ";984WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname";985Printer << "=";986WithColor(Printer, PDB_ColorItem::Path).get() << VFName;987Printer << ", ";988WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc";989Printer << "=";990WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC;991Printer << ", ";992WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression";993Printer << "=";994dumpPDBSourceCompression(995WithColor(Printer, PDB_ColorItem::LiteralValue).get(),996IS->getCompression());997998if (!opts::pretty::ShowInjectedSourceContent)999continue;10001001// Set the indent level to 0 when printing file content.1002int Indent = Printer.getIndentLevel();1003Printer.Unindent(Indent);10041005if (IS->getCompression() == PDB_SourceCompression::None)1006Printer.printLine(IS->getCode());1007else1008Printer.formatBinary("Compressed data",1009arrayRefFromStringRef(IS->getCode()),1010/*StartOffset=*/0);10111012// Re-indent back to the original level.1013Printer.Indent(Indent);1014}1015}10161017template <typename OuterT, typename ChildT>1018void diaDumpChildren(PDBSymbol &Outer, PdbSymbolIdField Ids,1019PdbSymbolIdField Recurse) {1020OuterT *ConcreteOuter = dyn_cast<OuterT>(&Outer);1021if (!ConcreteOuter)1022return;10231024auto Children = ConcreteOuter->template findAllChildren<ChildT>();1025while (auto Child = Children->getNext()) {1026outs() << " {";1027Child->defaultDump(outs(), 4, Ids, Recurse);1028outs() << "\n }\n";1029}1030}10311032static void dumpDia(StringRef Path) {1033std::unique_ptr<IPDBSession> Session;10341035const auto ReaderType =1036opts::diadump::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;1037ExitOnErr(loadDataForPDB(ReaderType, Path, Session));10381039auto GlobalScope = Session->getGlobalScope();10401041std::vector<PDB_SymType> SymTypes;10421043if (opts::diadump::Compilands)1044SymTypes.push_back(PDB_SymType::Compiland);1045if (opts::diadump::Enums)1046SymTypes.push_back(PDB_SymType::Enum);1047if (opts::diadump::Pointers)1048SymTypes.push_back(PDB_SymType::PointerType);1049if (opts::diadump::UDTs)1050SymTypes.push_back(PDB_SymType::UDT);1051if (opts::diadump::Funcsigs)1052SymTypes.push_back(PDB_SymType::FunctionSig);1053if (opts::diadump::Arrays)1054SymTypes.push_back(PDB_SymType::ArrayType);1055if (opts::diadump::VTShapes)1056SymTypes.push_back(PDB_SymType::VTableShape);1057if (opts::diadump::Typedefs)1058SymTypes.push_back(PDB_SymType::Typedef);1059PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None1060: PdbSymbolIdField::All;10611062PdbSymbolIdField Recurse = PdbSymbolIdField::None;1063if (opts::diadump::Recurse)1064Recurse = PdbSymbolIdField::All;1065if (!opts::diadump::ShowClassHierarchy)1066Ids &= ~(PdbSymbolIdField::ClassParent | PdbSymbolIdField::LexicalParent);10671068for (PDB_SymType ST : SymTypes) {1069auto Children = GlobalScope->findAllChildren(ST);1070while (auto Child = Children->getNext()) {1071outs() << "{";1072Child->defaultDump(outs(), 2, Ids, Recurse);10731074diaDumpChildren<PDBSymbolTypeEnum, PDBSymbolData>(*Child, Ids, Recurse);1075outs() << "\n}\n";1076}1077}1078}10791080static void dumpPretty(StringRef Path) {1081std::unique_ptr<IPDBSession> Session;10821083const auto ReaderType =1084opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;1085ExitOnErr(loadDataForPDB(ReaderType, Path, Session));10861087if (opts::pretty::LoadAddress)1088Session->setLoadAddress(opts::pretty::LoadAddress);10891090auto &Stream = outs();1091const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET1092? Stream.has_colors()1093: opts::pretty::ColorOutput == cl::BOU_TRUE;1094LinePrinter Printer(2, UseColor, Stream, opts::Filters);10951096auto GlobalScope(Session->getGlobalScope());1097if (!GlobalScope)1098return;1099std::string FileName(GlobalScope->getSymbolsFileName());11001101WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";1102WithColor(Printer, PDB_ColorItem::Path).get() << FileName;1103Printer.Indent();1104uint64_t FileSize = 0;11051106Printer.NewLine();1107WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";1108if (!sys::fs::file_size(FileName, FileSize)) {1109Printer << ": " << FileSize << " bytes";1110} else {1111Printer << ": (Unable to obtain file size)";1112}11131114Printer.NewLine();1115WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";1116Printer << ": " << GlobalScope->getGuid();11171118Printer.NewLine();1119WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";1120Printer << ": " << GlobalScope->getAge();11211122Printer.NewLine();1123WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";1124Printer << ": ";1125if (GlobalScope->hasCTypes())1126outs() << "HasCTypes ";1127if (GlobalScope->hasPrivateSymbols())1128outs() << "HasPrivateSymbols ";1129Printer.Unindent();11301131if (!opts::pretty::WithName.empty()) {1132Printer.NewLine();1133WithColor(Printer, PDB_ColorItem::SectionHeader).get()1134<< "---SYMBOLS & TYPES BY NAME---";11351136for (StringRef Name : opts::pretty::WithName) {1137auto Symbols = GlobalScope->findChildren(1138PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);1139if (!Symbols || Symbols->getChildCount() == 0) {1140Printer.formatLine("[not found] - {0}", Name);1141continue;1142}1143Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),1144Name);11451146AutoIndent Indent(Printer);1147Printer.NewLine();11481149while (auto Symbol = Symbols->getNext()) {1150switch (Symbol->getSymTag()) {1151case PDB_SymType::Typedef: {1152TypedefDumper TD(Printer);1153std::unique_ptr<PDBSymbolTypeTypedef> T =1154llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));1155TD.start(*T);1156break;1157}1158case PDB_SymType::Enum: {1159EnumDumper ED(Printer);1160std::unique_ptr<PDBSymbolTypeEnum> E =1161llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));1162ED.start(*E);1163break;1164}1165case PDB_SymType::UDT: {1166ClassDefinitionDumper CD(Printer);1167std::unique_ptr<PDBSymbolTypeUDT> C =1168llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));1169CD.start(*C);1170break;1171}1172case PDB_SymType::BaseClass:1173case PDB_SymType::Friend: {1174TypeDumper TD(Printer);1175Symbol->dump(TD);1176break;1177}1178case PDB_SymType::Function: {1179FunctionDumper FD(Printer);1180std::unique_ptr<PDBSymbolFunc> F =1181llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));1182FD.start(*F, FunctionDumper::PointerType::None);1183break;1184}1185case PDB_SymType::Data: {1186VariableDumper VD(Printer);1187std::unique_ptr<PDBSymbolData> D =1188llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));1189VD.start(*D);1190break;1191}1192case PDB_SymType::PublicSymbol: {1193ExternalSymbolDumper ED(Printer);1194std::unique_ptr<PDBSymbolPublicSymbol> PS =1195llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));1196ED.dump(*PS);1197break;1198}1199default:1200llvm_unreachable("Unexpected symbol tag!");1201}1202}1203}1204llvm::outs().flush();1205}12061207if (opts::pretty::Compilands) {1208Printer.NewLine();1209WithColor(Printer, PDB_ColorItem::SectionHeader).get()1210<< "---COMPILANDS---";1211auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();12121213if (Compilands) {1214Printer.Indent();1215CompilandDumper Dumper(Printer);1216CompilandDumpFlags options = CompilandDumper::Flags::None;1217if (opts::pretty::Lines)1218options = options | CompilandDumper::Flags::Lines;1219while (auto Compiland = Compilands->getNext())1220Dumper.start(*Compiland, options);1221Printer.Unindent();1222}1223}12241225if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||1226opts::pretty::Funcsigs || opts::pretty::Pointers ||1227opts::pretty::Arrays || opts::pretty::VTShapes) {1228Printer.NewLine();1229WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";1230Printer.Indent();1231TypeDumper Dumper(Printer);1232Dumper.start(*GlobalScope);1233Printer.Unindent();1234}12351236if (opts::pretty::Symbols) {1237Printer.NewLine();1238WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";1239if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {1240Printer.Indent();1241CompilandDumper Dumper(Printer);1242while (auto Compiland = Compilands->getNext())1243Dumper.start(*Compiland, true);1244Printer.Unindent();1245}1246}12471248if (opts::pretty::Globals) {1249Printer.NewLine();1250WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";1251Printer.Indent();1252if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {1253if (auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>()) {1254FunctionDumper Dumper(Printer);1255if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {1256while (auto Function = Functions->getNext()) {1257Printer.NewLine();1258Dumper.start(*Function, FunctionDumper::PointerType::None);1259}1260} else {1261std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;1262while (auto Func = Functions->getNext())1263Funcs.push_back(std::move(Func));1264llvm::sort(Funcs, opts::pretty::compareFunctionSymbols);1265for (const auto &Func : Funcs) {1266Printer.NewLine();1267Dumper.start(*Func, FunctionDumper::PointerType::None);1268}1269}1270}1271}1272if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {1273if (auto Vars = GlobalScope->findAllChildren<PDBSymbolData>()) {1274VariableDumper Dumper(Printer);1275if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {1276while (auto Var = Vars->getNext())1277Dumper.start(*Var);1278} else {1279std::vector<std::unique_ptr<PDBSymbolData>> Datas;1280while (auto Var = Vars->getNext())1281Datas.push_back(std::move(Var));1282llvm::sort(Datas, opts::pretty::compareDataSymbols);1283for (const auto &Var : Datas)1284Dumper.start(*Var);1285}1286}1287}1288if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {1289if (auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>()) {1290CompilandDumper Dumper(Printer);1291while (auto Thunk = Thunks->getNext())1292Dumper.dump(*Thunk);1293}1294}1295Printer.Unindent();1296}1297if (opts::pretty::Externals) {1298Printer.NewLine();1299WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";1300Printer.Indent();1301ExternalSymbolDumper Dumper(Printer);1302Dumper.start(*GlobalScope);1303}1304if (opts::pretty::Lines) {1305Printer.NewLine();1306}1307if (opts::pretty::InjectedSources) {1308Printer.NewLine();1309WithColor(Printer, PDB_ColorItem::SectionHeader).get()1310<< "---INJECTED SOURCES---";1311AutoIndent Indent1(Printer);1312dumpInjectedSources(Printer, *Session);1313}13141315Printer.NewLine();1316outs().flush();1317}13181319static void mergePdbs() {1320BumpPtrAllocator Allocator;1321MergingTypeTableBuilder MergedTpi(Allocator);1322MergingTypeTableBuilder MergedIpi(Allocator);13231324// Create a Tpi and Ipi type table with all types from all input files.1325for (const auto &Path : opts::merge::InputFilenames) {1326std::unique_ptr<IPDBSession> Session;1327auto &File = loadPDB(Path, Session);1328SmallVector<TypeIndex, 128> TypeMap;1329SmallVector<TypeIndex, 128> IdMap;1330if (File.hasPDBTpiStream()) {1331auto &Tpi = ExitOnErr(File.getPDBTpiStream());1332ExitOnErr(1333codeview::mergeTypeRecords(MergedTpi, TypeMap, Tpi.typeArray()));1334}1335if (File.hasPDBIpiStream()) {1336auto &Ipi = ExitOnErr(File.getPDBIpiStream());1337ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,1338Ipi.typeArray()));1339}1340}13411342// Then write the PDB.1343PDBFileBuilder Builder(Allocator);1344ExitOnErr(Builder.initialize(4096));1345// Add each of the reserved streams. We might not put any data in them,1346// but at least they have to be present.1347for (uint32_t I = 0; I < kSpecialStreamCount; ++I)1348ExitOnErr(Builder.getMsfBuilder().addStream(0));13491350auto &DestTpi = Builder.getTpiBuilder();1351auto &DestIpi = Builder.getIpiBuilder();1352MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {1353DestTpi.addTypeRecord(Type.RecordData, std::nullopt);1354});1355MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {1356DestIpi.addTypeRecord(Type.RecordData, std::nullopt);1357});1358Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);13591360SmallString<64> OutFile(opts::merge::PdbOutputFile);1361if (OutFile.empty()) {1362OutFile = opts::merge::InputFilenames[0];1363llvm::sys::path::replace_extension(OutFile, "merged.pdb");1364}13651366codeview::GUID IgnoredOutGuid;1367ExitOnErr(Builder.commit(OutFile, &IgnoredOutGuid));1368}13691370static void explain() {1371std::unique_ptr<IPDBSession> Session;1372InputFile IF =1373ExitOnErr(InputFile::open(opts::explain::InputFilename.front(), true));13741375for (uint64_t Off : opts::explain::Offsets) {1376auto O = std::make_unique<ExplainOutputStyle>(IF, Off);13771378ExitOnErr(O->dump());1379}1380}13811382static void exportStream() {1383std::unique_ptr<IPDBSession> Session;1384PDBFile &File = loadPDB(opts::exportstream::InputFilename.front(), Session);13851386std::unique_ptr<MappedBlockStream> SourceStream;1387uint32_t Index = 0;1388bool Success = false;1389std::string OutFileName = opts::exportstream::OutputFile;13901391if (!opts::exportstream::ForceName) {1392// First try to parse it as an integer, if it fails fall back to treating it1393// as a named stream.1394if (to_integer(opts::exportstream::Stream, Index)) {1395if (Index >= File.getNumStreams()) {1396errs() << "Error: " << Index << " is not a valid stream index.\n";1397exit(1);1398}1399Success = true;1400outs() << "Dumping contents of stream index " << Index << " to file "1401<< OutFileName << ".\n";1402}1403}14041405if (!Success) {1406InfoStream &IS = cantFail(File.getPDBInfoStream());1407Index = ExitOnErr(IS.getNamedStreamIndex(opts::exportstream::Stream));1408outs() << "Dumping contents of stream '" << opts::exportstream::Stream1409<< "' (index " << Index << ") to file " << OutFileName << ".\n";1410}14111412SourceStream = File.createIndexedStream(Index);1413auto OutFile = ExitOnErr(1414FileOutputBuffer::create(OutFileName, SourceStream->getLength()));1415FileBufferByteStream DestStream(std::move(OutFile), llvm::endianness::little);1416BinaryStreamWriter Writer(DestStream);1417ExitOnErr(Writer.writeStreamRef(*SourceStream));1418ExitOnErr(DestStream.commit());1419}14201421static bool parseRange(StringRef Str,1422std::optional<opts::bytes::NumberRange> &Parsed) {1423if (Str.empty())1424return true;14251426llvm::Regex R("^([^-]+)(-([^-]+))?$");1427llvm::SmallVector<llvm::StringRef, 2> Matches;1428if (!R.match(Str, &Matches))1429return false;14301431Parsed.emplace();1432if (!to_integer(Matches[1], Parsed->Min))1433return false;14341435if (!Matches[3].empty()) {1436Parsed->Max.emplace();1437if (!to_integer(Matches[3], *Parsed->Max))1438return false;1439}1440return true;1441}14421443static void simplifyChunkList(llvm::cl::list<opts::ModuleSubsection> &Chunks) {1444// If this list contains "All" plus some other stuff, remove the other stuff1445// and just keep "All" in the list.1446if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All))1447return;1448Chunks.reset();1449Chunks.push_back(opts::ModuleSubsection::All);1450}14511452int main(int Argc, const char **Argv) {1453InitLLVM X(Argc, Argv);1454ExitOnErr.setBanner("llvm-pdbutil: ");14551456cl::HideUnrelatedOptions(1457{&opts::TypeCategory, &opts::FilterCategory, &opts::OtherOptions});1458cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");14591460if (opts::BytesSubcommand) {1461if (!parseRange(opts::bytes::DumpBlockRangeOpt,1462opts::bytes::DumpBlockRange)) {1463errs() << "Argument '" << opts::bytes::DumpBlockRangeOpt1464<< "' invalid format.\n";1465errs().flush();1466exit(1);1467}1468if (!parseRange(opts::bytes::DumpByteRangeOpt,1469opts::bytes::DumpByteRange)) {1470errs() << "Argument '" << opts::bytes::DumpByteRangeOpt1471<< "' invalid format.\n";1472errs().flush();1473exit(1);1474}1475}14761477if (opts::DumpSubcommand) {1478if (opts::dump::RawAll) {1479opts::dump::DumpGlobals = true;1480opts::dump::DumpFpo = true;1481opts::dump::DumpInlineeLines = true;1482opts::dump::DumpIds = true;1483opts::dump::DumpIdExtras = true;1484opts::dump::DumpLines = true;1485opts::dump::DumpModules = true;1486opts::dump::DumpModuleFiles = true;1487opts::dump::DumpPublics = true;1488opts::dump::DumpSectionContribs = true;1489opts::dump::DumpSectionHeaders = true;1490opts::dump::DumpSectionMap = true;1491opts::dump::DumpStreams = true;1492opts::dump::DumpStreamBlocks = true;1493opts::dump::DumpStringTable = true;1494opts::dump::DumpStringTableDetails = true;1495opts::dump::DumpSummary = true;1496opts::dump::DumpSymbols = true;1497opts::dump::DumpSymbolStats = true;1498opts::dump::DumpTypes = true;1499opts::dump::DumpTypeExtras = true;1500opts::dump::DumpUdtStats = true;1501opts::dump::DumpXme = true;1502opts::dump::DumpXmi = true;1503}1504}1505if (opts::PdbToYamlSubcommand) {1506if (opts::pdb2yaml::All) {1507opts::pdb2yaml::StreamMetadata = true;1508opts::pdb2yaml::StreamDirectory = true;1509opts::pdb2yaml::PdbStream = true;1510opts::pdb2yaml::StringTable = true;1511opts::pdb2yaml::DbiStream = true;1512opts::pdb2yaml::TpiStream = true;1513opts::pdb2yaml::IpiStream = true;1514opts::pdb2yaml::PublicsStream = true;1515opts::pdb2yaml::DumpModules = true;1516opts::pdb2yaml::DumpModuleFiles = true;1517opts::pdb2yaml::DumpModuleSyms = true;1518opts::pdb2yaml::DumpModuleSubsections.push_back(1519opts::ModuleSubsection::All);1520}1521simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections);15221523if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)1524opts::pdb2yaml::DumpModules = true;15251526if (opts::pdb2yaml::DumpModules)1527opts::pdb2yaml::DbiStream = true;1528}15291530llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);15311532// Initialize the filters for LinePrinter.1533auto propagate = [&](auto &Target, auto &Reference) {1534for (std::string &Option : Reference)1535Target.push_back(Option);1536};15371538propagate(opts::Filters.ExcludeTypes, opts::pretty::ExcludeTypes);1539propagate(opts::Filters.ExcludeTypes, opts::pretty::ExcludeTypes);1540propagate(opts::Filters.ExcludeSymbols, opts::pretty::ExcludeSymbols);1541propagate(opts::Filters.ExcludeCompilands, opts::pretty::ExcludeCompilands);1542propagate(opts::Filters.IncludeTypes, opts::pretty::IncludeTypes);1543propagate(opts::Filters.IncludeSymbols, opts::pretty::IncludeSymbols);1544propagate(opts::Filters.IncludeCompilands, opts::pretty::IncludeCompilands);1545opts::Filters.PaddingThreshold = opts::pretty::PaddingThreshold;1546opts::Filters.SizeThreshold = opts::pretty::SizeThreshold;1547opts::Filters.JustMyCode = opts::dump::JustMyCode;1548if (opts::dump::DumpModi.getNumOccurrences() > 0) {1549if (opts::dump::DumpModi.getNumOccurrences() != 1) {1550errs() << "argument '-modi' specified more than once.\n";1551errs().flush();1552exit(1);1553}1554opts::Filters.DumpModi = opts::dump::DumpModi;1555}1556if (opts::dump::DumpSymbolOffset) {1557if (opts::dump::DumpModi.getNumOccurrences() != 1) {1558errs()1559<< "need to specify argument '-modi' when using '-symbol-offset'.\n";1560errs().flush();1561exit(1);1562}1563opts::Filters.SymbolOffset = opts::dump::DumpSymbolOffset;1564if (opts::dump::DumpParents)1565opts::Filters.ParentRecurseDepth = opts::dump::DumpParentDepth;1566if (opts::dump::DumpChildren)1567opts::Filters.ChildrenRecurseDepth = opts::dump::DumpChildrenDepth;1568}15691570if (opts::PdbToYamlSubcommand) {1571pdb2Yaml(opts::pdb2yaml::InputFilename.front());1572} else if (opts::YamlToPdbSubcommand) {1573if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {1574SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());1575sys::path::replace_extension(OutputFilename, ".pdb");1576opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename);1577}1578yamlToPdb(opts::yaml2pdb::InputFilename);1579} else if (opts::DiaDumpSubcommand) {1580llvm::for_each(opts::diadump::InputFilenames, dumpDia);1581} else if (opts::PrettySubcommand) {1582if (opts::pretty::Lines)1583opts::pretty::Compilands = true;15841585if (opts::pretty::All) {1586opts::pretty::Compilands = true;1587opts::pretty::Symbols = true;1588opts::pretty::Globals = true;1589opts::pretty::Types = true;1590opts::pretty::Externals = true;1591opts::pretty::Lines = true;1592}15931594if (opts::pretty::Types) {1595opts::pretty::Classes = true;1596opts::pretty::Typedefs = true;1597opts::pretty::Enums = true;1598opts::pretty::Pointers = true;1599opts::pretty::Funcsigs = true;1600}16011602// When adding filters for excluded compilands and types, we need to1603// remember that these are regexes. So special characters such as * and \1604// need to be escaped in the regex. In the case of a literal \, this means1605// it needs to be escaped again in the C++. So matching a single \ in the1606// input requires 4 \es in the C++.1607if (opts::pretty::ExcludeCompilerGenerated) {1608opts::Filters.ExcludeTypes.push_back("__vc_attributes");1609opts::Filters.ExcludeCompilands.push_back("\\* Linker \\*");1610}1611if (opts::pretty::ExcludeSystemLibraries) {1612opts::Filters.ExcludeCompilands.push_back(1613"f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");1614opts::Filters.ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");1615opts::Filters.ExcludeCompilands.push_back(1616"d:\\\\th.obj.x86fre\\\\minkernel");1617}1618llvm::for_each(opts::pretty::InputFilenames, dumpPretty);1619} else if (opts::DumpSubcommand) {1620llvm::for_each(opts::dump::InputFilenames, dumpRaw);1621} else if (opts::BytesSubcommand) {1622llvm::for_each(opts::bytes::InputFilenames, dumpBytes);1623} else if (opts::MergeSubcommand) {1624if (opts::merge::InputFilenames.size() < 2) {1625errs() << "merge subcommand requires at least 2 input files.\n";1626exit(1);1627}1628mergePdbs();1629} else if (opts::ExplainSubcommand) {1630explain();1631} else if (opts::ExportSubcommand) {1632exportStream();1633}16341635outs().flush();1636return 0;1637}163816391640