Reland "Use ScopedPrinter in llvm-pdbdump"

This reverts r268508 and reinstates r268506 with an additional cast from
TypeLeafKind to unsigned to allow conversion to HexNumber.

llvm-svn: 268517
This commit is contained in:
Reid Kleckner 2016-05-04 16:09:04 +00:00
parent 1a2b2f03e7
commit b034526853
3 changed files with 1426 additions and 1134 deletions

View File

@ -193,6 +193,12 @@ public:
startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
} }
template <typename... T> void printVersion(StringRef Label, T... Version) {
startLine() << Label << ": ";
printVersionInternal(Version...);
getOStream() << "\n";
}
template <typename T> void printList(StringRef Label, const T &List) { template <typename T> void printList(StringRef Label, const T &List) {
startLine() << Label << ": ["; startLine() << Label << ": [";
bool Comma = false; bool Comma = false;
@ -230,6 +236,8 @@ public:
startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n'; startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
} }
void printString(StringRef Value) { startLine() << Value << "\n"; }
void printString(StringRef Label, StringRef Value) { void printString(StringRef Label, StringRef Value) {
startLine() << Label << ": " << Value << "\n"; startLine() << Label << ": " << Value << "\n";
} }
@ -275,6 +283,10 @@ public:
printBinaryImpl(Label, StringRef(), V, true); printBinaryImpl(Label, StringRef(), V, true);
} }
template <typename T> void printObject(StringRef Label, const T &Value) {
startLine() << Label << ": " << Value << "\n";
}
raw_ostream &startLine() { raw_ostream &startLine() {
printIndent(); printIndent();
return OS; return OS;
@ -283,6 +295,16 @@ public:
raw_ostream &getOStream() { return OS; } raw_ostream &getOStream() { return OS; }
private: private:
template <typename T> void printVersionInternal(T Value) {
getOStream() << Value;
}
template <typename S, typename T, typename... TArgs>
void printVersionInternal(S Value, T Value2, TArgs... Args) {
getOStream() << Value << ".";
printVersionInternal(Value2, Args...);
}
template <typename T> template <typename T>
static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) { static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
return lhs.Name < rhs.Name; return lhs.Name < rhs.Name;
@ -304,6 +326,11 @@ ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
template<char Open, char Close> template<char Open, char Close>
struct DelimitedScope { struct DelimitedScope {
explicit DelimitedScope(ScopedPrinter &W) : W(W) {
W.startLine() << Open << '\n';
W.indent();
}
DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) { DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
W.startLine() << N; W.startLine() << N;
if (!N.empty()) if (!N.empty())

File diff suppressed because it is too large Load Diff

View File

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