diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h | 3 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp | 8 | ||||
-rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test | 61 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp | 30 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbutil/LinePrinter.cpp | 130 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbutil/LinePrinter.h | 16 |
6 files changed, 211 insertions, 37 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h index 4d3c569c3cd..4f6ad115e7d 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -13,6 +13,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/DebugInfo/MSF/IMSFFile.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MSFStreamLayout.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" @@ -85,6 +86,8 @@ public: ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; + msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const; + Error parseFileHeaders(); Error parseStreamData(); diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index a9597cdf4c4..4f6ebb0cb34 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -230,6 +230,14 @@ ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const { return ContainerLayout.DirectoryBlocks; } +MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const { + MSFStreamLayout Result; + auto Blocks = getStreamBlockList(StreamIdx); + Result.Blocks.assign(Blocks.begin(), Blocks.end()); + Result.Length = getStreamByteSize(StreamIdx); + return Result; +} + Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() { if (!Globals) { auto DbiS = getPDBDbiStream(); diff --git a/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test b/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test index d8510a1af73..0d57ddea015 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-raw-stream.test @@ -2,14 +2,20 @@ ; RUN: llvm-pdbutil bytes -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s ; RUN: llvm-pdbutil bytes -stream-data=1,100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BOTH %s +; RUN: llvm-pdbutil bytes -stream-data=1:10 %p/Inputs/empty.pdb | FileCheck --check-prefix=OFFSET %s +; RUN: llvm-pdbutil bytes -stream-data=1@20 %p/Inputs/empty.pdb | FileCheck --check-prefix=SIZED %s +; RUN: llvm-pdbutil bytes -stream-data=1:8@20 %p/Inputs/empty.pdb | FileCheck --check-prefix=SLICE %s +; RUN: llvm-pdbutil bytes -stream-data=1:0x8@0x14 %p/Inputs/empty.pdb | FileCheck --check-prefix=SLICE %s +; RUN: llvm-pdbutil bytes -stream-data=2:4050@100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=DISCONTINUITY %s + STREAM: Stream Data STREAM-NEXT: ============================================================ -STREAM-NEXT: Stream 1 (118 bytes): PDB Stream +STREAM-NEXT: Stream 1: PDB Stream (dumping 118 / 118 bytes) STREAM-NEXT: Data ( -STREAM-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| -STREAM-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| -STREAM-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| -STREAM-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| +STREAM-NEXT: 13000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| +STREAM-NEXT: 13020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| +STREAM-NEXT: 13040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| +STREAM-NEXT: 13060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| STREAM-NEXT: ) INVALIDSTREAM: Stream Data @@ -18,11 +24,46 @@ INVALIDSTREAM-NEXT: Stream 100: Not present BOTH: Stream Data BOTH-NEXT: ============================================================ -BOTH-NEXT: Stream 1 (118 bytes): PDB Stream +BOTH-NEXT: Stream 1: PDB Stream (dumping 118 / 118 bytes) BOTH-NEXT: Data ( -BOTH-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| -BOTH-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| -BOTH-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| -BOTH-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| +BOTH-NEXT: 13000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| +BOTH-NEXT: 13020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| +BOTH-NEXT: 13040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| +BOTH-NEXT: 13060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| BOTH-NEXT: ) BOTH-NEXT: Stream 100: Not present + +OFFSET: Stream Data +OFFSET-NEXT: ============================================================ +OFFSET-NEXT: Stream 1: PDB Stream (dumping 108 / 118 bytes) +OFFSET-NEXT: Data ( +OFFSET-NEXT: 1300A: 00000B35 564186A0 A249896F 9988FAE5 2FF02200 00002F4C 696E6B49 6E666F00 |...5VA...I.o..../.".../LinkInfo.| +OFFSET-NEXT: 1302A: 2F6E616D 6573002F 7372632F 68656164 6572626C 6F636B00 03000000 06000000 |/names./src/headerblock.........| +OFFSET-NEXT: 1304A: 01000000 1A000000 00000000 11000000 09000000 0A000000 0D000000 00000000 |................................| +OFFSET-NEXT: 1306A: 05000000 00000000 41913201 |........A.2.| +OFFSET-NEXT: ) + +SIZED: Stream Data +SIZED-NEXT: ============================================================ +SIZED-NEXT: Stream 1: PDB Stream (dumping 20 / 118 bytes) +SIZED-NEXT: Data ( +SIZED-NEXT: 13000: 942E3101 E207E554 01000000 0B355641 86A0A249 |..1....T.....5VA...I| +SIZED-NEXT: ) + +SLICE: Stream Data +SLICE-NEXT: ============================================================ +SLICE-NEXT: Stream 1: PDB Stream (dumping 20 / 118 bytes) +SLICE-NEXT: Data ( +SLICE-NEXT: 13008: 01000000 0B355641 86A0A249 896F9988 FAE52FF0 |.....5VA...I.o..../.| +SLICE-NEXT: ) + +DISCONTINUITY: Stream Data +DISCONTINUITY-NEXT: ============================================================ +DISCONTINUITY-NEXT: Stream 2: TPI Stream (dumping 100 / 5,392 bytes) +DISCONTINUITY-NEXT: Data ( +DISCONTINUITY-NEXT: 12FD2: 65537472 75637455 73616765 00F10215 03000480 00002000 654C6F63 616C5573 |eStructUsage.......... .eLocalUs| +DISCONTINUITY-NEXT: 12FF2: 61676500 F2F10215 03000480 0000 |age...........| +DISCONTINUITY-NEXT: -------------------------------------------------<discontinuity>-------------------------------------------------- +DISCONTINUITY-NEXT: 11000: 40006550 726F7065 72747955 73616765 00F3F2F1 02150300 04800000 80006545 |@.ePropertyUsage..............eE| +DISCONTINUITY-NEXT: 11020: 76656E74 55736167 6500F2F1 02150300 04800000 0001 |ventUsage.............| +DISCONTINUITY-NEXT: ) diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp index af56092ce63..123c55d2072 100644 --- a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp @@ -132,36 +132,12 @@ void BytesOutputStyle::dumpStreamBytes() { auto Specs = parseStreamSpecs(P); for (const auto &Spec : Specs) { - uint32_t End = 0; - AutoIndent Indent(P); - if (Spec.SI >= File.getNumStreams()) { - P.formatLine("Stream {0}: Not present", Spec.SI); - continue; - } - - auto S = MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), Spec.SI, File.getAllocator()); - if (!S) { - P.NewLine(); + if (Spec.SI >= StreamPurposes.size()) { P.formatLine("Stream {0}: Not present", Spec.SI); continue; } - - if (Spec.Size == 0) - End = S->getLength(); - else - End = std::min(Spec.Begin + Spec.Size, S->getLength()); - uint32_t Size = End - Spec.Begin; - - P.formatLine("Stream {0} ({1:N} bytes): {2}", Spec.SI, S->getLength(), - StreamPurposes[Spec.SI]); - AutoIndent Indent2(P); - - BinaryStreamReader R(*S); - ArrayRef<uint8_t> StreamData; - Err(R.readBytes(StreamData, S->getLength())); - StreamData = StreamData.slice(Spec.Begin, Size); - P.formatBinary("Data", StreamData, Spec.Begin); + P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI], + Spec.Begin, Spec.Size); } } diff --git a/llvm/tools/llvm-pdbutil/LinePrinter.cpp b/llvm/tools/llvm-pdbutil/LinePrinter.cpp index 3e736d90426..a5f48f05859 100644 --- a/llvm/tools/llvm-pdbutil/LinePrinter.cpp +++ b/llvm/tools/llvm-pdbutil/LinePrinter.cpp @@ -12,13 +12,21 @@ #include "llvm-pdbutil.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MSFStreamLayout.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/UDTLayout.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Regex.h" #include <algorithm> using namespace llvm; +using namespace llvm::msf; using namespace llvm::pdb; namespace { @@ -120,6 +128,128 @@ void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, OS << ")"; } +namespace { +struct Run { + Run() = default; + explicit Run(uint32_t Block) : Block(Block) {} + uint32_t Block = 0; + uint32_t ByteLen = 0; +}; +} // namespace + +static std::vector<Run> computeBlockRuns(uint32_t BlockSize, + const msf::MSFStreamLayout &Layout) { + std::vector<Run> Runs; + if (Layout.Length == 0) + return Runs; + + ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks; + assert(!Blocks.empty()); + uint32_t StreamBytesRemaining = Layout.Length; + Runs.emplace_back(Blocks[0]); + while (!Blocks.empty()) { + Run *CurrentRun = &Runs.back(); + uint32_t NextBlock = Blocks.front(); + if (NextBlock < CurrentRun->Block || (NextBlock - CurrentRun->Block > 1)) { + Runs.emplace_back(NextBlock); + CurrentRun = &Runs.back(); + } + + uint32_t Used = std::min(BlockSize, StreamBytesRemaining); + CurrentRun->ByteLen += Used; + StreamBytesRemaining -= Used; + Blocks = Blocks.drop_front(); + } + return Runs; +} + +static std::pair<Run, uint32_t> findRun(uint32_t Offset, ArrayRef<Run> Runs) { + for (const auto &R : Runs) { + if (Offset < R.ByteLen) + return std::make_pair(R, Offset); + Offset -= R.ByteLen; + } + llvm_unreachable("Invalid offset!"); +} + +void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File, + uint32_t StreamIdx, + StringRef StreamPurpose, uint32_t Offset, + uint32_t Size) { + if (StreamIdx >= File.getNumStreams()) { + formatLine("Stream {0}: Not present", StreamIdx); + return; + } + if (Size + Offset > File.getStreamByteSize(StreamIdx)) { + formatLine( + "Stream {0}: Invalid offset and size, range out of stream bounds", + StreamIdx); + return; + } + + auto S = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), StreamIdx, File.getAllocator()); + if (!S) { + NewLine(); + formatLine("Stream {0}: Not present", StreamIdx); + return; + } + + uint32_t End = + (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength()); + Size = End - Offset; + + formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx, + StreamPurpose, Size, S->getLength()); + AutoIndent Indent(*this); + BinaryStreamRef Slice(*S); + Slice = Slice.keep_front(Offset + Size); + BinaryStreamReader Reader(Slice); + consumeError(Reader.skip(Offset)); + auto Layout = File.getStreamLayout(StreamIdx); + formatMsfStreamData(Label, File, Layout, Reader); +} + +void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File, + const msf::MSFStreamLayout &Stream, + BinarySubstreamRef Substream) { + BinaryStreamReader Reader(Substream.StreamData); + + consumeError(Reader.skip(Substream.Offset)); + formatMsfStreamData(Label, File, Stream, Reader); +} + +void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File, + const msf::MSFStreamLayout &Stream, + BinaryStreamReader &Reader) { + auto Runs = computeBlockRuns(File.getBlockSize(), Stream); + + NewLine(); + OS << Label << " ("; + while (Reader.bytesRemaining() > 0) { + OS << "\n"; + + Run FoundRun; + uint32_t RunOffset; + std::tie(FoundRun, RunOffset) = findRun(Reader.getOffset(), Runs); + assert(FoundRun.ByteLen >= RunOffset); + uint32_t Len = FoundRun.ByteLen - RunOffset; + Len = std::min(Len, Reader.bytesRemaining()); + uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset; + ArrayRef<uint8_t> Data; + consumeError(Reader.readBytes(Data, Len)); + OS << format_bytes_with_ascii(Data, Base, 32, 4, + CurrentIndent + IndentSpaces, true); + if (Reader.bytesRemaining() > 0) { + NewLine(); + OS << formatv(" {0}", + fmt_align("<discontinuity>", AlignStyle::Center, 114, '-')); + } + } + NewLine(); + OS << ")"; +} + bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) { if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters)) return true; diff --git a/llvm/tools/llvm-pdbutil/LinePrinter.h b/llvm/tools/llvm-pdbutil/LinePrinter.h index 9293c49132d..7ce410d10c0 100644 --- a/llvm/tools/llvm-pdbutil/LinePrinter.h +++ b/llvm/tools/llvm-pdbutil/LinePrinter.h @@ -13,6 +13,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" @@ -20,9 +21,14 @@ #include <list> namespace llvm { +class BinaryStreamReader; +namespace msf { +class MSFStreamLayout; +} // namespace msf namespace pdb { class ClassLayout; +class PDBFile; class LinePrinter { friend class WithColor; @@ -48,6 +54,16 @@ public: void formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint64_t BaseAddr, uint32_t StartOffset); + void formatMsfStreamData(StringRef Label, PDBFile &File, uint32_t StreamIdx, + StringRef StreamPurpose, uint32_t Offset, + uint32_t Size); + void formatMsfStreamData(StringRef Label, PDBFile &File, + const msf::MSFStreamLayout &Stream, + BinarySubstreamRef Substream); + void formatMsfStreamData(StringRef Label, PDBFile &File, + const msf::MSFStreamLayout &Stream, + BinaryStreamReader &Reader); + bool hasColor() const { return UseColor; } raw_ostream &getStream() { return OS; } int getIndentLevel() const { return CurrentIndent; } |