[pdb] Print out some more info when dumping a raw stream.

We have various command line options that print the type of a
stream, the size of a stream, etc but nowhere that it can all be
viewed together.

Since a previous patch introduced the ability to dump the bytes
of a stream, this seems like a good place to present a full view
of the stream's properties including its size, what kind of data
it represents, and the blocks it occupies.  So I added the
ability to print that information to the -stream-data command
line option.

llvm-svn: 281077
This commit is contained in:
Zachary Turner 2016-09-09 19:00:49 +00:00
parent c236e5a0f1
commit 36efbfa6d8
4 changed files with 60 additions and 26 deletions

View File

@ -200,6 +200,10 @@ uint32_t MappedBlockStream::getLength() const { return StreamLayout.Length; }
bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size, bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const { ArrayRef<uint8_t> &Buffer) const {
if (Size == 0) {
Buffer = ArrayRef<uint8_t>();
return true;
}
// Attempt to fulfill the request with a reference directly into the stream. // Attempt to fulfill the request with a reference directly into the stream.
// This can work even if the request crosses a block boundary, provided that // This can work even if the request crosses a block boundary, provided that
// all subsequent blocks are contiguous. For example, a 10k read with a 4k // all subsequent blocks are contiguous. For example, a 10k read with a 4k

View File

@ -2,16 +2,22 @@
; RUN: not llvm-pdbdump raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s ; RUN: not llvm-pdbdump raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
STREAM1: Stream Data { STREAM1: Stream Data {
STREAM1-NEXT: Stream 1 ( STREAM1-NEXT: Stream {
STREAM1-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 |..1....T.....5VA| STREAM1-NEXT: Index: 1
STREAM1-NEXT: 0010: 86A0A249 896F9988 FAE52FF0 22000000 |...I.o..../."...| STREAM1-NEXT: Type: PDB Stream
STREAM1-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 |/LinkInfo./names| STREAM1-NEXT: Size: 118
STREAM1-NEXT: 0030: 002F7372 632F6865 61646572 626C6F63 |./src/headerbloc| STREAM1-NEXT: Blocks: [19]
STREAM1-NEXT: 0040: 6B000300 00000600 00000100 00001A00 |k...............| STREAM1-NEXT: Data (
STREAM1-NEXT: 0050: 00000000 00001100 00000900 00000A00 |................| STREAM1-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 |..1....T.....5VA|
STREAM1-NEXT: 0060: 00000D00 00000000 00000500 00000000 |................| STREAM1-NEXT: 0010: 86A0A249 896F9988 FAE52FF0 22000000 |...I.o..../."...|
STREAM1-NEXT: 0070: 00004191 3201 |..A.2.| STREAM1-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 |/LinkInfo./names|
STREAM1-NEXT: ) STREAM1-NEXT: 0030: 002F7372 632F6865 61646572 626C6F63 |./src/headerbloc|
STREAM1-NEXT: 0040: 6B000300 00000600 00000100 00001A00 |k...............|
STREAM1-NEXT: 0050: 00000000 00001100 00000900 00000A00 |................|
STREAM1-NEXT: 0060: 00000D00 00000000 00000500 00000000 |................|
STREAM1-NEXT: 0070: 00004191 3201 |..A.2.|
STREAM1-NEXT: )
STREAM1-NEXT: }
STREAM1-NEXT: } STREAM1-NEXT: }
INVALIDSTREAM: Native PDB Error: The specified stream could not be loaded. INVALIDSTREAM: Native PDB Error: The specified stream could not be loaded.

View File

@ -157,9 +157,9 @@ Error LLVMOutputStyle::dumpFileHeaders() {
return Error::success(); return Error::success();
} }
Error LLVMOutputStyle::dumpStreamSummary() { void LLVMOutputStyle::discoverStreamPurposes() {
if (!opts::raw::DumpStreamSummary) if (!StreamPurposes.empty())
return Error::success(); return;
// It's OK if we fail to load some of these streams, we still attempt to print // It's OK if we fail to load some of these streams, we still attempt to print
// what we can. // what we can.
@ -168,7 +168,6 @@ Error LLVMOutputStyle::dumpStreamSummary() {
auto Ipi = File.getPDBIpiStream(); auto Ipi = File.getPDBIpiStream();
auto Info = File.getPDBInfoStream(); auto Info = File.getPDBInfoStream();
ListScope L(P, "Streams");
uint32_t StreamCount = File.getNumStreams(); uint32_t StreamCount = File.getNumStreams();
std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams; std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
std::unordered_map<uint16_t, std::string> NamedStreams; std::unordered_map<uint16_t, std::string> NamedStreams;
@ -185,9 +184,8 @@ Error LLVMOutputStyle::dumpStreamSummary() {
} }
} }
StreamPurposes.resize(StreamCount);
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
std::string Label("Stream ");
Label += to_string(StreamIdx);
std::string Value; std::string Value;
if (StreamIdx == OldMSFDirectory) if (StreamIdx == OldMSFDirectory)
Value = "Old MSF Directory"; Value = "Old MSF Directory";
@ -258,11 +256,7 @@ Error LLVMOutputStyle::dumpStreamSummary() {
Value = "???"; Value = "???";
} }
} }
Value = "[" + Value + "]"; StreamPurposes[StreamIdx] = Value;
Value =
Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
P.printString(Label, Value);
} }
// Consume errors from missing streams. // Consume errors from missing streams.
@ -274,6 +268,27 @@ Error LLVMOutputStyle::dumpStreamSummary() {
consumeError(Ipi.takeError()); consumeError(Ipi.takeError());
if (!Info) if (!Info)
consumeError(Info.takeError()); consumeError(Info.takeError());
}
Error LLVMOutputStyle::dumpStreamSummary() {
if (!opts::raw::DumpStreamSummary)
return Error::success();
discoverStreamPurposes();
uint32_t StreamCount = File.getNumStreams();
ListScope L(P, "Streams");
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
std::string Label("Stream ");
Label += to_string(StreamIdx);
std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
Value += to_string(File.getStreamByteSize(StreamIdx));
Value += " bytes)";
P.printString(Label, Value);
}
P.flush(); P.flush();
return Error::success(); return Error::success();
@ -377,6 +392,8 @@ Error LLVMOutputStyle::dumpStreamBytes() {
if (opts::raw::DumpStreamData.empty()) if (opts::raw::DumpStreamData.empty())
return Error::success(); return Error::success();
discoverStreamPurposes();
DictScope D(P, "Stream Data"); DictScope D(P, "Stream Data");
for (uint32_t SI : opts::raw::DumpStreamData) { for (uint32_t SI : opts::raw::DumpStreamData) {
if (SI >= File.getNumStreams()) if (SI >= File.getNumStreams())
@ -386,15 +403,19 @@ Error LLVMOutputStyle::dumpStreamBytes() {
File.getMsfBuffer(), SI); File.getMsfBuffer(), SI);
if (!S) if (!S)
continue; continue;
DictScope DD(P, "Stream");
P.printNumber("Index", SI);
P.printString("Type", StreamPurposes[SI]);
P.printNumber("Size", S->getLength());
auto Blocks = File.getMsfLayout().StreamMap[SI];
P.printList("Blocks", Blocks);
StreamReader R(*S); StreamReader R(*S);
ArrayRef<uint8_t> StreamData; ArrayRef<uint8_t> StreamData;
if (auto EC = R.readBytes(StreamData, S->getLength())) if (auto EC = R.readBytes(StreamData, S->getLength()))
return EC; return EC;
std::string Label; P.printBinaryBlock("Data", StreamData);
llvm::raw_string_ostream Stream(Label);
Stream << "Stream " << SI;
Stream.flush();
P.printBinaryBlock(Label, StreamData);
} }
return Error::success(); return Error::success();
} }

View File

@ -25,6 +25,8 @@ public:
Error dump() override; Error dump() override;
private: private:
void discoverStreamPurposes();
Error dumpFileHeaders(); Error dumpFileHeaders();
Error dumpStreamSummary(); Error dumpStreamSummary();
Error dumpFreePageMap(); Error dumpFreePageMap();
@ -47,6 +49,7 @@ private:
PDBFile &File; PDBFile &File;
ScopedPrinter P; ScopedPrinter P;
codeview::CVTypeDumper Dumper; codeview::CVTypeDumper Dumper;
std::vector<std::string> StreamPurposes;
}; };
} }
} }