forked from OSchip/llvm-project
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:
parent
1a2b2f03e7
commit
b034526853
|
@ -193,6 +193,12 @@ public:
|
|||
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) {
|
||||
startLine() << Label << ": [";
|
||||
bool Comma = false;
|
||||
|
@ -230,6 +236,8 @@ public:
|
|||
startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
|
||||
}
|
||||
|
||||
void printString(StringRef Value) { startLine() << Value << "\n"; }
|
||||
|
||||
void printString(StringRef Label, StringRef Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
@ -275,6 +283,10 @@ public:
|
|||
printBinaryImpl(Label, StringRef(), V, true);
|
||||
}
|
||||
|
||||
template <typename T> void printObject(StringRef Label, const T &Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
raw_ostream &startLine() {
|
||||
printIndent();
|
||||
return OS;
|
||||
|
@ -283,6 +295,16 @@ public:
|
|||
raw_ostream &getOStream() { return OS; }
|
||||
|
||||
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>
|
||||
static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
|
||||
return lhs.Name < rhs.Name;
|
||||
|
@ -304,6 +326,11 @@ ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
|
|||
|
||||
template<char Open, char Close>
|
||||
struct DelimitedScope {
|
||||
explicit DelimitedScope(ScopedPrinter &W) : W(W) {
|
||||
W.startLine() << Open << '\n';
|
||||
W.indent();
|
||||
}
|
||||
|
||||
DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
|
||||
W.startLine() << N;
|
||||
if (!N.empty())
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,85 +157,61 @@ 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();
|
||||
P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
|
||||
P.printNumber("NumStreams", File.getNumStreams());
|
||||
}
|
||||
|
||||
if (opts::DumpHeaders) {
|
||||
outs() << "DirectoryBlocks: [";
|
||||
for (const auto &DirectoryBlockAddr : DirectoryBlocks) {
|
||||
if (&DirectoryBlockAddr != &DirectoryBlocks.front())
|
||||
outs() << ", ";
|
||||
outs() << DirectoryBlockAddr;
|
||||
}
|
||||
outs() << "]\n";
|
||||
}
|
||||
static void dumpStreamSizes(ScopedPrinter &P, PDBFile &File) {
|
||||
if (!opts::DumpStreamSizes)
|
||||
return;
|
||||
|
||||
if (opts::DumpHeaders)
|
||||
outs() << "NumStreams: " << File.getNumStreams() << '\n';
|
||||
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';
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
std::string Name("Stream ");
|
||||
Name += to_string(StreamIdx);
|
||||
P.printNumber(Name, File.getStreamByteSize(StreamIdx));
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
|
||||
DumpStreamNum >= StreamCount)
|
||||
return;
|
||||
|
||||
uint32_t StreamBytesRead = 0;
|
||||
uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum);
|
||||
auto StreamBlocks = File.getStreamBlockList(DumpStreamNum);
|
||||
|
@ -245,87 +229,133 @@ static void dumpStructure(RawSession &RS) {
|
|||
outs() << StreamBlockData;
|
||||
StreamBytesRead += StreamBlockData.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dumpInfoStream(ScopedPrinter &P, PDBFile &File) {
|
||||
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");
|
||||
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();
|
||||
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:
|
||||
|
|
Loading…
Reference in New Issue