OSDN Git Service

[pdb] Finish conversion to zero copy pdb access.
authorZachary Turner <zturner@google.com>
Sat, 28 May 2016 05:21:57 +0000 (05:21 +0000)
committerZachary Turner <zturner@google.com>
Sat, 28 May 2016 05:21:57 +0000 (05:21 +0000)
This converts remaining uses of ByteStream, which was still
left in the symbol stream and type stream, to using the new
StreamInterface zero-copy classes.

RecordIterator is finally deleted, so this is the only way left
now.  Additionally, more error checking is added when iterating
the various streams.

With this, the transition to zero copy pdb access is complete.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271101 91177308-0d34-0410-b5e6-96231b3b80d8

33 files changed:
include/llvm/DebugInfo/CodeView/ByteStream.h
include/llvm/DebugInfo/CodeView/CVRecord.h [new file with mode: 0644]
include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
include/llvm/DebugInfo/CodeView/RecordIterator.h [deleted file]
include/llvm/DebugInfo/CodeView/StreamArray.h
include/llvm/DebugInfo/CodeView/StreamInterface.h
include/llvm/DebugInfo/CodeView/StreamReader.h
include/llvm/DebugInfo/CodeView/StreamRef.h
include/llvm/DebugInfo/CodeView/SymbolDumper.h
include/llvm/DebugInfo/CodeView/SymbolRecord.h
include/llvm/DebugInfo/CodeView/TypeDumper.h
include/llvm/DebugInfo/CodeView/TypeRecord.h
include/llvm/DebugInfo/CodeView/TypeStream.h [deleted file]
include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h
include/llvm/DebugInfo/PDB/Raw/ModInfo.h
include/llvm/DebugInfo/PDB/Raw/ModStream.h
include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
include/llvm/DebugInfo/PDB/Raw/TpiStream.h
lib/DebugInfo/CodeView/ByteStream.cpp
lib/DebugInfo/CodeView/StreamReader.cpp
lib/DebugInfo/CodeView/SymbolDumper.cpp
lib/DebugInfo/CodeView/TypeDumper.cpp
lib/DebugInfo/CodeView/TypeStreamMerger.cpp
lib/DebugInfo/PDB/Raw/ModInfo.cpp
lib/DebugInfo/PDB/Raw/ModStream.cpp
lib/DebugInfo/PDB/Raw/PublicsStream.cpp
lib/DebugInfo/PDB/Raw/SymbolStream.cpp
lib/DebugInfo/PDB/Raw/TpiStream.cpp
tools/llvm-pdbdump/llvm-pdbdump.cpp
tools/llvm-readobj/COFFDumper.cpp

index ba16232..44fcbaa 100644 (file)
@@ -24,16 +24,9 @@ class StreamReader;
 class ByteStream : public StreamInterface {
 public:
   ByteStream();
-  explicit ByteStream(MutableArrayRef<uint8_t> Data);
+  explicit ByteStream(ArrayRef<uint8_t> Data);
   ~ByteStream() override;
 
-  void reset();
-
-  void load(uint32_t Length);
-  Error load(StreamReader &Reader, uint32_t Length);
-
-  Error readBytes(uint32_t Offset,
-                  MutableArrayRef<uint8_t> Buffer) const override;
   Error readBytes(uint32_t Offset, uint32_t Size,
                   ArrayRef<uint8_t> &Buffer) const override;
 
@@ -43,8 +36,7 @@ public:
   StringRef str() const;
 
 private:
-  MutableArrayRef<uint8_t> Data;
-  std::unique_ptr<uint8_t[]> Ownership;
+  ArrayRef<uint8_t> Data;
 };
 
 } // end namespace pdb
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
new file mode 100644 (file)
index 0000000..f6736dd
--- /dev/null
@@ -0,0 +1,47 @@
+//===- RecordIterator.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace codeview {
+
+template <typename Kind> struct CVRecord {
+  uint32_t Length;
+  Kind Type;
+  ArrayRef<uint8_t> Data;
+};
+
+template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
+  Error operator()(const StreamInterface &Stream, uint32_t &Len,
+                   CVRecord<Kind> &Item) const {
+    const RecordPrefix *Prefix = nullptr;
+    StreamReader Reader(Stream);
+    if (auto EC = Reader.readObject(Prefix))
+      return EC;
+    Item.Length = Prefix->RecordLen;
+    Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
+    if (auto EC = Reader.readBytes(Item.Data, Item.Length - 2))
+      return EC;
+    Len = Prefix->RecordLen + 2;
+    return Error::success();
+  }
+};
+}
+}
+
+#endif
index febd9a0..7c88956 100644 (file)
@@ -10,8 +10,8 @@
 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
 #define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
 
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
 #include "llvm/Support/ErrorOr.h"
@@ -72,8 +72,8 @@ public:
   }
 
   /// Visits the symbol records in Data. Sets the error flag on parse failures.
