LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
: File(File), P(outs()), TD(&P, false) {}
+Error LLVMOutputStyle::dump() {
+ if (auto EC = dumpFileHeaders())
+ return EC;
+
+ if (auto EC = dumpStreamSummary())
+ return EC;
+
+ if (auto EC = dumpStreamBlocks())
+ return EC;
+
+ if (auto EC = dumpStreamData())
+ return EC;
+
+ if (auto EC = dumpInfoStream())
+ return EC;
+
+ if (auto EC = dumpNamedStream())
+ return EC;
+
+ if (auto EC = dumpTpiStream(StreamTPI))
+ return EC;
+
+ if (auto EC = dumpTpiStream(StreamIPI))
+ return EC;
+
+ if (auto EC = dumpDbiStream())
+ return EC;
+
+ if (auto EC = dumpSectionContribs())
+ return EC;
+
+ if (auto EC = dumpSectionMap())
+ return EC;
+
+ if (auto EC = dumpPublicsStream())
+ return EC;
+
+ if (auto EC = dumpSectionHeaders())
+ return EC;
+
+ if (auto EC = dumpFpoStream())
+ return EC;
+
+ flush();
+
+ return Error::success();
+}
+
Error LLVMOutputStyle::dumpFileHeaders() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
DictScope D(P, "FileHeaders");
}
Error LLVMOutputStyle::dumpStreamSummary() {
- if (!opts::DumpStreamSummary)
+ if (!opts::raw::DumpStreamSummary)
return Error::success();
// It's OK if we fail to load some of these streams, we still attempt to print
}
Error LLVMOutputStyle::dumpStreamBlocks() {
- if (!opts::DumpStreamBlocks)
+ if (!opts::raw::DumpStreamBlocks)
return Error::success();
ListScope L(P, "StreamBlocks");
Error LLVMOutputStyle::dumpStreamData() {
uint32_t StreamCount = File.getNumStreams();
- StringRef DumpStreamStr = opts::DumpStreamDataIdx;
+ StringRef DumpStreamStr = opts::raw::DumpStreamDataIdx;
uint32_t DumpStreamNum;
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum))
return Error::success();
}
Error LLVMOutputStyle::dumpInfoStream() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
auto IS = File.getPDBInfoStream();
if (!IS)
}
Error LLVMOutputStyle::dumpNamedStream() {
- if (opts::DumpStreamDataName.empty())
+ if (opts::raw::DumpStreamDataName.empty())
return Error::success();
auto IS = File.getPDBInfoStream();
if (!IS)
return IS.takeError();
- uint32_t NameStreamIndex = IS->getNamedStreamIndex(opts::DumpStreamDataName);
+ uint32_t NameStreamIndex =
+ IS->getNamedStreamIndex(opts::raw::DumpStreamDataName);
if (NameStreamIndex == 0 || NameStreamIndex >= File.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
if (NameStreamIndex != 0) {
std::string Name("Stream '");
- Name += opts::DumpStreamDataName;
+ Name += opts::raw::DumpStreamDataName;
Name += "'";
DictScope D(P, Name);
P.printNumber("Index", NameStreamIndex);
}
static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) {
- if (!opts::DumpTpiHash)
+ if (!opts::raw::DumpTpiHash)
return;
DictScope DD(P, "Hash");
P.printNumber("Number of Hash Buckets", Tpi.NumHashBuckets());
StringRef Label;
StringRef VerLabel;
if (StreamIdx == StreamTPI) {
- DumpRecordBytes = opts::DumpTpiRecordBytes;
- DumpRecords = opts::DumpTpiRecords;
+ DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
+ DumpRecords = opts::raw::DumpTpiRecords;
Label = "Type Info Stream (TPI)";
VerLabel = "TPI Version";
} else if (StreamIdx == StreamIPI) {
- DumpRecordBytes = opts::DumpIpiRecordBytes;
- DumpRecords = opts::DumpIpiRecords;
+ DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
+ DumpRecords = opts::raw::DumpIpiRecords;
Label = "Type Info Stream (IPI)";
VerLabel = "IPI Version";
}
- if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
+ if (!DumpRecordBytes && !DumpRecords && !opts::raw::DumpModuleSyms)
return Error::success();
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI stream contained corrupt record");
- } else if (opts::DumpModuleSyms) {
+ } else if (opts::raw::DumpModuleSyms) {
// Even if the user doesn't want to dump type records, we still need to
// iterate them in order to build the list of types so that we can print
// them when dumping module symbols. So when they want to dump symbols
}
Error LLVMOutputStyle::dumpDbiStream() {
- bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
- opts::DumpModuleFiles || opts::DumpLineInfo;
- if (!opts::DumpHeaders && !DumpModules)
+ bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
+ opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
+ if (!opts::raw::DumpHeaders && !DumpModules)
return Error::success();
auto DS = File.getPDBDbiStream();
P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
- if (opts::DumpModuleFiles) {
+ if (opts::raw::DumpModuleFiles) {
std::string FileListName =
to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
ListScope LL(P, FileListName);
bool HasModuleDI =
(Modi.Info.getModuleStreamIndex() < File.getNumStreams());
bool ShouldDumpSymbols =
- (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
- if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
+ (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
+ if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
auto ModStreamData = MappedBlockStream::createIndexedStream(
Modi.Info.getModuleStreamIndex(), File);
if (!ModStreamData)
for (const auto &S : ModS.symbols(&HadError)) {
DictScope DD(P, "");
- if (opts::DumpModuleSyms)
+ if (opts::raw::DumpModuleSyms)
SD.dump(S);
- if (opts::DumpSymRecordBytes)
+ if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
raw_error_code::corrupt_file,
"DBI stream contained corrupt symbol record");
}
- if (opts::DumpLineInfo) {
+ if (opts::raw::DumpLineInfo) {
ListScope SS(P, "LineInfo");
bool HadError = false;
// Define a locally scoped visitor to print the different
}
Error LLVMOutputStyle::dumpSectionContribs() {
- if (!opts::DumpSectionContribs)
+ if (!opts::raw::DumpSectionContribs)
return Error::success();
auto Dbi = File.getPDBDbiStream();
}
Error LLVMOutputStyle::dumpSectionMap() {
- if (!opts::DumpSectionMap)
+ if (!opts::raw::DumpSectionMap)
return Error::success();
auto Dbi = File.getPDBDbiStream();
}
Error LLVMOutputStyle::dumpPublicsStream() {
- if (!opts::DumpPublics)
+ if (!opts::raw::DumpPublics)
return Error::success();
DictScope D(P, "Publics Stream");
DictScope DD(P, "");
SD.dump(S);
- if (opts::DumpSymRecordBytes)
+ if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
}
Error LLVMOutputStyle::dumpSectionHeaders() {
- if (!opts::DumpSectionHeaders)
+ if (!opts::raw::DumpSectionHeaders)
return Error::success();
auto Dbi = File.getPDBDbiStream();
}
Error LLVMOutputStyle::dumpFpoStream() {
- if (!opts::DumpFpo)
+ if (!opts::raw::DumpFpo)
return Error::success();
auto Dbi = File.getPDBDbiStream();
}
return Error::success();
}
+
void LLVMOutputStyle::flush() { P.flush(); }
namespace opts {
-enum class PDB_DumpType { ByType, ByObjFile, Both };
-
-cl::list<std::string> InputFilenames(cl::Positional,
- cl::desc("<input PDB files>"),
- cl::OneOrMore);
+cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
+cl::SubCommand
+ PrettySubcommand("pretty",
+ "Dump semantic information about types and symbols");
+cl::SubCommand YamlToPdbSubcommand("yaml2pdb", "Generate a PDB file from a YAML description");
+cl::SubCommand
+ PdbToYamlSubcommand("pdb2yaml",
+ "Generate a detailed YAML description of a PDB File");
cl::OptionCategory TypeCategory("Symbol Type Options");
cl::OptionCategory FilterCategory("Filtering Options");
cl::OptionCategory OtherOptions("Other Options");
-cl::OptionCategory NativeOptions("Native Options");
+
+namespace pretty {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(PrettySubcommand));
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
- cl::cat(TypeCategory));
-cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
-cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
+ cl::sub(PrettySubcommand));
+cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
+ cl::sub(PrettySubcommand));
cl::opt<bool>
All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<uint64_t> LoadAddress(
"load-address",
cl::desc("Assume the module is loaded at the specified address"),
- cl::cat(OtherOptions));
-
-cl::opt<OutputStyleTy>
- RawOutputStyle("raw-output-style", cl::desc("Specify dump outpout style"),
- cl::values(clEnumVal(LLVM, "LLVM default style"),
- clEnumVal(YAML, "YAML style"), clEnumValEnd),
- cl::init(LLVM), cl::cat(NativeOptions));
-
-cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpStreamBlocks("raw-stream-blocks",
- cl::desc("dump PDB stream blocks"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpStreamSummary("raw-stream-summary",
- cl::desc("dump summary of the PDB streams"),
- cl::cat(NativeOptions));
-cl::opt<bool>
- DumpTpiRecords("raw-tpi-records",
- cl::desc("dump CodeView type records from TPI stream"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpTpiRecordBytes(
- "raw-tpi-record-bytes",
- cl::desc("dump CodeView type record raw bytes from TPI stream"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpTpiHash("raw-tpi-hash",
- cl::desc("dump CodeView TPI hash stream"),
- cl::cat(NativeOptions));
-cl::opt<bool>
- DumpIpiRecords("raw-ipi-records",
- cl::desc("dump CodeView type records from IPI stream"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpIpiRecordBytes(
- "raw-ipi-record-bytes",
- cl::desc("dump CodeView type record raw bytes from IPI stream"),
- cl::cat(NativeOptions));
-cl::opt<std::string> DumpStreamDataIdx("raw-stream",
- cl::desc("dump stream data"),
- cl::cat(NativeOptions));
-cl::opt<std::string> DumpStreamDataName("raw-stream-name",
- cl::desc("dump stream data"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModuleFiles("raw-module-files",
- cl::desc("dump file information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionContribs("raw-section-contribs",
- cl::desc("dump section contributions"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpLineInfo("raw-line-info",
- cl::desc("dump file and line information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionMap("raw-section-map", cl::desc("dump section map"),
- cl::cat(NativeOptions));
-cl::opt<bool>
- DumpSymRecordBytes("raw-sym-record-bytes",
- cl::desc("dump CodeView symbol record raw bytes"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionHeaders("raw-section-headers",
- cl::desc("dump section headers"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpFpo("raw-fpo", cl::desc("dump FPO records"),
- cl::cat(NativeOptions));
-
-cl::opt<bool>
- RawAll("raw-all",
- cl::desc("Implies most other options in 'Native Options' category"),
- cl::cat(NativeOptions));
-
-cl::opt<bool>
- YamlToPdb("yaml-to-pdb",
- cl::desc("The input file is yaml, and the tool outputs a pdb"),
- cl::cat(NativeOptions));
-cl::opt<std::string> YamlPdbOutputFile(
- "pdb-output", cl::desc("When yaml-to-pdb is specified, the output file"),
- cl::cat(NativeOptions));
-
-cl::list<std::string>
- ExcludeTypes("exclude-types",
- cl::desc("Exclude types by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string>
- ExcludeSymbols("exclude-symbols",
- cl::desc("Exclude symbols by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string>
- ExcludeCompilands("exclude-compilands",
- cl::desc("Exclude compilands by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeTypes(
+ "exclude-types", cl::desc("Exclude types by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeSymbols(
+ "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeCompilands(
+ "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::list<std::string> IncludeTypes(
"include-types",
cl::desc("Include only types which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::list<std::string> IncludeSymbols(
"include-symbols",
cl::desc("Include only symbols which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::list<std::string> IncludeCompilands(
"include-compilands",
cl::desc("Include only compilands those which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::opt<bool> ExcludeCompilerGenerated(
"no-compiler-generated",
cl::desc("Don't show compiler generated types and symbols"),
- cl::cat(FilterCategory));
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::opt<bool>
ExcludeSystemLibraries("no-system-libs",
cl::desc("Don't show symbols from system libraries"),
- cl::cat(FilterCategory));
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::opt<bool> NoClassDefs("no-class-definitions",
cl::desc("Don't display full class definitions"),
- cl::cat(FilterCategory));
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
cl::opt<bool> NoEnumDefs("no-enum-definitions",
cl::desc("Don't display full enum definitions"),
- cl::cat(FilterCategory));
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
}
-static ExitOnError ExitOnErr;
+namespace raw {
-static Error dumpStructure(RawSession &RS) {
- PDBFile &File = RS.getPDBFile();
- std::unique_ptr<OutputStyle> O;
- if (opts::RawOutputStyle == opts::OutputStyleTy::LLVM)
- O = llvm::make_unique<LLVMOutputStyle>(File);
- else if (opts::RawOutputStyle == opts::OutputStyleTy::YAML)
- O = llvm::make_unique<YAMLOutputStyle>(File);
- else
- return make_error<RawError>(raw_error_code::feature_unsupported,
- "Requested output style unsupported");
-
- if (auto EC = O->dumpFileHeaders())
- return EC;
-
- if (auto EC = O->dumpStreamSummary())
- return EC;
-
- if (auto EC = O->dumpStreamBlocks())
- return EC;
+cl::OptionCategory MsfOptions("MSF Container Options");
+cl::OptionCategory TypeOptions("Type Record Options");
+cl::OptionCategory FileOptions("Module & File Options");
+cl::OptionCategory SymbolOptions("Symbol Options");
+cl::OptionCategory MiscOptions("Miscellaneous Options");
- if (auto EC = O->dumpStreamData())
- return EC;
-
- if (auto EC = O->dumpInfoStream())
- return EC;
-
- if (auto EC = O->dumpNamedStream())
- return EC;
+// MSF OPTIONS
+cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
+ cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpStreamBlocks("stream-blocks",
+ cl::desc("dump PDB stream blocks"),
+ cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpStreamSummary("stream-summary",
+ cl::desc("dump summary of the PDB streams"),
+ cl::cat(MsfOptions), cl::sub(RawSubcommand));
- if (auto EC = O->dumpTpiStream(StreamTPI))
- return EC;
+// TYPE OPTIONS
+cl::opt<bool>
+ DumpTpiRecords("tpi-records",
+ cl::desc("dump CodeView type records from TPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpTpiRecordBytes(
+ "tpi-record-bytes",
+ cl::desc("dump CodeView type record raw bytes from TPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool>
+ DumpIpiRecords("ipi-records",
+ cl::desc("dump CodeView type records from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpIpiRecordBytes(
+ "ipi-record-bytes",
+ cl::desc("dump CodeView type record raw bytes from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+// MODULE & FILE OPTIONS
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpLineInfo("line-info",
+ cl::desc("dump file and line information"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+
+// SYMBOL OPTIONS
+cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
+ cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
+ cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+cl::opt<bool>
+ DumpSymRecordBytes("sym-record-bytes",
+ cl::desc("dump CodeView symbol record raw bytes"),
+ cl::cat(SymbolOptions), cl::sub(RawSubcommand));
- if (auto EC = O->dumpTpiStream(StreamIPI))
- return EC;
+// MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpSectionContribs("section-contribs",
+ cl::desc("dump section contributions"),
+ cl::cat(MiscOptions),
+ cl::sub(RawSubcommand));
+cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
+ cl::cat(MiscOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
+ cl::desc("dump section headers"),
+ cl::cat(MiscOptions),
+ cl::sub(RawSubcommand));
+cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
+ cl::cat(MiscOptions), cl::sub(RawSubcommand));
+
+cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
+ cl::cat(MiscOptions),
+ cl::sub(RawSubcommand));
+cl::opt<std::string> DumpStreamDataName("stream-name",
+ cl::desc("dump stream data"),
+ cl::cat(MiscOptions),
+ cl::sub(RawSubcommand));
- if (auto EC = O->dumpDbiStream())
- return EC;
+cl::opt<bool>
+ RawAll("all",
+ cl::desc("Implies most other options."),
+ cl::cat(MiscOptions), cl::sub(RawSubcommand));
- if (auto EC = O->dumpSectionContribs())
- return EC;
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(RawSubcommand));
+}
- if (auto EC = O->dumpSectionMap())
- return EC;
+namespace yaml2pdb {
+cl::opt<std::string>
+ YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+ cl::sub(YamlToPdbSubcommand));
- if (auto EC = O->dumpPublicsStream())
- return EC;
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input YAML file>"), cl::Required,
+ cl::sub(YamlToPdbSubcommand));
+}
- if (auto EC = O->dumpSectionHeaders())
- return EC;
+namespace pdb2yaml {
+ cl::opt<bool> StreamMetadata("stream-metadata", cl::desc("Dump the number of streams and each stream's size"), cl::sub(PdbToYamlSubcommand));
+ cl::opt<bool> StreamDirectory("stream-directory", cl::desc("Dump each stream's block map (implies -stream-metadata)"), cl::sub(PdbToYamlSubcommand));
- if (auto EC = O->dumpFpoStream())
- return EC;
- O->flush();
- return Error::success();
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(PdbToYamlSubcommand));
}
-
-bool isRawDumpEnabled() {
- if (opts::DumpHeaders)
- return true;
- if (opts::DumpModules)
- return true;
- if (opts::DumpModuleFiles)
- return true;
- if (opts::DumpModuleSyms)
- return true;
- if (!opts::DumpStreamDataIdx.empty())
- return true;
- if (!opts::DumpStreamDataName.empty())
- return true;
- if (opts::DumpPublics)
- return true;
- if (opts::DumpStreamSummary)
- return true;
- if (opts::DumpStreamBlocks)
- return true;
- if (opts::DumpSymRecordBytes)
- return true;
- if (opts::DumpTpiRecordBytes)
- return true;
- if (opts::DumpTpiRecords)
- return true;
- if (opts::DumpTpiHash)
- return true;
- if (opts::DumpIpiRecords)
- return true;
- if (opts::DumpIpiRecordBytes)
- return true;
- if (opts::DumpSectionHeaders)
- return true;
- if (opts::DumpSectionContribs)
- return true;
- if (opts::DumpSectionMap)
- return true;
- if (opts::DumpLineInfo)
- return true;
- if (opts::DumpFpo)
- return true;
- return false;
}
+static ExitOnError ExitOnErr;
+
static void yamlToPdb(StringRef Path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
pdb::yaml::PdbObject YamlObj;
In >> YamlObj;
- auto OutFileOrError = FileOutputBuffer::create(opts::YamlPdbOutputFile,
- YamlObj.Headers.FileSize);
+ auto OutFileOrError = FileOutputBuffer::create(
+ opts::yaml2pdb::YamlPdbOutputFile, YamlObj.Headers.FileSize);
if (OutFileOrError.getError())
ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path,
- opts::YamlPdbOutputFile));
+ opts::yaml2pdb::YamlPdbOutputFile));
auto FileByteStream =
llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
Pdb.commit();
}
-static void dumpInput(StringRef Path) {
+static void dumpRaw(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- if (isRawDumpEnabled()) {
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
+ ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
- RawSession *RS = static_cast<RawSession *>(Session.get());
- ExitOnErr(dumpStructure(*RS));
- return;
- }
+ RawSession *RS = static_cast<RawSession *>(Session.get());
+ PDBFile &File = RS->getPDBFile();
+ std::unique_ptr<OutputStyle> O;
+ if (opts::PdbToYamlSubcommand)
+ O = llvm::make_unique<YAMLOutputStyle>(File);
+ else
+ O = llvm::make_unique<LLVMOutputStyle>(File);
+
+ ExitOnErr(O->dump());
+}
+
+static void dumpPretty(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, Session));
- if (opts::LoadAddress)
- Session->setLoadAddress(opts::LoadAddress);
+ if (opts::pretty::LoadAddress)
+ Session->setLoadAddress(opts::pretty::LoadAddress);
LinePrinter Printer(2, outs());
outs() << "HasPrivateSymbols ";
Printer.Unindent();
- if (opts::Compilands) {
+ if (opts::pretty::Compilands) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get()
<< "---COMPILANDS---";
auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
CompilandDumper Dumper(Printer);
CompilandDumpFlags options = CompilandDumper::Flags::None;
- if (opts::Lines)
+ if (opts::pretty::Lines)
options = options | CompilandDumper::Flags::Lines;
while (auto Compiland = Compilands->getNext())
Dumper.start(*Compiland, options);
Printer.Unindent();
}
- if (opts::Types) {
+ if (opts::pretty::Types) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
Printer.Indent();
Printer.Unindent();
}
- if (opts::Symbols) {
+ if (opts::pretty::Symbols) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
Printer.Indent();
Printer.Unindent();
}
- if (opts::Globals) {
+ if (opts::pretty::Globals) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
Printer.Indent();
}
Printer.Unindent();
}
- if (opts::Externals) {
+ if (opts::pretty::Externals) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
Printer.Indent();
ExternalSymbolDumper Dumper(Printer);
Dumper.start(*GlobalScope);
}
- if (opts::Lines) {
+ if (opts::pretty::Lines) {
Printer.NewLine();
}
outs().flush();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
- if (opts::Lines)
- opts::Compilands = true;
-
- if (opts::All) {
- opts::Compilands = true;
- opts::Symbols = true;
- opts::Globals = true;
- opts::Types = true;
- opts::Externals = true;
- opts::Lines = true;
- }
- if (opts::RawAll) {
- opts::DumpHeaders = true;
- opts::DumpModules = true;
- opts::DumpModuleFiles = true;
- opts::DumpModuleSyms = true;
- opts::DumpPublics = true;
- opts::DumpSectionHeaders = true;
- opts::DumpStreamSummary = true;
- opts::DumpStreamBlocks = true;
- opts::DumpTpiRecords = true;
- opts::DumpTpiHash = true;
- opts::DumpIpiRecords = true;
- opts::DumpSectionMap = true;
- opts::DumpSectionContribs = true;
- opts::DumpLineInfo = true;
- opts::DumpFpo = true;
- }
-
- // When adding filters for excluded compilands and types, we need to remember
- // that these are regexes. So special characters such as * and \ need to be
- // escaped in the regex. In the case of a literal \, this means it needs to
- // be escaped again in the C++. So matching a single \ in the input requires
- // 4 \es in the C++.
- if (opts::ExcludeCompilerGenerated) {
- opts::ExcludeTypes.push_back("__vc_attributes");
- opts::ExcludeCompilands.push_back("\\* Linker \\*");
- }
- if (opts::ExcludeSystemLibraries) {
- opts::ExcludeCompilands.push_back(
- "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
- opts::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
- opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel");
+ // These options are shared by two subcommands.
+ if ((opts::PdbToYamlSubcommand || opts::RawSubcommand) && opts::raw::RawAll) {
+ opts::raw::DumpHeaders = true;
+ opts::raw::DumpModules = true;
+ opts::raw::DumpModuleFiles = true;
+ opts::raw::DumpModuleSyms = true;
+ opts::raw::DumpPublics = true;
+ opts::raw::DumpSectionHeaders = true;
+ opts::raw::DumpStreamSummary = true;
+ opts::raw::DumpStreamBlocks = true;
+ opts::raw::DumpTpiRecords = true;
+ opts::raw::DumpTpiHash = true;
+ opts::raw::DumpIpiRecords = true;
+ opts::raw::DumpSectionMap = true;
+ opts::raw::DumpSectionContribs = true;
+ opts::raw::DumpLineInfo = true;
+ opts::raw::DumpFpo = true;
}
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
- if (opts::YamlToPdb) {
- std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
- yamlToPdb);
- } else {
- std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
- dumpInput);
+ if (opts::PdbToYamlSubcommand) {
+ dumpRaw(opts::pdb2yaml::InputFilename.front());
+ } else if (opts::YamlToPdbSubcommand) {
+ yamlToPdb(opts::yaml2pdb::InputFilename.front());
+ } else if (opts::PrettySubcommand) {
+ if (opts::pretty::Lines)
+ opts::pretty::Compilands = true;
+
+ if (opts::pretty::All) {
+ opts::pretty::Compilands = true;
+ opts::pretty::Symbols = true;
+ opts::pretty::Globals = true;
+ opts::pretty::Types = true;
+ opts::pretty::Externals = true;
+ opts::pretty::Lines = true;
+ }
+
+ // When adding filters for excluded compilands and types, we need to
+ // remember
+ // that these are regexes. So special characters such as * and \ need to be
+ // escaped in the regex. In the case of a literal \, this means it needs to
+ // be escaped again in the C++. So matching a single \ in the input
+ // requires
+ // 4 \es in the C++.
+ if (opts::pretty::ExcludeCompilerGenerated) {
+ opts::pretty::ExcludeTypes.push_back("__vc_attributes");
+ opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
+ }
+ if (opts::pretty::ExcludeSystemLibraries) {
+ opts::pretty::ExcludeCompilands.push_back(
+ "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
+ opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
+ opts::pretty::ExcludeCompilands.push_back(
+ "d:\\\\th.obj.x86fre\\\\minkernel");
+ }
+ std::for_each(opts::pretty::InputFilenames.begin(),
+ opts::pretty::InputFilenames.end(), dumpPretty);
+ } else if (opts::RawSubcommand) {
+ std::for_each(opts::raw::InputFilenames.begin(),
+ opts::raw::InputFilenames.end(), dumpRaw);
}
outs().flush();