[llvm] r306141 - [llvm-pdbutil] Add a function for formatting MSF data.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 23 11:52:14 PDT 2017


Author: zturner
Date: Fri Jun 23 13:52:13 2017
New Revision: 306141

URL: http://llvm.org/viewvc/llvm-project?rev=306141&view=rev
Log:
[llvm-pdbutil] Add a function for formatting MSF data.

The goal here is to make it possible to display absolute
file offsets when dumping byets from an MSF.  The problem is
that when dumping bytes from an MSF, often the bytes will
cross a block boundary and encounter a discontinuity.  We
can't use the normal formatBinary() function for this because
this would just treat the sequence as entirely ascending, and
not account out-of-order blocks.

This patch adds a formatMsfData() function to our printer, and
then uses this function to improve the output of the -stream-data
command line option for dumping bytes from a particular stream.

Test coverage is also expanded to make sure to include all possible
scenarios of offsets, sizes, and crossing block boundaries.

Modified:
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFile.h
    llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp
    llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test
    llvm/trunk/tools/llvm-pdbutil/BytesOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp
    llvm/trunk/tools/llvm-pdbutil/LinePrinter.h

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFile.h?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFile.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFile.h Fri Jun 23 13:52:13 2017
@@ -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();
 

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp Fri Jun 23 13:52:13 2017
@@ -230,6 +230,14 @@ ArrayRef<support::ulittle32_t> PDBFile::
   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();

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test Fri Jun 23 13:52:13 2017
@@ -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 at 20 %p/Inputs/empty.pdb | FileCheck --check-prefix=SIZED %s
+; RUN: llvm-pdbutil bytes -stream-data=1:8 at 20 %p/Inputs/empty.pdb | FileCheck --check-prefix=SLICE %s
+; RUN: llvm-pdbutil bytes -stream-data=1:0x8 at 0x14 %p/Inputs/empty.pdb | FileCheck --check-prefix=SLICE %s
+; RUN: llvm-pdbutil bytes -stream-data=2:4050 at 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 pr
 
 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:     )

Modified: llvm/trunk/tools/llvm-pdbutil/BytesOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/BytesOutputStyle.cpp?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/BytesOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/BytesOutputStyle.cpp Fri Jun 23 13:52:13 2017
@@ -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);
   }
 }

Modified: llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp Fri Jun 23 13:52:13 2017
@@ -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
   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;

Modified: llvm/trunk/tools/llvm-pdbutil/LinePrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LinePrinter.h?rev=306141&r1=306140&r2=306141&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LinePrinter.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/LinePrinter.h Fri Jun 23 13:52:13 2017
@@ -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; }




More information about the llvm-commits mailing list