-  void visitSymbolStream(ArrayRef<uint8_t> Data) {
-    for (const auto &I : makeSymbolRange(Data, &HadError)) {
+  void visitSymbolStream(const CVSymbolArray &Symbols) {
+    for (const auto &I : Symbols) {
       visitSymbolRecord(I);
       if (hadError())
         break;
index 6d26090..0e21bfc 100644 (file)
 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
 #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
 
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 #include "llvm/Support/ErrorOr.h"
 
 namespace llvm {
@@ -81,8 +80,8 @@ public:
   }
 
   /// Visits the type records in Data. Sets the error flag on parse failures.
-  void visitTypeStream(ArrayRef<uint8_t> Data) {
-    for (const auto &I : makeTypeRange(Data, &HadError)) {
+  void visitTypeStream(const CVTypeArray &Types) {
+    for (const auto &I : Types) {
       visitTypeRecord(I);
       if (hadError())
         break;
diff --git a/include/llvm/DebugInfo/CodeView/RecordIterator.h b/include/llvm/DebugInfo/CodeView/RecordIterator.h
deleted file mode 100644 (file)
index a8073ea..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-//===- RecordIterator.h -----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
-#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/CodeView/StreamInterface.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/Support/Endian.h"
-
-namespace llvm {
-namespace codeview {
-
-template <typename Kind> struct CVRecord {
-  uint32_t Length;
-  Kind Type;
-  ArrayRef<uint8_t> Data;
-};
-
-template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
-  uint32_t operator()(const StreamInterface &Stream,
-                      CVRecord<Kind> &Item) const {
-    const RecordPrefix *Prefix = nullptr;
-    StreamReader Reader(Stream);
-    if (auto EC = Reader.readObject(Prefix)) {
-      consumeError(std::move(EC));
-      return 0;
-    }
-    Item.Length = Prefix->RecordLen;
-    Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
-    if (auto EC = Reader.readBytes(Item.Length - 2, Item.Data)) {
-      consumeError(std::move(EC));
-      return 0;
-    }
-    return Prefix->RecordLen + 2;
-  }
-};
-
-// A const input iterator interface to the CodeView record stream.
-template <typename Kind> class RecordIterator {
-public:
-
-  explicit RecordIterator(const ArrayRef<uint8_t> &RecordBytes, bool *HadError)
-      : HadError(HadError), Data(RecordBytes), AtEnd(false) {
-    next(); // Prime the pump
-  }
-
-  RecordIterator() : HadError(nullptr), AtEnd(true) {}
-
-  // For iterators to compare equal, they must both point at the same record
-  // in the same data stream, or they must both be at the end of a stream.
-  friend bool operator==(const RecordIterator<Kind> &lhs,
-                         const RecordIterator<Kind> &rhs) {
-    return (lhs.Data.begin() == rhs.Data.begin()) || (lhs.AtEnd && rhs.AtEnd);
-  }
-
-  friend bool operator!=(const RecordIterator<Kind> &lhs,
-                         const RecordIterator<Kind> &rhs) {
-    return !(lhs == rhs);
-  }
-
-  const CVRecord<Kind> &operator*() const {
-    assert(!AtEnd);
-    return Current;
-  }
-
-  const CVRecord<Kind> *operator->() const {
-    assert(!AtEnd);
-    return &Current;
-  }
-
-  RecordIterator<Kind> &operator++() {
-    next();
-    return *this;
-  }
-
-  RecordIterator<Kind> operator++(int) {
-    RecordIterator<Kind> Original = *this;
-    ++*this;
-    return Original;
-  }
-
-private:
-  void next() {
-    assert(!AtEnd && "Attempted to advance more than one past the last rec");
-    if (Data.empty()) {
-      // We've advanced past the last record.
-      AtEnd = true;
-      return;
-    }
-
-    // FIXME: Use consumeObject when it deals in ArrayRef<uint8_t>.
-    if (Data.size() < sizeof(RecordPrefix))
-      return parseError();
-    const auto *Rec = reinterpret_cast<const RecordPrefix *>(Data.data());
-    Data = Data.drop_front(sizeof(RecordPrefix));
-
-    Current.Length = Rec->RecordLen;
-    Current.Type = static_cast<Kind>(uint16_t(Rec->RecordKind));
-    size_t RecLen = Current.Length - 2;
-    if (RecLen > Data.size())
-      return parseError();
-    Current.Data = Data.slice(0, RecLen);
-
-    // The next record starts immediately after this one.
-    Data = Data.drop_front(Current.Data.size());
-
-    // FIXME: The stream contains LF_PAD bytes that we need to ignore, but those
-    // are typically included in LeafData. We may need to call skipPadding() if
-    // we ever find a record that doesn't count those bytes.
-
-    return;
-  }
-
-  void parseError() {
-    if (HadError)
-      *HadError = true;
-  }
-
-  bool *HadError;
-  ArrayRef<uint8_t> Data;
-  CVRecord<Kind> Current;
-  bool AtEnd;
-};
-
-template <typename Kind>
-inline iterator_range<RecordIterator<Kind>>
-makeRecordRange(ArrayRef<uint8_t> Data, bool *HadError) {
-  return make_range(RecordIterator<Kind>(Data, HadError), RecordIterator<Kind>());
-}
-}
-}
-
-#endif
index 7e4296c..23e475d 100644 (file)
@@ -11,6 +11,7 @@
 #define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H
 
 #include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/Support/Error.h"
 
 #include <functional>
 #include <type_traits>
@@ -25,8 +26,11 @@ namespace codeview {
 /// value type.
 template <typename T> struct VarStreamArrayExtractor {
   // Method intentionally deleted.  You must provide an explicit specialization
-  // with the following method implemented.
-  uint32_t operator()(const StreamInterface &Stream, T &t) const = delete;
+  // with the following method implemented.  On output return `Len` should
+  // contain the number of bytes to consume from the stream, and `Item` should
+  // be initialized with the proper value.
+  Error operator()(const StreamInterface &Stream, uint32_t &Len,
+                   T &Item) const = delete;
 };
 
 /// VarStreamArray represents an array of variable length records backed by a
@@ -52,7 +56,9 @@ public:
 
   VarStreamArray(StreamRef Stream) : Stream(Stream) {}
 
-  Iterator begin() const { return Iterator(*this); }
+  Iterator begin(bool *HadError = nullptr) const {
+    return Iterator(*this, HadError);
+  }
 
   Iterator end() const { return Iterator(); }
 
@@ -65,11 +71,20 @@ template <typename ValueType, typename Extractor> class VarStreamArrayIterator {
   typedef VarStreamArray<ValueType, Extractor> ArrayType;
 
 public:
-  VarStreamArrayIterator(const ArrayType &Array)
-      : Array(&Array), IterRef(Array.Stream) {
-    ThisLen = Extract(IterRef, ThisValue);
+  VarStreamArrayIterator(const ArrayType &Array, bool *HadError = nullptr)
+      : Array(&Array), IterRef(Array.Stream), HasError(false),
+        HadError(HadError) {
+    auto EC = Extract(IterRef, ThisLen, ThisValue);
+    if (EC) {
+      consumeError(std::move(EC));
+      HasError = true;
+      if (HadError)
+        *HadError = true;
+    }
   }
-  VarStreamArrayIterator() : Array(nullptr), IterRef() {}
+  VarStreamArrayIterator() : Array(nullptr), IterRef(), HasError(false) {}
+  ~VarStreamArrayIterator() {}
+
   bool operator==(const IterType &R) const {
     if (Array && R.Array) {
       // Both have a valid array, make sure they're same.
@@ -87,19 +102,30 @@ public:
 
   bool operator!=(const IterType &R) { return !(*this == R); }
 
-  const ValueType &operator*() const { return ThisValue; }
+  const ValueType &operator*() const {
+    assert(Array && !HasError);
+    return ThisValue;
+  }
 
   IterType &operator++() {
-    if (!Array || IterRef.getLength() == 0 || ThisLen == 0)
+    if (!Array || IterRef.getLength() == 0 || ThisLen == 0 || HasError)
       return *this;
     IterRef = IterRef.drop_front(ThisLen);
     if (IterRef.getLength() == 0)
       ThisLen = 0;
-    else
-      // TODO: We should report an error if Extract fails.
-      ThisLen = Extract(IterRef, ThisValue);
-    if (ThisLen == 0)
+    else {
+      auto EC = Extract(IterRef, ThisLen, ThisValue);
+      if (EC) {
+        consumeError(std::move(EC));
+        HasError = true;
+        if (HadError)
+          *HadError = true;
+      }
+    }
+    if (ThisLen == 0 || HasError) {
       Array = nullptr;
+      ThisLen = 0;
+    }
     return *this;
   }
 
@@ -114,6 +140,8 @@ private:
   uint32_t ThisLen;
   ValueType ThisValue;
   StreamRef IterRef;
+  bool HasError;
+  bool *HadError;
   Extractor Extract;
 };
 
index fb73da3..f875f18 100644 (file)
@@ -28,8 +28,6 @@ class StreamInterface {
 public:
   virtual ~StreamInterface() {}
 
-  virtual Error readBytes(uint32_t Offset,
-                          MutableArrayRef<uint8_t> Buffer) const = 0;
   virtual Error readBytes(uint32_t Offset, uint32_t Size,
                           ArrayRef<uint8_t> &Buffer) const = 0;
 
index 71691dc..adc23ca 100644 (file)
@@ -28,18 +28,17 @@ class StreamReader {
 public:
   StreamReader(const StreamInterface &S);
 
-  Error readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer);
+  Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
   Error readInteger(uint16_t &Dest);
   Error readInteger(uint32_t &Dest);
   Error readZeroString(StringRef &Dest);
   Error readFixedString(StringRef &Dest, uint32_t Length);
   Error readStreamRef(StreamRef &Ref);
   Error readStreamRef(StreamRef &Ref, uint32_t Length);
-  Error readBytes(MutableArrayRef<uint8_t> Buffer);
 
   template <typename T> Error readObject(const T *&Dest) {
     ArrayRef<uint8_t> Buffer;
-    if (auto EC = readBytes(sizeof(T), Buffer))
+    if (auto EC = readBytes(Buffer, sizeof(T)))
       return EC;
     Dest = reinterpret_cast<const T *>(Buffer.data());
     return Error::success();
index 1597f9a..7fdfb2a 100644 (file)
@@ -26,11 +26,6 @@ public:
       : Stream(Other.Stream), ViewOffset(Other.ViewOffset),
         Length(Other.Length) {}
 
-  Error readBytes(uint32_t Offset,
-                  MutableArrayRef<uint8_t> Buffer) const override {
-    return Stream->readBytes(ViewOffset + Offset, Buffer);
-  }
-
   Error readBytes(uint32_t Offset, uint32_t Size,
                   ArrayRef<uint8_t> &Buffer) const override {
     return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
index 97c7952..648e40f 100644 (file)
@@ -39,7 +39,7 @@ public:
 
   /// Dumps the type records in Data. Returns false if there was a type stream
   /// parse error, and true otherwise.
-  bool dump(ArrayRef<uint8_t> Data);
+  bool dump(const CVSymbolArray &Symbols);
 
 private:
   ScopedPrinter &W;
index 9ab559d..0677f5c 100644 (file)
@@ -12,8 +12,8 @@
 
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
 #include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/StreamInterface.h"
@@ -1442,15 +1442,9 @@ public:
   StringRef Name;
 };
 
-typedef RecordIterator<SymbolKind> SymbolIterator;
 typedef CVRecord<SymbolKind> CVSymbol;
 typedef VarStreamArray<CVSymbol> CVSymbolArray;
 
-inline iterator_range<SymbolIterator> makeSymbolRange(ArrayRef<uint8_t> Data,
-                                                      bool *HadError) {
-  return make_range(SymbolIterator(Data, HadError), SymbolIterator());
-}
-
 } // namespace codeview
 } // namespace llvm
 
index c74f5cf..670dcd7 100644 (file)
@@ -14,7 +14,6 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 
 namespace llvm {
 class ScopedPrinter;
@@ -38,7 +37,7 @@ public:
 
   /// Dumps the type records in Data. Returns false if there was a type stream
   /// parse error, and true otherwise.
-  bool dump(ArrayRef<uint8_t> Data);
+  bool dump(const CVTypeArray &Types);
 
   /// Gets the type index for the next type record.
   unsigned getNextTypeIndex() const {
index a53570f..c2f1343 100644 (file)
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/Support/ErrorOr.h"
 #include <cinttypes>
@@ -1398,6 +1400,9 @@ private:
   uint64_t VBPtrOffset;
   uint64_t VTableIndex;
 };
+
+typedef CVRecord<TypeLeafKind> CVType;
+typedef VarStreamArray<CVType> CVTypeArray;
 }
 }
 
diff --git a/include/llvm/DebugInfo/CodeView/TypeStream.h b/include/llvm/DebugInfo/CodeView/TypeStream.h
deleted file mode 100644 (file)
index 5dc2df3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- TypeStream.h ---------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/Support/Endian.h"
-#include <cstdint>
-#include <system_error>
-
-namespace llvm {
-
-class APSInt;
-
-namespace codeview {
-
-typedef RecordIterator<TypeLeafKind> TypeIterator;
-
-inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data, bool *HadError) {
-  return make_range(TypeIterator(Data, HadError), TypeIterator());
-}
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H
index 0dd4927..af396c7 100644 (file)
@@ -18,8 +18,7 @@ namespace llvm {
 namespace codeview {
 
 /// Merges one type stream into another. Returns true on success.
-bool mergeTypeStreams(TypeTableBuilder &DestStream,
-                      ArrayRef<uint8_t> SrcStream);
+bool mergeTypeStreams(TypeTableBuilder &DestStream, const CVTypeArray &Types);
 
 } // end namespace codeview
 } // end namespace llvm
index 864f8d4..dd69694 100644 (file)
@@ -27,14 +27,13 @@ class MappedBlockStream : public codeview::StreamInterface {
 public:
   MappedBlockStream(uint32_t StreamIdx, const PDBFile &File);
 
-  Error readBytes(uint32_t Offset,
-                  MutableArrayRef<uint8_t> Buffer) const override;
   Error readBytes(uint32_t Offset, uint32_t Size,
                   ArrayRef<uint8_t> &Buffer) const override;
 
   uint32_t getLength() const override { return StreamLength; }
 
 private:
+  Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
   bool tryReadContiguously(uint32_t Offset, uint32_t Size,
                            ArrayRef<uint8_t> &Buffer) const;
 
index c9050ab..cd7f2cf 100644 (file)
@@ -25,10 +25,11 @@ private:
 
 public:
   ModInfo();
-  ModInfo(codeview::StreamRef Stream);
   ModInfo(const ModInfo &Info);
   ~ModInfo();
 
+  static Error initialize(codeview::StreamRef Stream, ModInfo &Info);
+
   bool hasECInfo() const;
   uint16_t getTypeServerIndex() const;
   uint16_t getModuleStreamIndex() const;
@@ -51,7 +52,6 @@ private:
 };
 
 struct ModuleInfoEx {
-  ModuleInfoEx(codeview::StreamRef Stream) : Info(Stream) {}
   ModuleInfoEx(const ModInfo &Info) : Info(Info) {}
   ModuleInfoEx(const ModuleInfoEx &Ex)
       : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
@@ -64,9 +64,12 @@ struct ModuleInfoEx {
 
 namespace codeview {
 template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
-  uint32_t operator()(const StreamInterface &Stream, pdb::ModInfo &Info) const {
-    Info = pdb::ModInfo(Stream);
-    return Info.getRecordLength();
+  Error operator()(const StreamInterface &Stream, uint32_t &Length,
+                   pdb::ModInfo &Info) const {
+    if (auto EC = pdb::ModInfo::initialize(Stream, Info))
+      return EC;
+    Length = Info.getRecordLength();
+    return Error::success();
   }
 };
 }
index 7286913..1460e82 100644 (file)
@@ -11,7 +11,7 @@
 #define LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H
 
 #include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/StreamRef.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
@@ -29,7 +29,8 @@ public:
 
   Error reload();
 
-  iterator_range<codeview::CVSymbolArray::Iterator> symbols() const;
+  iterator_range<codeview::CVSymbolArray::Iterator>
+  symbols(bool *HadError) const;
 
 private:
   const ModInfo &Mod;
index 10fd130..c2138be 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@@ -37,7 +36,8 @@ public:
   uint32_t getSymHash() const;
   uint32_t getAddrMap() const;
   uint32_t getNumBuckets() const { return NumBuckets; }
-  iterator_range<codeview::SymbolIterator> getSymbols() const;
+  iterator_range<codeview::CVSymbolArray::Iterator>
+  getSymbols(bool *HadError) const;
   codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
     return HashBuckets;
   }
@@ -52,8 +52,6 @@ public:
   }
 
 private:
-  Error readSymbols();
-
   PDBFile &Pdb;
 
   uint32_t StreamNum;
index bb5f418..1f8598d 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
 #define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
 
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
 
@@ -26,10 +26,11 @@ public:
   ~SymbolStream();
   Error reload();
 
-  iterator_range<codeview::SymbolIterator> getSymbols() const;
+  iterator_range<codeview::CVSymbolArray::Iterator>
+  getSymbols(bool *HadError) const;
 
 private:
-  codeview::ByteStream Stream;
+  codeview::CVSymbolArray SymbolRecords;
   MappedBlockStream MappedStream;
 };
 }
index 4fb9110..55c0e30 100644 (file)
@@ -10,9 +10,9 @@
 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
 #define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
 
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
 #include "llvm/DebugInfo/CodeView/StreamRef.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@@ -41,14 +41,14 @@ public:
   uint16_t getTypeHashStreamIndex() const;
   uint16_t getTypeHashStreamAuxIndex() const;
 
-  iterator_range<codeview::TypeIterator> types(bool *HadError) const;
+  iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
 
 private:
   PDBFile &Pdb;
   MappedBlockStream Stream;
   HashFunctionType HashFunction;
 
-  codeview::ByteStream RecordsBuffer;
+  codeview::CVTypeArray TypeRecords;
   codeview::StreamRef TypeIndexOffsetBuffer;
   codeview::StreamRef HashValuesBuffer;
   codeview::StreamRef HashAdjBuffer;
index 1ea976b..c0ac0b7 100644 (file)
@@ -17,41 +17,13 @@ using namespace llvm::codeview;
 
 ByteStream::ByteStream() {}
 
-ByteStream::ByteStream(MutableArrayRef<uint8_t> Data) : Data(Data) {}
+ByteStream::ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
 
 ByteStream::~ByteStream() {}
 
-void ByteStream::reset() {
-  Ownership.reset();
-  Data = MutableArrayRef<uint8_t>();
-}
-
-void ByteStream::load(uint32_t Length) {
-  reset();
-  if (Length > 0)
-    Data = MutableArrayRef<uint8_t>(new uint8_t[Length], Length);
-  Ownership.reset(Data.data());
-}
-
-Error ByteStream::load(StreamReader &Reader, uint32_t Length) {
-  load(Length);
-  auto EC = Reader.readBytes(Data);
-  if (EC)
-    reset();
-  return EC;
-}
-
-Error ByteStream::readBytes(uint32_t Offset,
-                            MutableArrayRef<uint8_t> Buffer) const {
-  if (Data.size() < Buffer.size() + Offset)
-    return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-  ::memcpy(Buffer.data() + Offset, Data.data(), Buffer.size());
-  return Error::success();
-}
-
 Error ByteStream::readBytes(uint32_t Offset, uint32_t Size,
                             ArrayRef<uint8_t> &Buffer) const {
-  if (Data.size() < Buffer.size() + Offset)
+  if (Data.size() < Size + Offset)
     return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
   Buffer = Data.slice(Offset, Size);
   return Error::success();
index 64985bf..94a6183 100644 (file)
@@ -17,20 +17,13 @@ using namespace llvm::codeview;
 
 StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {}
 
-Error StreamReader::readBytes(uint32_t Size, ArrayRef<uint8_t> &Buffer) {
+Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
   if (auto EC = Stream.readBytes(Offset, Size, Buffer))
     return EC;
   Offset += Size;
   return Error::success();
 }
 
-Error StreamReader::readBytes(MutableArrayRef<uint8_t> Buffer) {
-  if (auto EC = Stream.readBytes(Offset, Buffer))
-    return EC;
-  Offset += Buffer.size();
-  return Error::success();
-}
-
 Error StreamReader::readInteger(uint16_t &Dest) {
   const support::ulittle16_t *P;
   if (auto EC = readObject(P))
@@ -63,7 +56,7 @@ Error StreamReader::readZeroString(StringRef &Dest) {
   setOffset(OriginalOffset);
 
   ArrayRef<uint8_t> Data;
-  if (auto EC = readBytes(Length, Data))
+  if (auto EC = readBytes(Data, Length))
     return EC;
   Dest = StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size());
 
@@ -74,7 +67,7 @@ Error StreamReader::readZeroString(StringRef &Dest) {
 
 Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
   ArrayRef<uint8_t> Bytes;
-  if (auto EC = readBytes(Length, Bytes))
+  if (auto EC = readBytes(Bytes, Length))
     return EC;
   Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
   return Error::success();
index 7d405ec..e2dc9d5 100644 (file)
@@ -872,8 +872,8 @@ bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
   return !Dumper.hadError();
 }
 
-bool CVSymbolDumper::dump(ArrayRef<uint8_t> Data) {
+bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
-  Dumper.visitSymbolStream(Data);
+  Dumper.visitSymbolStream(Symbols);
   return !Dumper.hadError();
 }
index 1db1e54..da3919a 100644 (file)
@@ -12,7 +12,6 @@
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;
@@ -683,10 +682,10 @@ bool CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
   return !Dumper.hadError();
 }
 
-bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+bool CVTypeDumper::dump(const CVTypeArray &Types) {
   assert(W && "printer should not be null");
   CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
-  Dumper.visitTypeStream(Data);
+  Dumper.visitTypeStream(Types);
   return !Dumper.hadError();
 }
 
index 88211d0..d16e481 100644 (file)
@@ -12,9 +12,9 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;
@@ -71,7 +71,7 @@ public:
 
   void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData);
 
-  bool mergeStream(ArrayRef<uint8_t> SrcStream);
+  bool mergeStream(const CVTypeArray &Types);
 
 private:
   bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); }
@@ -131,14 +131,14 @@ void TypeStreamMerger::visitUnknownMember(TypeLeafKind LF) {
   parseError();
 }
 
-bool TypeStreamMerger::mergeStream(ArrayRef<uint8_t> SrcStream) {
+bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
   assert(IndexMap.empty());
-  visitTypeStream(SrcStream);
+  visitTypeStream(Types);
   IndexMap.clear();
   return !hadError();
 }
 
 bool llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestStream,
-                                      ArrayRef<uint8_t> SrcStream) {
-  return TypeStreamMerger(DestStream).mergeStream(SrcStream);
+                                      const CVTypeArray &Types) {
+  return TypeStreamMerger(DestStream).mergeStream(Types);
 }
index 67dc81d..bae135f 100644 (file)
@@ -69,28 +69,25 @@ struct ModInfo::FileLayout {
 
 ModInfo::ModInfo() : Layout(nullptr) {}
 
-ModInfo::ModInfo(codeview::StreamRef Stream) : Layout(nullptr) {
-  codeview::StreamReader Reader(Stream);
-  if (auto EC = Reader.readObject(Layout)) {
-    consumeError(std::move(EC));
-    return;
-  }
-  if (auto EC = Reader.readZeroString(ModuleName)) {
-    consumeError(std::move(EC));
-    return;
-  }
-  if (auto EC = Reader.readZeroString(ObjFileName)) {
-    consumeError(std::move(EC));
-    return;
-  }
-}
-
 ModInfo::ModInfo(const ModInfo &Info)
     : ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
       Layout(Info.Layout) {}
 
 ModInfo::~ModInfo() {}
 
+Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) {
+  codeview::StreamReader Reader(Stream);
+  if (auto EC = Reader.readObject(Info.Layout))
+    return EC;
+
+  if (auto EC = Reader.readZeroString(Info.ModuleName))
+    return EC;
+
+  if (auto EC = Reader.readZeroString(Info.ObjFileName))
+    return EC;
+  return Error::success();
+}
+
 bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; }
 
 uint16_t ModInfo::getTypeServerIndex() const {
index 404208a..88c6b7c 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "llvm/DebugInfo/PDB/Raw/ModStream.h"
 
-#include "llvm/DebugInfo/CodeView/RecordIterator.h"
 #include "llvm/DebugInfo/CodeView/StreamReader.h"
 #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
@@ -58,6 +57,7 @@ Error ModStream::reload() {
   return Error::success();
 }
 
-iterator_range<codeview::CVSymbolArray::Iterator> ModStream::symbols() const {
+iterator_range<codeview::CVSymbolArray::Iterator>
+ModStream::symbols(bool *HadError) const {
   return llvm::make_range(SymbolsSubstream.begin(), SymbolsSubstream.end());
 }
index f51a8ef..d3a7ffd 100644 (file)
@@ -113,7 +113,7 @@ Error PublicsStream::reload() {
   // A bitmap of a fixed length follows.
   size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
   uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
-  if (auto EC = Reader.readBytes(NumBitmapEntries, Bitmap))
+  if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
     return joinErrors(std::move(EC),
                       make_error<RawError>(raw_error_code::corrupt_file,
                                            "Could not read a bitmap."));
@@ -156,13 +156,14 @@ Error PublicsStream::reload() {
   return Error::success();
 }
 
-iterator_range<codeview::SymbolIterator> PublicsStream::getSymbols() const {
-  using codeview::SymbolIterator;
+iterator_range<codeview::CVSymbolArray::Iterator>
+PublicsStream::getSymbols(bool *HadError) const {
   auto SymbolS = Pdb.getPDBSymbolStream();
   if (SymbolS.takeError()) {
-    return llvm::make_range<SymbolIterator>(SymbolIterator(), SymbolIterator());
+    codeview::CVSymbolArray::Iterator Iter;
+    return llvm::make_range(Iter, Iter);
   }
   SymbolStream &SS = SymbolS.get();
 
-  return SS.getSymbols();
+  return SS.getSymbols(HadError);
 }
index ba4ea57..021e229 100644 (file)
@@ -30,20 +30,13 @@ SymbolStream::~SymbolStream() {}
 Error SymbolStream::reload() {
   codeview::StreamReader Reader(MappedStream);
 
-  if (Stream.load(Reader, MappedStream.getLength()))
-    return make_error<RawError>(raw_error_code::corrupt_file,
-                                "Could not load symbol stream.");
+  if (auto EC = Reader.readArray(SymbolRecords, MappedStream.getLength()))
+    return EC;
 
   return Error::success();
 }
 
-iterator_range<codeview::SymbolIterator> SymbolStream::getSymbols() const {
-  using codeview::SymbolIterator;
-  ArrayRef<uint8_t> Data;
-  if (auto Error = Stream.readBytes(0, Stream.getLength(), Data)) {
-    consumeError(std::move(Error));
-    return iterator_range<SymbolIterator>(SymbolIterator(), SymbolIterator());
-  }
-
-  return codeview::makeSymbolRange(Data, nullptr);
+iterator_range<codeview::CVSymbolArray::Iterator>
+SymbolStream::getSymbols(bool *HadError) const {
+  return llvm::make_range(SymbolRecords.begin(HadError), SymbolRecords.end());
 }
index 3345ab2..6478ad1 100644 (file)
@@ -92,7 +92,7 @@ Error TpiStream::reload() {
   HashFunction = HashBufferV8;
 
   // The actual type records themselves come from this stream
-  if (auto EC = RecordsBuffer.load(Reader, Header->TypeRecordBytes))
+  if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
     return EC;
 
   // Hash indices, hash values, etc come from the hash stream.
@@ -136,6 +136,7 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
   return Header->HashAuxStreamIndex;
 }
 
-iterator_range<codeview::TypeIterator> TpiStream::types(bool *HadError) const {
-  return codeview::makeTypeRange(RecordsBuffer.data(), /*HadError=*/HadError);
+iterator_range<codeview::CVTypeArray::Iterator>
+TpiStream::types(bool *HadError) const {
+  return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
 }
index 50e2123..b81ba21 100644 (file)
@@ -354,7 +354,7 @@ static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) {
     ArrayRef<uint8_t> Data;
     uint32_t BytesToReadInBlock = std::min(
         R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
-    if (auto EC = R.readBytes(BytesToReadInBlock, Data))
+    if (auto EC = R.readBytes(Data, BytesToReadInBlock))
       return EC;
     P.printBinaryBlock(
         "Data",
@@ -485,7 +485,8 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
           return EC;
 
         codeview::CVSymbolDumper SD(P, TD, nullptr, false);
-        for (auto &S : ModS.symbols()) {
+        bool HadError = false;
+        for (auto &S : ModS.symbols(&HadError)) {
           DictScope DD(P, "");
 
           if (opts::DumpModuleSyms)
@@ -493,6 +494,9 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
           if (opts::DumpSymRecordBytes)
             P.printBinaryBlock("Bytes", S.Data);
         }
+        if (HadError)
+          return make_error<RawError>(raw_error_code::corrupt_file,
+                                      "DBI stream contained corrupt record");
       }
     }
   }
@@ -509,7 +513,7 @@ static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File,
   StringRef VerLabel;
   if (StreamIdx == StreamTPI) {
     DumpRecordBytes = opts::DumpTpiRecordBytes;
-    DumpRecords = opts::DumpTpiRecordBytes;
+    DumpRecords = opts::DumpTpiRecords;
     Label = "Type Info Stream (TPI)";
     VerLabel = "TPI Version";
   } else if (StreamIdx == StreamIPI) {
@@ -595,13 +599,19 @@ static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File,
               printSectionOffset);
   ListScope L(P, "Symbols");
   codeview::CVSymbolDumper SD(P, TD, nullptr, false);
-  for (auto S : Publics.getSymbols()) {
+  bool HadError = false;
+  for (auto S : Publics.getSymbols(&HadError)) {
     DictScope DD(P, "");
 
     SD.dump(S);
     if (opts::DumpSymRecordBytes)
       P.printBinaryBlock("Bytes", S.Data);
   }
+  if (HadError)
+    return make_error<RawError>(
+        raw_error_code::corrupt_file,
+        "Public symbol stream contained corrupt record");
+
   return Error::success();
 }
 
index 546387b..c890c9a 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/ByteStream.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
@@ -32,7 +33,6 @@
 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/ObjectFile.h"
@@ -898,8 +898,16 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
                                                         SectionContents);
 
   CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes);
+  ByteStream Stream(BinaryData);
+  CVSymbolArray Symbols;
+  StreamReader Reader(Stream);
+  if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
+    consumeError(std::move(EC));
+    W.flush();
+    error(object_error::parse_failed);
+  }
 
-  if (!CVSD.dump(BinaryData)) {
+  if (!CVSD.dump(Symbols)) {
     W.flush();
     error(object_error::parse_failed);
   }
@@ -996,7 +1004,16 @@ void COFFDumper::mergeCodeViewTypes(MemoryTypeTableBuilder &CVTypes) {
       Data = Data.drop_front(4);
       ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
                               Data.size());
-      if (!mergeTypeStreams(CVTypes, Bytes))
+      ByteStream Stream(Bytes);
+      CVTypeArray Types;
+      StreamReader Reader(Stream);
+      if (auto EC = Reader.readArray(Types, Reader.getLength())) {
+        consumeError(std::move(EC));
+        W.flush();
+        error(object_error::parse_failed);
+      }
+
+      if (!mergeTypeStreams(CVTypes, Types))
         return error(object_error::parse_failed);
     }
   }
@@ -1020,7 +1037,16 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
 
   ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Data.data()),
                                Data.size());
-  if (!CVTD.dump(BinaryData)) {
+  ByteStream Stream(BinaryData);
+  CVTypeArray Types;
+  StreamReader Reader(Stream);
+  if (auto EC = Reader.readArray(Types, Reader.getLength())) {
+    consumeError(std::move(EC));
+    W.flush();
+    error(object_error::parse_failed);
+  }
+
+  if (!CVTD.dump(Types)) {
     W.flush();
     error(object_error::parse_failed);
   }
@@ -1472,7 +1498,16 @@ void llvm::dumpCodeViewMergedTypes(
   CVTypeDumper CVTD(Writer, opts::CodeViewSubsectionBytes);
   ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Buf.data()),
                                Buf.size());
-  if (!CVTD.dump(BinaryData)) {
+  ByteStream Stream(BinaryData);
+  CVTypeArray Types;
+  StreamReader Reader(Stream);
+  if (auto EC = Reader.readArray(Types, Reader.getLength())) {
+    consumeError(std::move(EC));
+    Writer.flush();
+    error(object_error::parse_failed);
+  }
+
+  if (!CVTD.dump(Types)) {
     Writer.flush();
     error(object_error::parse_failed);
   }