summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp')
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp308
1 files changed, 169 insertions, 139 deletions
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 0467fdaad43..fa235e28006 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -52,6 +52,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@@ -104,6 +105,13 @@ cl::opt<bool> DumpStreamSizes("dump-stream-sizes",
cl::opt<bool> DumpStreamBlocks("dump-stream-blocks",
cl::desc("dump PDB stream blocks"),
cl::cat(OtherOptions));
+cl::opt<bool> DumpTypeStream("dump-tpi-stream",
+ cl::desc("dump PDB TPI (Type Info) stream"),
+ cl::cat(OtherOptions));
+cl::opt<bool>
+ DumpTpiRecordBytes("dump-tpi-record-bytes",
+ cl::desc("dump CodeView type record raw bytes"),
+ cl::cat(OtherOptions));
cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"),
cl::cat(OtherOptions));
@@ -149,183 +157,205 @@ cl::opt<bool> NoEnumDefs("no-enum-definitions",
cl::cat(FilterCategory));
}
-static void dumpBytes(raw_ostream &S, StringRef Bytes, uint32_t BytesPerRow,
- uint32_t Indent) {
- S << "[";
-
- while (!Bytes.empty()) {
- size_t BytesThisLine = std::min<size_t>(Bytes.size(), BytesPerRow);
- while (BytesThisLine > 0) {
- S << format_hex_no_prefix(uint8_t(Bytes.front()), 2, true);
- Bytes = Bytes.drop_front();
- if (--BytesThisLine > 0)
- S << ' ';
- }
- if (!Bytes.empty()) {
- S << '\n';
- S.indent(Indent);
- }
- }
- S << ']';
-}
-
-static void dumpStructure(RawSession &RS) {
- PDBFile &File = RS.getPDBFile();
-
- if (opts::DumpHeaders) {
- outs() << "BlockSize: " << File.getBlockSize() << '\n';
- outs() << "Unknown0: " << File.getUnknown0() << '\n';
- outs() << "NumBlocks: " << File.getBlockCount() << '\n';
- outs() << "NumDirectoryBytes: " << File.getNumDirectoryBytes() << '\n';
- outs() << "Unknown1: " << File.getUnknown1() << '\n';
- outs() << "BlockMapAddr: " << File.getBlockMapIndex() << '\n';
- }
-
- if (opts::DumpHeaders)
- outs() << "NumDirectoryBlocks: " << File.getNumDirectoryBlocks() << '\n';
-
- if (opts::DumpHeaders)
- outs() << "BlockMapOffset: " << File.getBlockMapOffset() << '\n';
+static void dumpFileHeaders(ScopedPrinter &P, PDBFile &File) {
+ if (!opts::DumpHeaders)
+ return;
+ DictScope D(P, "FileHeaders");
+ P.printNumber("BlockSize", File.getBlockSize());
+ P.printNumber("Unknown0", File.getUnknown0());
+ P.printNumber("NumBlocks", File.getBlockCount());
+ P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
+ P.printNumber("Unknown1", File.getUnknown1());
+ P.printNumber("BlockMapAddr", File.getBlockMapIndex());
+ P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
+ P.printNumber("BlockMapOffset", File.getBlockMapOffset());
// The directory is not contiguous. Instead, the block map contains a
// contiguous list of block numbers whose contents, when concatenated in
// order, make up the directory.
- auto DirectoryBlocks = File.getDirectoryBlockArray();
-
- if (opts::DumpHeaders) {
- outs() << "DirectoryBlocks: [";
- for (const auto &DirectoryBlockAddr : DirectoryBlocks) {
- if (&DirectoryBlockAddr != &DirectoryBlocks.front())
- outs() << ", ";
- outs() << DirectoryBlockAddr;
- }
- outs() << "]\n";
- }
+ P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
+ P.printNumber("NumStreams", File.getNumStreams());
+}
- if (opts::DumpHeaders)
- outs() << "NumStreams: " << File.getNumStreams() << '\n';
+static void dumpStreamSizes(ScopedPrinter &P, PDBFile &File) {
+ if (!opts::DumpStreamSizes)
+ return;
+
+ ListScope L(P, "StreamSizes");
uint32_t StreamCount = File.getNumStreams();
- if (opts::DumpStreamSizes) {
- for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx)
- outs() << "StreamSizes[" << StreamIdx
- << "]: " << File.getStreamByteSize(StreamIdx) << '\n';
+ for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ std::string Name("Stream ");
+ Name += to_string(StreamIdx);
+ P.printNumber(Name, File.getStreamByteSize(StreamIdx));
}
+}
- if (opts::DumpStreamBlocks) {
- for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- outs() << "StreamBlocks[" << StreamIdx << "]: [";
- auto StreamBlocks = File.getStreamBlockList(StreamIdx);
- for (size_t i = 0; i < StreamBlocks.size(); ++i) {
- if (i != 0)
- outs() << ", ";
- outs() << StreamBlocks[i];
- }
- outs() << "]\n";
- }
+static void dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) {
+ if (!opts::DumpStreamBlocks)
+ return;
+
+ ListScope L(P, "StreamBlocks");
+ uint32_t StreamCount = File.getNumStreams();
+ for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ std::string Name("Stream ");
+ Name += to_string(StreamIdx);
+ auto StreamBlocks = File.getStreamBlockList(StreamIdx);
+ P.printList(Name, StreamBlocks);
}
+}
+static void dumpStreamData(ScopedPrinter &P, PDBFile &File) {
+ uint32_t StreamCount = File.getNumStreams();
StringRef DumpStreamStr = opts::DumpStreamData;
uint32_t DumpStreamNum;
- if (!DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) &&
- DumpStreamNum < StreamCount) {
- uint32_t StreamBytesRead = 0;
- uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum);
- auto StreamBlocks = File.getStreamBlockList(DumpStreamNum);
-
- for (uint32_t StreamBlockAddr : StreamBlocks) {
- uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead;
- if (BytesLeftToReadInStream == 0)
- break;
-
- uint32_t BytesToReadInBlock = std::min(
- BytesLeftToReadInStream, static_cast<uint32_t>(File.getBlockSize()));
- auto StreamBlockData =
- File.getBlockData(StreamBlockAddr, BytesToReadInBlock);
-
- outs() << StreamBlockData;
- StreamBytesRead += StreamBlockData.size();
- }
+ if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
+ DumpStreamNum >= StreamCount)
+ return;
+
+ uint32_t StreamBytesRead = 0;
+ uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum);
+ auto StreamBlocks = File.getStreamBlockList(DumpStreamNum);
+
+ for (uint32_t StreamBlockAddr : StreamBlocks) {
+ uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead;
+ if (BytesLeftToReadInStream == 0)
+ break;
+
+ uint32_t BytesToReadInBlock = std::min(
+ BytesLeftToReadInStream, static_cast<uint32_t>(File.getBlockSize()));
+ auto StreamBlockData =
+ File.getBlockData(StreamBlockAddr, BytesToReadInBlock);
+
+ outs() << StreamBlockData;
+ StreamBytesRead += StreamBlockData.size();
}
+}
+
+static void dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
+ InfoStream &IS = File.getPDBInfoStream();
+
+ DictScope D(P, "PDB Stream");
+ P.printNumber("Version", IS.getVersion());
+ P.printHex("Signature", IS.getSignature());
+ P.printNumber("Age", IS.getAge());
+ P.printObject("Guid", IS.getGuid());
+}
+static void dumpNamedStream(ScopedPrinter &P, PDBFile &File, StringRef Stream) {
InfoStream &IS = File.getPDBInfoStream();
- outs() << "Version: " << IS.getVersion() << '\n';
- outs() << "Signature: ";
- outs().write_hex(IS.getSignature()) << '\n';
- outs() << "Age: " << IS.getAge() << '\n';
- outs() << "Guid: " << IS.getGuid() << '\n';
-
- // Let's try to dump out the named stream "/names".
- uint32_t NameStreamIndex = IS.getNamedStreamIndex("/names");
+ uint32_t NameStreamIndex = IS.getNamedStreamIndex(Stream);
+
if (NameStreamIndex != 0) {
+ std::string Name("Stream '");
+ Name += Stream;
+ Name += "'";
+ DictScope D(P, Name);
+ P.printNumber("Index", NameStreamIndex);
+
MappedBlockStream NameStream(NameStreamIndex, File);
StreamReader Reader(NameStream);
- outs() << "NameStream: " << NameStreamIndex << '\n';
-
NameHashTable NameTable;
NameTable.load(Reader);
- outs() << "NameStreamSignature: ";
- outs().write_hex(NameTable.getSignature()) << '\n';
- outs() << "NameStreamVersion: " << NameTable.getHashVersion() << '\n';
- outs() << "Name Count: " << NameTable.getNameCount() << '\n';
+ P.printHex("Signature", NameTable.getSignature());
+ P.printNumber("Version", NameTable.getHashVersion());
+ P.printNumber("Name Count", NameTable.getNameCount());
+ ListScope L(P, "Names");
for (uint32_t ID : NameTable.name_ids()) {
- outs() << "Name: " << NameTable.getStringForID(ID) << '\n';
+ StringRef Str = NameTable.getStringForID(ID);
+ if (!Str.empty())
+ P.printString(Str);
}
}
+}
+static void dumpDbiStream(ScopedPrinter &P, PDBFile &File) {
DbiStream &DS = File.getPDBDbiStream();
- outs() << "Dbi Version: " << DS.getDbiVersion() << '\n';
- outs() << "Age: " << DS.getAge() << '\n';
- outs() << "Incremental Linking: " << DS.isIncrementallyLinked() << '\n';
- outs() << "Has CTypes: " << DS.hasCTypes() << '\n';
- outs() << "Is Stripped: " << DS.isStripped() << '\n';
- outs() << "Machine Type: " << DS.getMachineType() << '\n';
- outs() << "Number of Symbols: " << DS.getNumberOfSymbols() << '\n';
+
+ DictScope D(P, "DBI Stream");
+ P.printNumber("Dbi Version", DS.getDbiVersion());
+ P.printNumber("Age", DS.getAge());
+ P.printBoolean("Incremental Linking", DS.isIncrementallyLinked());
+ P.printBoolean("Has CTypes", DS.hasCTypes());
+ P.printBoolean("Is Stripped", DS.isStripped());
+ P.printObject("Machine Type", DS.getMachineType());
+ P.printNumber("Number of Symbols", DS.getNumberOfSymbols());
uint16_t Major = DS.getBuildMajorVersion();
uint16_t Minor = DS.getBuildMinorVersion();
- outs() << "Toolchain Version: " << Major << "." << Minor << '\n';
- outs() << "mspdb" << Major << Minor << ".dll version: " << Major << "."
- << Minor << "." << DS.getPdbDllVersion() << '\n';
+ P.printVersion("Toolchain Version", Major, Minor);
- outs() << "Modules: \n";
+ std::string DllName;
+ raw_string_ostream DllStream(DllName);
+ DllStream << "mspdb" << Major << Minor << ".dll version";
+ DllStream.flush();
+ P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion());
+
+ ListScope L(P, "Modules");
for (auto &Modi : DS.modules()) {
- outs() << Modi.Info.getModuleName() << '\n';
- outs().indent(4) << "Debug Stream Index: "
- << Modi.Info.getModuleStreamIndex() << '\n';
- outs().indent(4) << "Object File: " << Modi.Info.getObjFileName() << '\n';
- outs().indent(4) << "Num Files: " << Modi.Info.getNumberOfFiles() << '\n';
- outs().indent(4) << "Source File Name Idx: "
- << Modi.Info.getSourceFileNameIndex() << '\n';
- outs().indent(4) << "Pdb File Name Idx: "
- << Modi.Info.getPdbFilePathNameIndex() << '\n';
- outs().indent(4) << "Line Info Byte Size: "
- << Modi.Info.getLineInfoByteSize() << '\n';
- outs().indent(4) << "C13 Line Info Byte Size: "
- << Modi.Info.getC13LineInfoByteSize() << '\n';
- outs().indent(4) << "Symbol Byte Size: "
- << Modi.Info.getSymbolDebugInfoByteSize() << '\n';
- outs().indent(4) << "Type Server Index: " << Modi.Info.getTypeServerIndex()
- << '\n';
- outs().indent(4) << "Has EC Info: " << Modi.Info.hasECInfo() << '\n';
- outs().indent(4) << Modi.SourceFiles.size()
- << " Contributing Source Files: \n";
- for (auto File : Modi.SourceFiles) {
- outs().indent(8) << File << '\n';
- }
+ DictScope DD(P);
+ P.printString("Name", Modi.Info.getModuleName());
+ P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex());
+ P.printString("Object File Name", Modi.Info.getObjFileName());
+ P.printNumber("Num Files", Modi.Info.getNumberOfFiles());
+ P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex());
+ P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex());
+ P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize());
+ P.printNumber("C13 Line Info Byte Size",
+ Modi.Info.getC13LineInfoByteSize());
+ P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
+ P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
+ P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
+ std::string FileListName =
+ to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
+ ListScope LL(P, FileListName);
+ for (auto File : Modi.SourceFiles)
+ P.printString(File);
}
+}
+
+static void dumpTpiStream(ScopedPrinter &P, PDBFile &File) {
+ if (!opts::DumpTypeStream)
+ return;
+
+ DictScope D(P, "Type Info Stream");
TpiStream &Tpi = File.getPDBTpiStream();
- outs() << "TPI Version: " << Tpi.getTpiVersion() << '\n';
- outs() << "Record count: " << Tpi.NumTypeRecords() << '\n';
+ P.printNumber("TPI Version", Tpi.getTpiVersion());
+ P.printNumber("Record count", Tpi.NumTypeRecords());
+
+ if (!opts::DumpTpiRecordBytes)
+ return;
+
+ ListScope L(P, "Records");
for (auto &Type : Tpi.types()) {
- outs().indent(2) << "Kind: 0x" << Type.Leaf;
- outs().indent(2) << "Bytes: ";
- dumpBytes(outs(), Type.LeafData, 16, 24);
- outs() << '\n';
+ DictScope DD(P, "");
+ P.printHex("Kind", unsigned(Type.Leaf));
+ P.printBinaryBlock("Bytes", Type.LeafData);
}
}
+static void dumpStructure(RawSession &RS) {
+ PDBFile &File = RS.getPDBFile();
+ ScopedPrinter P(outs());
+
+ dumpFileHeaders(P, File);
+
+ dumpStreamSizes(P, File);
+
+ dumpStreamBlocks(P, File);
+
+ dumpStreamData(P, File);
+
+ dumpInfoStream(P, File);
+
+ dumpNamedStream(P, File, "/names");
+
+ dumpDbiStream(P, File);
+
+ dumpTpiStream(P, File);
+}
+
static void reportError(StringRef Path, PDB_ErrorCode Error) {
switch (Error) {
case PDB_ErrorCode::Success:
OpenPOWER on IntegriCloud