]> granicus.if.org Git - llvm/commitdiff
[CodeView] Refactor serialization to use StreamInterface.
authorZachary Turner <zturner@google.com>
Thu, 20 Oct 2016 18:31:19 +0000 (18:31 +0000)
committerZachary Turner <zturner@google.com>
Thu, 20 Oct 2016 18:31:19 +0000 (18:31 +0000)
This was all using ArrayRef<>s before which presents a problem
when you want to serialize to or deserialize from an actual
PDB stream.  An ArrayRef<> is really just a special case of
what can be handled with StreamInterface though (e.g. by using
a ByteStream), so changing this to use StreamInterface allows
us to plug in a PDB stream and get all the record serialization
and deserialization for free on a MappedBlockStream.

Subsequent patches will try to remove TypeTableBuilder and
TypeRecordBuilder in favor of class that operate on
Streams as well, which should allow us to completely merge
the reading and writing codepaths for both types and symbols.

Differential Revision: https://reviews.llvm.org/D25831

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

14 files changed:
include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
include/llvm/DebugInfo/CodeView/RecordSerialization.h
include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
include/llvm/DebugInfo/CodeView/SymbolRecord.h
include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
include/llvm/DebugInfo/CodeView/TypeDeserializer.h
include/llvm/DebugInfo/CodeView/TypeRecord.h
include/llvm/DebugInfo/MSF/ByteStream.h
include/llvm/DebugInfo/MSF/StreamReader.h
lib/DebugInfo/CodeView/CVTypeVisitor.cpp
lib/DebugInfo/CodeView/RecordSerialization.cpp
lib/DebugInfo/CodeView/TypeRecord.cpp
lib/DebugInfo/MSF/StreamReader.cpp
tools/llvm-readobj/COFFDumper.cpp

index 77e74ff7565e7d54db7fcd1771bf2ce90fe2e0af..d1b0363a4133d8dfc7c3e08fc8bfd38bc2a39317 100644 (file)
@@ -30,6 +30,7 @@ public:
   Error visitTypeStream(const CVTypeArray &Types);
 
   Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
+  Error visitFieldListMemberStream(msf::StreamReader Reader);
 
 private:
   /// The interface to the class that gets notified of each visitation.
index 8b24086a66419b205d6f81ff049dca9077a34ddd..a670bb420d8ada80aa2d324aaaf9c5707ff0a19e 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include <cinttypes>
@@ -40,53 +41,40 @@ struct RecordPrefix {
 StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
 StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
 
-/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
-/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
-/// T object and points 'Res' at them.
-template <typename T, typename U>
-inline Error consumeObject(U &Data, const T *&Res) {
-  if (Data.size() < sizeof(*Res))
-    return make_error<CodeViewError>(
-        cv_error_code::insufficient_buffer,
-        "Insufficient bytes for expected object type");
-  Res = reinterpret_cast<const T *>(Data.data());
-  Data = Data.drop_front(sizeof(*Res));
-  return Error::success();
-}
-
-inline Error consume(ArrayRef<uint8_t> &Data) { return Error::success(); }
+inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
 
 /// Decodes a numeric "leaf" value. These are integer literals encountered in
 /// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
 /// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
 /// that indicates the bitwidth and sign of the numeric data.
-Error consume(ArrayRef<uint8_t> &Data, APSInt &Num);
-Error consume(StringRef &Data, APSInt &Num);
+Error consume(msf::StreamReader &Reader, APSInt &Num);
 
 /// Decodes a numeric leaf value that is known to be a particular type.
-Error consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Value);
+Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value);
 
 /// Decodes signed and unsigned fixed-length integers.
-Error consume(ArrayRef<uint8_t> &Data, uint32_t &Item);
-Error consume(StringRef &Data, uint32_t &Item);
-Error consume(ArrayRef<uint8_t> &Data, int32_t &Item);
+Error consume(msf::StreamReader &Reader, uint32_t &Item);
+Error consume(msf::StreamReader &Reader, int32_t &Item);
 
 /// Decodes a null terminated string.
-Error consume(ArrayRef<uint8_t> &Data, StringRef &Item);
+Error consume(msf::StreamReader &Reader, StringRef &Item);
+
+Error consume(StringRef &Data, APSInt &Num);
+Error consume(StringRef &Data, uint32_t &Item);
 
 /// Decodes an arbitrary object whose layout matches that of the underlying
 /// byte sequence, and returns a pointer to the object.
-template <typename T> Error consume(ArrayRef<uint8_t> &Data, T *&Item) {
-  return consumeObject(Data, Item);
+template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
+  return Reader.readObject(Item);
 }
 
 template <typename T, typename U> struct serialize_conditional_impl {
   serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
+  Error deserialize(msf::StreamReader &Reader) const {
     if (!Func())
       return Error::success();
-    return consume(Data, Item);
+    return consume(Reader, Item);
   }
 
   T &Item;
@@ -101,26 +89,8 @@ serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) {
 template <typename T, typename U> struct serialize_array_impl {
   serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
-    uint32_t N = Func();
-    if (N == 0)
-      return Error::success();
-
-    uint32_t Size = sizeof(T) * N;
-
-    if (Size / sizeof(T) != N)
-      return make_error<CodeViewError>(
-          cv_error_code::corrupt_record,
-          "Array<T> length is not a multiple of sizeof(T)");
-
-    if (Data.size() < Size)
-      return make_error<CodeViewError>(
-          cv_error_code::corrupt_record,
-          "Array<T> does not contain enough data for all elements");
-
-    Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N);
-    Data = Data.drop_front(Size);
-    return Error::success();
+  Error deserialize(msf::StreamReader &Reader) const {
+    return Reader.readArray(Item, Func());
   }
 
   ArrayRef<T> &Item;
@@ -130,11 +100,11 @@ template <typename T, typename U> struct serialize_array_impl {
 template <typename T> struct serialize_vector_tail_impl {
   serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
+  Error deserialize(msf::StreamReader &Reader) const {
     T Field;
     // Stop when we run out of bytes or we hit record padding bytes.
-    while (!Data.empty() && Data.front() < LF_PAD0) {
-      if (auto EC = consume(Data, Field))
+    while (!Reader.empty() && Reader.peek() < LF_PAD0) {
+      if (auto EC = consume(Reader, Field))
         return EC;
       Item.push_back(Field);
     }
@@ -148,24 +118,18 @@ struct serialize_null_term_string_array_impl {
   serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
       : Item(Item) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
-    if (Data.empty())
+  Error deserialize(msf::StreamReader &Reader) const {
+    if (Reader.empty())
       return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
                                        "Null terminated string is empty!");
 
-    StringRef Field;
-    // Stop when we run out of bytes or we hit record padding bytes.
-    while (Data.front() != 0) {
-      if (auto EC = consume(Data, Field))
+    while (Reader.peek() != 0) {
+      StringRef Field;
+      if (auto EC = Reader.readZeroString(Field))
         return EC;
       Item.push_back(Field);
-      if (Data.empty())
-        return make_error<CodeViewError>(
-            cv_error_code::insufficient_buffer,
-            "Null terminated string has no null terminator!");
     }
-    Data = Data.drop_front(1);
-    return Error::success();
+    return Reader.skip(1);
   }
 
   std::vector<StringRef> &Item;
@@ -174,10 +138,9 @@ struct serialize_null_term_string_array_impl {
 template <typename T> struct serialize_arrayref_tail_impl {
   serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
-    uint32_t Count = Data.size() / sizeof(T);
-    Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count);
-    return Error::success();
+  Error deserialize(msf::StreamReader &Reader) const {
+    uint32_t Count = Reader.bytesRemaining() / sizeof(T);
+    return Reader.readArray(Item, Count);
   }
 
   ArrayRef<T> &Item;
@@ -186,8 +149,8 @@ template <typename T> struct serialize_arrayref_tail_impl {
 template <typename T> struct serialize_numeric_impl {
   serialize_numeric_impl(T &Item) : Item(Item) {}
 
-  Error deserialize(ArrayRef<uint8_t> &Data) const {
-    return consume_numeric(Data, Item);
+  Error deserialize(msf::StreamReader &Reader) const {
+    return consume_numeric(Reader, Item);
   }
 
   T &Item;
@@ -238,43 +201,45 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
 #define CV_NUMERIC_FIELD(I) serialize_numeric(I)
 
 template <typename T, typename U>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
               const serialize_conditional_impl<T, U> &Item) {
-  return Item.deserialize(Data);
+  return Item.deserialize(Reader);
 }
 
 template <typename T, typename U>
-Error consume(ArrayRef<uint8_t> &Data, const serialize_array_impl<T, U> &Item) {
-  return Item.deserialize(Data);
+Error consume(msf::StreamReader &Reader,
+              const serialize_array_impl<T, U> &Item) {
+  return Item.deserialize(Reader);
 }
 
-inline Error consume(ArrayRef<uint8_t> &Data,
+inline Error consume(msf::StreamReader &Reader,
                      const serialize_null_term_string_array_impl &Item) {
-  return Item.deserialize(Data);
+  return Item.deserialize(Reader);
 }
 
 template <typename T>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
               const serialize_vector_tail_impl<T> &Item) {
-  return Item.deserialize(Data);
+  return Item.deserialize(Reader);
 }
 
 template <typename T>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
               const serialize_arrayref_tail_impl<T> &Item) {
-  return Item.deserialize(Data);
+  return Item.deserialize(Reader);
 }
 
 template <typename T>
-Error consume(ArrayRef<uint8_t> &Data, const serialize_numeric_impl<T> &Item) {
-  return Item.deserialize(Data);
+Error consume(msf::StreamReader &Reader,
+              const serialize_numeric_impl<T> &Item) {
+  return Item.deserialize(Reader);
 }
 
 template <typename T, typename U, typename... Args>
-Error consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y, Args &&... Rest) {
-  if (auto EC = consume(Data, X))
+Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
+  if (auto EC = consume(Reader, X))
     return EC;
-  return consume(Data, Y, std::forward<Args>(Rest)...);
+  return consume(Reader, Y, std::forward<Args>(Rest)...);
 }
 
 #define CV_DESERIALIZE(...)                                                    \
index 24e8c6150a5c0978342b8b04a150022c68bf033e..3ccc2db073c44d72e206fbaf5177d22cdebdd362 100644 (file)
@@ -14,6 +14,8 @@
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
 #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
@@ -33,11 +35,11 @@ public:
 
 protected:
   template <typename T>
-  Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
+  Error deserializeRecord(msf::StreamReader &Reader, SymbolKind Kind,
                           T &Record) const {
-    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
+    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Reader) : 0;
     SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
-    auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
+    auto ExpectedRecord = T::deserialize(RK, RecordOffset, Reader);
     if (!ExpectedRecord)
       return ExpectedRecord.takeError();
     Record = std::move(*ExpectedRecord);
@@ -47,8 +49,9 @@ protected:
 private:
   template <typename T>
   Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
-    ArrayRef<uint8_t> RD = CVR.content();
-    if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+    msf::ByteStream S(CVR.content());
+    msf::StreamReader SR(S);
+    if (auto EC = deserializeRecord(SR, CVR.Type, Record))
       return EC;
     return Error::success();
   }
index 4eecda0dd8173047433e855320dabb47166c1822..117c63baaa03f2bd72b5cc91ec60b36e78240a8c 100644 (file)
@@ -64,10 +64,10 @@ public:
 
   static Expected<ProcSym> deserialize(SymbolRecordKind Kind,
                                        uint32_t RecordOffset,
-                                       ArrayRef<uint8_t> &Data) {
+                                       msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return ProcSym(Kind, RecordOffset, H, Name);
   }
@@ -104,12 +104,12 @@ public:
 
   static Expected<Thunk32Sym> deserialize(SymbolRecordKind Kind,
                                           uint32_t RecordOffset,
-                                          ArrayRef<uint8_t> &Data) {
+                                          msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
     ArrayRef<uint8_t> VariantData;
 
-    CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
+    CV_DESERIALIZE(Reader, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
 
     return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
   }
@@ -138,10 +138,10 @@ public:
 
   static Expected<TrampolineSym> deserialize(SymbolRecordKind Kind,
                                              uint32_t RecordOffset,
-                                             ArrayRef<uint8_t> &Data) {
+                                             msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
 
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return TrampolineSym(Kind, RecordOffset, H);
   }
@@ -171,11 +171,11 @@ public:
 
   static Expected<SectionSym> deserialize(SymbolRecordKind Kind,
                                           uint32_t RecordOffset,
-                                          ArrayRef<uint8_t> &Data) {
+                                          msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
 
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return SectionSym(Kind, RecordOffset, H, Name);
   }
@@ -204,11 +204,11 @@ public:
 
   static Expected<CoffGroupSym> deserialize(SymbolRecordKind Kind,
                                             uint32_t RecordOffset,
-                                            ArrayRef<uint8_t> &Data) {
+                                            msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
 
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return CoffGroupSym(Kind, RecordOffset, H, Name);
   }
@@ -226,7 +226,7 @@ public:
 
   static Expected<ScopeEndSym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     return ScopeEndSym(Kind, RecordOffset);
   }
   uint32_t RecordOffset;
@@ -246,11 +246,11 @@ public:
 
   static Expected<CallerSym> deserialize(SymbolRecordKind Kind,
                                          uint32_t RecordOffset,
-                                         ArrayRef<uint8_t> &Data) {
+                                         msf::StreamReader &Reader) {
     const Hdr *Header;
     ArrayRef<TypeIndex> Indices;
 
-    CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
+    CV_DESERIALIZE(Reader, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
 
     return CallerSym(Kind, RecordOffset, Header, Indices);
   }
@@ -456,10 +456,10 @@ public:
 
   static Expected<InlineSiteSym> deserialize(SymbolRecordKind Kind,
                                              uint32_t RecordOffset,
-                                             ArrayRef<uint8_t> &Data) {
+                                             msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<uint8_t> Annotations;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Annotations));
 
     return InlineSiteSym(RecordOffset, H, Annotations);
   }
@@ -493,10 +493,10 @@ public:
 
   static Expected<PublicSym32> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return PublicSym32(RecordOffset, H, Name);
   }
@@ -522,10 +522,10 @@ public:
 
   static Expected<RegisterSym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return RegisterSym(RecordOffset, H, Name);
   }
@@ -552,10 +552,10 @@ public:
 
   static Expected<ProcRefSym> deserialize(SymbolRecordKind Kind,
                                           uint32_t RecordOffset,
-                                          ArrayRef<uint8_t> &Data) {
+                                          msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return ProcRefSym(RecordOffset, H, Name);
   }
@@ -581,10 +581,10 @@ public:
 
   static Expected<LocalSym> deserialize(SymbolRecordKind Kind,
                                         uint32_t RecordOffset,
-                                        ArrayRef<uint8_t> &Data) {
+                                        msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return LocalSym(RecordOffset, H, Name);
   }
@@ -624,10 +624,10 @@ public:
 
   static Expected<DefRangeSym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeSym(RecordOffset, H, Gaps);
   }
@@ -658,10 +658,10 @@ public:
 
   static Expected<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
                                                    uint32_t RecordOffset,
-                                                   ArrayRef<uint8_t> &Data) {
+                                                   msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeSubfieldSym(RecordOffset, H, Gaps);
   }
@@ -702,10 +702,10 @@ public:
 
   static Expected<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
                                                    uint32_t RecordOffset,
-                                                   ArrayRef<uint8_t> &Data) {
+                                                   msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeRegisterSym(RecordOffset, H, Gaps);
   }
@@ -750,10 +750,10 @@ public:
 
   static Expected<DefRangeSubfieldRegisterSym>
   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
-              ArrayRef<uint8_t> &Data) {
+              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
   }
@@ -785,10 +785,10 @@ public:
 
   static Expected<DefRangeFramePointerRelSym>
   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
-              ArrayRef<uint8_t> &Data) {
+              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
   }
@@ -830,12 +830,12 @@ public:
     Header.Range = {};
   }
 
-  static Expected<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
-                                                      uint32_t RecordOffset,
-                                                      ArrayRef<uint8_t> &Data) {
+  static Expected<DefRangeRegisterRelSym>
+  deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     ArrayRef<LocalVariableAddrGap> Gaps;
-    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+    CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
 
     return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
   }
@@ -876,9 +876,9 @@ public:
 
   static Expected<DefRangeFramePointerRelFullScopeSym>
   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
-              ArrayRef<uint8_t> &Data) {
+              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
   }
@@ -906,10 +906,10 @@ public:
 
   static Expected<BlockSym> deserialize(SymbolRecordKind Kind,
                                         uint32_t RecordOffset,
-                                        ArrayRef<uint8_t> &Data) {
+                                        msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return BlockSym(RecordOffset, H, Name);
   }
@@ -940,10 +940,10 @@ public:
 
   static Expected<LabelSym> deserialize(SymbolRecordKind Kind,
                                         uint32_t RecordOffset,
-                                        ArrayRef<uint8_t> &Data) {
+                                        msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return LabelSym(RecordOffset, H, Name);
   }
@@ -972,10 +972,10 @@ public:
 
   static Expected<ObjNameSym> deserialize(SymbolRecordKind Kind,
                                           uint32_t RecordOffset,
-                                          ArrayRef<uint8_t> &Data) {
+                                          msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return ObjNameSym(RecordOffset, H, Name);
   }
@@ -1001,10 +1001,10 @@ public:
 
   static Expected<EnvBlockSym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     std::vector<StringRef> Fields;
-    CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
+    CV_DESERIALIZE(Reader, H, CV_STRING_ARRAY_NULL_TERM(Fields));
 
     return EnvBlockSym(RecordOffset, H, Fields);
   }
@@ -1030,10 +1030,10 @@ public:
 
   static Expected<ExportSym> deserialize(SymbolRecordKind Kind,
                                          uint32_t RecordOffset,
-                                         ArrayRef<uint8_t> &Data) {
+                                         msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return ExportSym(RecordOffset, H, Name);
   }
@@ -1060,10 +1060,10 @@ public:
 
   static Expected<FileStaticSym> deserialize(SymbolRecordKind Kind,
                                              uint32_t RecordOffset,
-                                             ArrayRef<uint8_t> &Data) {
+                                             msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return FileStaticSym(RecordOffset, H, Name);
   }
@@ -1097,10 +1097,10 @@ public:
 
   static Expected<Compile2Sym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Version;
-    CV_DESERIALIZE(Data, H, Version);
+    CV_DESERIALIZE(Reader, H, Version);
 
     return Compile2Sym(RecordOffset, H, Version);
   }
@@ -1135,10 +1135,10 @@ public:
 
   static Expected<Compile3Sym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Version;
-    CV_DESERIALIZE(Data, H, Version);
+    CV_DESERIALIZE(Reader, H, Version);
 
     return Compile3Sym(RecordOffset, H, Version);
   }
@@ -1168,9 +1168,9 @@ public:
 
   static Expected<FrameProcSym> deserialize(SymbolRecordKind Kind,
                                             uint32_t RecordOffset,
-                                            ArrayRef<uint8_t> &Data) {
+                                            msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return FrameProcSym(RecordOffset, H);
   }
@@ -1196,9 +1196,9 @@ public:
 
   static Expected<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
                                                uint32_t RecordOffset,
-                                               ArrayRef<uint8_t> &Data) {
+                                               msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return CallSiteInfoSym(RecordOffset, H);
   }
@@ -1226,11 +1226,11 @@ public:
       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
         RecordOffset(RecordOffset), Header(*H) {}
 
-  static Expected<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
-                                                     uint32_t RecordOffset,
-                                                     ArrayRef<uint8_t> &Data) {
+  static Expected<HeapAllocationSiteSym>
+  deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return HeapAllocationSiteSym(RecordOffset, H);
   }
@@ -1260,9 +1260,9 @@ public:
 
   static Expected<FrameCookieSym> deserialize(SymbolRecordKind Kind,
                                               uint32_t RecordOffset,
-                                              ArrayRef<uint8_t> &Data) {
+                                              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return FrameCookieSym(RecordOffset, H);
   }
@@ -1290,10 +1290,10 @@ public:
 
   static Expected<UDTSym> deserialize(SymbolRecordKind Kind,
                                       uint32_t RecordOffset,
-                                      ArrayRef<uint8_t> &Data) {
+                                      msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return UDTSym(RecordOffset, H, Name);
   }
@@ -1317,9 +1317,9 @@ public:
 
   static Expected<BuildInfoSym> deserialize(SymbolRecordKind Kind,
                                             uint32_t RecordOffset,
-                                            ArrayRef<uint8_t> &Data) {
+                                            msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
-    CV_DESERIALIZE(Data, H);
+    CV_DESERIALIZE(Reader, H);
 
     return BuildInfoSym(RecordOffset, H);
   }
@@ -1344,10 +1344,10 @@ public:
 
   static Expected<BPRelativeSym> deserialize(SymbolRecordKind Kind,
                                              uint32_t RecordOffset,
-                                             ArrayRef<uint8_t> &Data) {
+                                             msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return BPRelativeSym(RecordOffset, H, Name);
   }
@@ -1374,10 +1374,10 @@ public:
 
   static Expected<RegRelativeSym> deserialize(SymbolRecordKind Kind,
                                               uint32_t RecordOffset,
-                                              ArrayRef<uint8_t> &Data) {
+                                              msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return RegRelativeSym(RecordOffset, H, Name);
   }
@@ -1404,11 +1404,11 @@ public:
 
   static Expected<ConstantSym> deserialize(SymbolRecordKind Kind,
                                            uint32_t RecordOffset,
-                                           ArrayRef<uint8_t> &Data) {
+                                           msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     APSInt Value;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Value, Name);
+    CV_DESERIALIZE(Reader, H, Value, Name);
 
     return ConstantSym(RecordOffset, H, Value, Name);
   }
@@ -1436,10 +1436,10 @@ public:
 
   static Expected<DataSym> deserialize(SymbolRecordKind Kind,
                                        uint32_t RecordOffset,
-                                       ArrayRef<uint8_t> &Data) {
+                                       msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return DataSym(RecordOffset, H, Name);
   }
@@ -1470,10 +1470,10 @@ public:
 
   static Expected<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
                                                   uint32_t RecordOffset,
-                                                  ArrayRef<uint8_t> &Data) {
+                                                  msf::StreamReader &Reader) {
     const Hdr *H = nullptr;
     StringRef Name;
-    CV_DESERIALIZE(Data, H, Name);
+    CV_DESERIALIZE(Reader, H, Name);
 
     return ThreadLocalDataSym(RecordOffset, H, Name);
   }
index a4965168c3db7a015bd890390c13434ae5ce4c0a..f4449baf52d063ec4f67786ea5c6b77e6a33aa22 100644 (file)
 
 namespace llvm {
 
+namespace msf {
+class StreamReader;
+}
+
 namespace codeview {
 
 class SymbolVisitorDelegate {
 public:
   virtual ~SymbolVisitorDelegate() {}
 
-  virtual uint32_t getRecordOffset(ArrayRef<uint8_t> Record) = 0;
+  virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0;
   virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
   virtual StringRef getStringTable() = 0;
 };
index bf5c8251989e64b7506ffff47da000aed79f45c2..eb73ce0881048c2a5ee02024d98a33039539117e 100644 (file)
@@ -11,6 +11,8 @@
 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
 
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/Msf/ByteStream.h"
+#include "llvm/DebugInfo/Msf/StreamReader.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
@@ -32,12 +34,11 @@ public:
 #include "TypeRecords.def"
 
 protected:
-
   template <typename T>
-  Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+  Error deserializeRecord(msf::StreamReader &Reader, TypeLeafKind Kind,
                           T &Record) const {
     TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
-    auto ExpectedRecord = T::deserialize(RK, Data);
+    auto ExpectedRecord = T::deserialize(RK, Reader);
     if (!ExpectedRecord)
       return ExpectedRecord.takeError();
     Record = std::move(*ExpectedRecord);
@@ -46,15 +47,17 @@ protected:
 
 private:
   template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
-    ArrayRef<uint8_t> RD = CVR.content();
-    if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+    msf::ByteStream S(CVR.content());
+    msf::StreamReader SR(S);
+    if (auto EC = deserializeRecord(SR, CVR.Type, Record))
       return EC;
     return Error::success();
   }
   template <typename T>
   Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
-    ArrayRef<uint8_t> RD = CVMR.Data;
-    if (auto EC = deserializeRecord(RD, CVMR.Kind, Record))
+    msf::ByteStream S(CVMR.Data);
+    msf::StreamReader SR(S);
+    if (auto EC = deserializeRecord(SR, CVMR.Kind, Record))
       return EC;
     return Error::success();
   }
index 16800d95d7ab534bc316679426d0664dad68b279..35f0775d5c51e3d3e50cd34a046edd7b77d2b966 100644 (file)
 #include <utility>
 
 namespace llvm {
+
+namespace msf {
+class StreamReader;
+}
+
 namespace codeview {
 
 using llvm::support::little32_t;
@@ -92,7 +97,7 @@ public:
   /// is not in the map.
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data);
+  static Expected<MemberPointerInfo> deserialize(msf::StreamReader &Reader);
 
   TypeIndex getContainingType() const { return ContainingType; }
   PointerToMemberRepresentation getRepresentation() const {
@@ -134,7 +139,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<ModifierRecord> deserialize(TypeRecordKind Kind,
-                                              ArrayRef<uint8_t> &Data);
+                                              msf::StreamReader &Reader);
 
   TypeIndex getModifiedType() const { return ModifiedType; }
   ModifierOptions getModifiers() const { return Modifiers; }
@@ -165,7 +170,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<ProcedureRecord> deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data);
+                                               msf::StreamReader &Reader);
 
   static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
 
@@ -211,7 +216,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
-                                                    ArrayRef<uint8_t> &Data);
+                                                    msf::StreamReader &Reader);
 
   TypeIndex getReturnType() const { return ReturnType; }
   TypeIndex getClassType() const { return ClassType; }
@@ -258,7 +263,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
-                                                  ArrayRef<uint8_t> &Data);
+                                                  msf::StreamReader &Reader);
   TypeIndex getClassType() const { return ClassType; }
   TypeIndex getFunctionType() const { return FunctionType; }
   StringRef getName() const { return Name; }
@@ -287,7 +292,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<ArgListRecord> deserialize(TypeRecordKind Kind,
-                                             ArrayRef<uint8_t> &Data);
+                                             msf::StreamReader &Reader);
 
   ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
 
@@ -333,7 +338,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<PointerRecord> deserialize(TypeRecordKind Kind,
-                                             ArrayRef<uint8_t> &Data);
+                                             msf::StreamReader &Reader);
 
   TypeIndex getReferentType() const { return ReferentType; }
   PointerKind getPointerKind() const { return PtrKind; }
@@ -410,7 +415,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<NestedTypeRecord> deserialize(TypeRecordKind Kind,
-                                                ArrayRef<uint8_t> &Data);
+                                                msf::StreamReader &Reader);
 
   TypeIndex getNestedType() const { return Type; }
   StringRef getName() const { return Name; }
@@ -438,7 +443,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
 
   static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data);
+                                               msf::StreamReader &Reader);
 
   ArrayRef<uint8_t> Data;
 };
@@ -457,7 +462,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<ArrayRecord> deserialize(TypeRecordKind Kind,
-                                           ArrayRef<uint8_t> &Data);
+                                           msf::StreamReader &Reader);
 
   TypeIndex getElementType() const { return ElementType; }
   TypeIndex getIndexType() const { return IndexType; }
@@ -526,7 +531,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<ClassRecord> deserialize(TypeRecordKind Kind,
-                                           ArrayRef<uint8_t> &Data);
+                                           msf::StreamReader &Reader);
 
   HfaKind getHfa() const { return Hfa; }
   WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
@@ -568,7 +573,7 @@ struct UnionRecord : public TagRecord {
         Hfa(Hfa), Size(Size) {}
 
   static Expected<UnionRecord> deserialize(TypeRecordKind Kind,
-                                           ArrayRef<uint8_t> &Data);
+                                           msf::StreamReader &Reader);
 
   HfaKind getHfa() const { return Hfa; }
   uint64_t getSize() const { return Size; }
@@ -605,7 +610,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<EnumRecord> deserialize(TypeRecordKind Kind,
-                                          ArrayRef<uint8_t> &Data);
+                                          msf::StreamReader &Reader);
 
   TypeIndex getUnderlyingType() const { return UnderlyingType; }
   TypeIndex UnderlyingType;
@@ -638,7 +643,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<BitFieldRecord> deserialize(TypeRecordKind Kind,
-                                              ArrayRef<uint8_t> &Data);
+                                              msf::StreamReader &Reader);
 
   TypeIndex getType() const { return Type; }
   uint8_t getBitOffset() const { return BitOffset; }
@@ -670,7 +675,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
-                                                  ArrayRef<uint8_t> &Data);
+                                                  msf::StreamReader &Reader);
 
   ArrayRef<VFTableSlotKind> getSlots() const {
     if (!SlotsRef.empty())
@@ -705,7 +710,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<TypeServer2Record> deserialize(TypeRecordKind Kind,
-                                                 ArrayRef<uint8_t> &Data);
+                                                 msf::StreamReader &Reader);
 
   StringRef getGuid() const { return Guid; }
 
@@ -736,7 +741,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<StringIdRecord> deserialize(TypeRecordKind Kind,
-                                              ArrayRef<uint8_t> &Data);
+                                              msf::StreamReader &Reader);
 
   TypeIndex getId() const { return Id; }
 
@@ -764,7 +769,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<FuncIdRecord> deserialize(TypeRecordKind Kind,
-                                            ArrayRef<uint8_t> &Data);
+                                            msf::StreamReader &Reader);
 
   TypeIndex getParentScope() const { return ParentScope; }
 
@@ -797,7 +802,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
-                                                   ArrayRef<uint8_t> &Data);
+                                                   msf::StreamReader &Reader);
 
   TypeIndex getUDT() const { return UDT; }
   TypeIndex getSourceFile() const { return SourceFile; }
@@ -826,10 +831,10 @@ public:
 
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind,
-                                                      ArrayRef<uint8_t> &Data) {
+  static Expected<UdtModSourceLineRecord>
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
     const Layout *L = nullptr;
-    CV_DESERIALIZE(Data, L);
+    CV_DESERIALIZE(Reader, L);
 
     return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
                                   L->Module);
@@ -867,7 +872,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<BuildInfoRecord> deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data);
+                                               msf::StreamReader &Reader);
 
   ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
   SmallVector<TypeIndex, 4> ArgIndices;
@@ -901,7 +906,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<VFTableRecord> deserialize(TypeRecordKind Kind,
-                                             ArrayRef<uint8_t> &Data);
+                                             msf::StreamReader &Reader);
 
   TypeIndex getCompleteClass() const { return CompleteClass; }
   TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
@@ -947,7 +952,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<OneMethodRecord> deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data);
+                                               msf::StreamReader &Reader);
 
   TypeIndex getType() const { return Type; }
   MethodKind getKind() const { return Kind; }
@@ -990,7 +995,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<MethodOverloadListRecord>
-  deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data);
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
 
   ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
   std::vector<OneMethodRecord> Methods;
@@ -1020,8 +1025,8 @@ public:
   /// is not in the map.
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
-                                                      ArrayRef<uint8_t> &Data);
+  static Expected<OverloadedMethodRecord>
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
 
   uint16_t getNumOverloads() const { return NumOverloads; }
   TypeIndex getMethodList() const { return MethodList; }
@@ -1053,7 +1058,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<DataMemberRecord> deserialize(TypeRecordKind Kind,
-                                                ArrayRef<uint8_t> &Data);
+                                                msf::StreamReader &Reader);
 
   MemberAccess getAccess() const { return Access; }
   TypeIndex getType() const { return Type; }
@@ -1086,8 +1091,8 @@ public:
   /// is not in the map.
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
-                                                      ArrayRef<uint8_t> &Data);
+  static Expected<StaticDataMemberRecord>
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
 
   MemberAccess getAccess() const { return Access; }
   TypeIndex getType() const { return Type; }
@@ -1118,7 +1123,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<EnumeratorRecord> deserialize(TypeRecordKind Kind,
-                                                ArrayRef<uint8_t> &Data);
+                                                msf::StreamReader &Reader);
 
   MemberAccess getAccess() const { return Access; }
   APSInt getValue() const { return Value; }
@@ -1148,7 +1153,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<VFPtrRecord> deserialize(TypeRecordKind Kind,
-                                           ArrayRef<uint8_t> &Data);
+                                           msf::StreamReader &Reader);
 
   TypeIndex getType() const { return Type; }
   TypeIndex Type;
@@ -1173,7 +1178,7 @@ public:
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
   static Expected<BaseClassRecord> deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data);
+                                               msf::StreamReader &Reader);
 
   MemberAccess getAccess() const { return Access; }
   TypeIndex getBaseType() const { return Type; }
@@ -1204,8 +1209,8 @@ public:
   /// is not in the map.
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
-                                                      ArrayRef<uint8_t> &Data);
+  static Expected<VirtualBaseClassRecord>
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
 
   MemberAccess getAccess() const { return Access; }
   TypeIndex getBaseType() const { return BaseType; }
@@ -1241,8 +1246,8 @@ public:
 
   bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
 
-  static Expected<ListContinuationRecord> deserialize(TypeRecordKind Kind,
-                                                      ArrayRef<uint8_t> &Data);
+  static Expected<ListContinuationRecord>
+  deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
   TypeIndex ContinuationIndex;
 
 private:
index 737693aa00997fea4e980596b4c7200caba06601..34361ef9d9323bca23f951f88346e961442a4572 100644 (file)
@@ -28,6 +28,8 @@ class ByteStream : public ReadableStream {
 public:
   ByteStream() {}
   explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
+  explicit ByteStream(StringRef Data)
+      : Data(Data.bytes_begin(), Data.bytes_end()) {}
 
   Error readBytes(uint32_t Offset, uint32_t Size,
                   ArrayRef<uint8_t> &Buffer) const override {
index 5c971e08491f41cfb1cdb1a23f80e54001a625cb..fc2ca78dc18f493ef2682b220e46f91f1f8997a8 100644 (file)
@@ -29,8 +29,14 @@ public:
 
   Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
   Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
+  Error readInteger(uint8_t &Dest);
   Error readInteger(uint16_t &Dest);
   Error readInteger(uint32_t &Dest);
+  Error readInteger(uint64_t &Dest);
+  Error readInteger(int8_t &Dest);
+  Error readInteger(int16_t &Dest);
+  Error readInteger(int32_t &Dest);
+  Error readInteger(int64_t &Dest);
   Error readZeroString(StringRef &Dest);
   Error readFixedString(StringRef &Dest, uint32_t Length);
   Error readStreamRef(ReadableStreamRef &Ref);
@@ -101,6 +107,10 @@ public:
   uint32_t getLength() const { return Stream.getLength(); }
   uint32_t bytesRemaining() const { return getLength() - getOffset(); }
 
+  Error skip(uint32_t Amount);
+
+  uint8_t peek() const;
+
 private:
   ReadableStreamRef Stream;
   uint32_t Offset;
index deefa8d4ef0e0ba5b1dbcd7c7bbe1fc1605d9e27..2dee8988df944f3ac483c674ee1737a877bfb2b3 100644 (file)
 using namespace llvm;
 using namespace llvm::codeview;
 
-template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
-  if (Data.size() < sizeof(*Res))
-    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-  Res = reinterpret_cast<const T *>(Data.data());
-  Data = Data.drop_front(sizeof(*Res));
-  return Error::success();
-}
-
-static Error skipPadding(ArrayRef<uint8_t> &Data) {
-  if (Data.empty())
+static Error skipPadding(msf::StreamReader &Reader) {
+  if (Reader.empty())
     return Error::success();
-  uint8_t Leaf = Data.front();
+
+  uint8_t Leaf = Reader.peek();
   if (Leaf < LF_PAD0)
     return Error::success();
   // Leaf is greater than 0xf0. We should advance by the number of bytes in
   // the low 4 bits.
   unsigned BytesToAdvance = Leaf & 0x0F;
-  if (Data.size() < BytesToAdvance) {
-    return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
-                                           "Invalid padding bytes!");
-  }
-  Data = Data.drop_front(BytesToAdvance);
-  return Error::success();
+  return Reader.skip(BytesToAdvance);
 }
 
 template <typename T>
-static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
-                                                        TypeLeafKind Kind) {
-  ArrayRef<uint8_t> OldData = Data;
+static Expected<CVMemberRecord>
+deserializeMemberRecord(msf::StreamReader &Reader, TypeLeafKind Kind) {
+  msf::StreamReader OldReader = Reader;
   TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
-  auto ExpectedRecord = T::deserialize(RK, Data);
+  auto ExpectedRecord = T::deserialize(RK, Reader);
   if (!ExpectedRecord)
     return ExpectedRecord.takeError();
-  assert(Data.size() < OldData.size());
-  if (auto EC = skipPadding(Data))
+  assert(Reader.bytesRemaining() < OldReader.bytesRemaining());
+  if (auto EC = skipPadding(Reader))
     return std::move(EC);
 
   CVMemberRecord CVMR;
   CVMR.Kind = Kind;
-  CVMR.Data = OldData.drop_back(Data.size());
+
+  uint32_t RecordLength = OldReader.bytesRemaining() - Reader.bytesRemaining();
+  if (auto EC = OldReader.readBytes(CVMR.Data, RecordLength))
+    return std::move(EC);
+
   return CVMR;
 }
 
@@ -147,9 +138,9 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
 }
 
 template <typename MR>
-static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
+static Error visitKnownMember(msf::StreamReader &Reader, TypeLeafKind Leaf,
                               TypeVisitorCallbacks &Callbacks) {
-  auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf);
+  auto ExpectedRecord = deserializeMemberRecord<MR>(Reader, Leaf);
   if (!ExpectedRecord)
     return ExpectedRecord.takeError();
   CVMemberRecord &Record = *ExpectedRecord;
@@ -162,13 +153,12 @@ static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
   return Error::success();
 }
 
-Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
-  while (!Data.empty()) {
-    const support::ulittle16_t *LeafValue;
-    if (auto EC = takeObject(Data, LeafValue))
+Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
+  TypeLeafKind Leaf;
+  while (!Reader.empty()) {
+    if (auto EC = Reader.readEnum(Leaf))
       return EC;
 
-    TypeLeafKind Leaf = static_cast<TypeLeafKind>(uint16_t(*LeafValue));
     CVType Record;
     switch (Leaf) {
     default:
@@ -178,7 +168,7 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
           cv_error_code::unknown_member_record);
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
   case EnumName: {                                                             \
-    if (auto EC = visitKnownMember<Name##Record>(Data, Leaf, Callbacks))       \
+    if (auto EC = visitKnownMember<Name##Record>(Reader, Leaf, Callbacks))     \
       return EC;                                                               \
     break;                                                                     \
   }
@@ -189,3 +179,9 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
   }
   return Error::success();
 }
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+  msf::ByteStream S(Data);
+  msf::StreamReader SR(S);
+  return visitFieldListMemberStream(SR);
+}
index 9386d29f223632ac9ce0a91b7c4aded1222e478b..6f29caa9bbfc154dc74709548ea39bcf0bc88298 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/ADT/APSInt.h"
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -32,114 +33,88 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
   return getBytesAsCharacters(LeafData).split('\0').first;
 }
 
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
+Error llvm::codeview::consume(msf::StreamReader &Reader, APSInt &Num) {
   // Used to avoid overload ambiguity on APInt construtor.
   bool FalseVal = false;
-  if (Data.size() < 2)
-    return make_error<CodeViewError>(
-        cv_error_code::insufficient_buffer,
-        "Buffer does not contain enough data for an APSInt");
-  uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
-  Data = Data.drop_front(2);
+  uint16_t Short;
+  if (auto EC = Reader.readInteger(Short))
+    return EC;
+
   if (Short < LF_NUMERIC) {
     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
                  /*isUnsigned=*/true);
     return Error::success();
   }
+
   switch (Short) {
-  case LF_CHAR:
-    if (Data.size() < 1)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_CHAR");
-    Num = APSInt(APInt(/*numBits=*/8,
-                       *reinterpret_cast<const int8_t *>(Data.data()),
-                       /*isSigned=*/true),
-                 /*isUnsigned=*/false);
-    Data = Data.drop_front(1);
+  case LF_CHAR: {
+    int8_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(8, N, true), false);
     return Error::success();
-  case LF_SHORT:
-    if (Data.size() < 2)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_SHORT");
-    Num = APSInt(APInt(/*numBits=*/16,
-                       *reinterpret_cast<const little16_t *>(Data.data()),
-                       /*isSigned=*/true),
-                 /*isUnsigned=*/false);
-    Data = Data.drop_front(2);
+  }
+  case LF_SHORT: {
+    int16_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(16, N, true), false);
     return Error::success();
-  case LF_USHORT:
-    if (Data.size() < 2)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_USHORT");
-    Num = APSInt(APInt(/*numBits=*/16,
-                       *reinterpret_cast<const ulittle16_t *>(Data.data()),
-                       /*isSigned=*/false),
-                 /*isUnsigned=*/true);
-    Data = Data.drop_front(2);
+  }
+  case LF_USHORT: {
+    uint16_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(16, N, false), true);
     return Error::success();
-  case LF_LONG:
-    if (Data.size() < 4)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_LONG");
-    Num = APSInt(APInt(/*numBits=*/32,
-                       *reinterpret_cast<const little32_t *>(Data.data()),
-                       /*isSigned=*/true),
-                 /*isUnsigned=*/false);
-    Data = Data.drop_front(4);
+  }
+  case LF_LONG: {
+    int32_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(32, N, true), false);
     return Error::success();
-  case LF_ULONG:
-    if (Data.size() < 4)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_ULONG");
-    Num = APSInt(APInt(/*numBits=*/32,
-                       *reinterpret_cast<const ulittle32_t *>(Data.data()),
-                       /*isSigned=*/FalseVal),
-                 /*isUnsigned=*/true);
-    Data = Data.drop_front(4);
+  }
+  case LF_ULONG: {
+    uint32_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(32, N, FalseVal), true);
     return Error::success();
-  case LF_QUADWORD:
-    if (Data.size() < 8)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_QUADWORD");
-    Num = APSInt(APInt(/*numBits=*/64,
-                       *reinterpret_cast<const little64_t *>(Data.data()),
-                       /*isSigned=*/true),
-                 /*isUnsigned=*/false);
-    Data = Data.drop_front(8);
+  }
+  case LF_QUADWORD: {
+    int64_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(64, N, true), false);
     return Error::success();
-  case LF_UQUADWORD:
-    if (Data.size() < 8)
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Buffer does not contain enough data for an LF_UQUADWORD");
-    Num = APSInt(APInt(/*numBits=*/64,
-                       *reinterpret_cast<const ulittle64_t *>(Data.data()),
-                       /*isSigned=*/false),
-                 /*isUnsigned=*/true);
-    Data = Data.drop_front(8);
+  }
+  case LF_UQUADWORD: {
+    uint64_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(64, N, false), true);
     return Error::success();
   }
+  }
   return make_error<CodeViewError>(cv_error_code::corrupt_record,
                                    "Buffer contains invalid APSInt type");
 }
 
 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
-  auto EC = consume(Bytes, Num);
-  Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+  msf::ByteStream S(Bytes);
+  msf::StreamReader SR(S);
+  auto EC = consume(SR, Num);
+  Data = Data.take_back(SR.bytesRemaining());
   return EC;
 }
 
 /// Decode a numeric leaf value that is known to be a uint64_t.
-Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
+Error llvm::codeview::consume_numeric(msf::StreamReader &Reader,
+                                      uint64_t &Num) {
   APSInt N;
-  if (auto EC = consume(Data, N))
+  if (auto EC = consume(Reader, N))
     return EC;
   if (N.isSigned() || !N.isIntN(64))
     return make_error<CodeViewError>(cv_error_code::corrupt_record,
@@ -148,41 +123,27 @@ Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
   return Error::success();
 }
 
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) {
-  const support::ulittle32_t *IntPtr;
-  if (auto EC = consumeObject(Data, IntPtr))
-    return EC;
-  Item = *IntPtr;
-  return Error::success();
+Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
+  return Reader.readInteger(Item);
 }
 
 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
-  auto EC = consume(Bytes, Item);
-  Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+  msf::ByteStream S(Bytes);
+  msf::StreamReader SR(S);
+  auto EC = consume(SR, Item);
+  Data = Data.take_back(SR.bytesRemaining());
   return EC;
 }
 
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) {
-  const support::little32_t *IntPtr;
-  if (auto EC = consumeObject(Data, IntPtr))
-    return EC;
-  Item = *IntPtr;
-  return Error::success();
+Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
+  return Reader.readInteger(Item);
 }
 
-Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) {
-  if (Data.empty())
+Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) {
+  if (Reader.empty())
     return make_error<CodeViewError>(cv_error_code::corrupt_record,
                                      "Null terminated string buffer is empty!");
 
-  StringRef Rest;
-  std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
-  // We expect this to be null terminated.  If it was not, it is an error.
-  if (Data.size() == Item.size())
-    return make_error<CodeViewError>(cv_error_code::corrupt_record,
-                                     "Expected null terminator!");
-
-  Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
-  return Error::success();
+  return Reader.readZeroString(Item);
 }
index 47aa04fe76ae7c53809f5515c2f61b02967b9811..a7a1bb9228ca8c3b26c919332fc43f594ca69c50 100644 (file)
@@ -11,6 +11,7 @@
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -20,9 +21,9 @@ using namespace llvm::codeview;
 //===----------------------------------------------------------------------===//
 
 Expected<MemberPointerInfo>
-MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
+MemberPointerInfo::deserialize(msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
 
   TypeIndex T = L->ClassType;
@@ -32,10 +33,10 @@ MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
   return MemberPointerInfo(T, PMR);
 }
 
-Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
-                                                     ArrayRef<uint8_t> &Data) {
+Expected<ModifierRecord>
+ModifierRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
 
   TypeIndex M = L->ModifiedType;
@@ -45,9 +46,9 @@ Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
 }
 
 Expected<ProcedureRecord>
-ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ProcedureRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
   return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
                          L->NumParameters, L->ArgListType);
@@ -55,24 +56,25 @@ ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
 
 Expected<MemberFunctionRecord>
 MemberFunctionRecord::deserialize(TypeRecordKind Kind,
-                                  ArrayRef<uint8_t> &Data) {
+                                  msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  CV_DESERIALIZE(Data, L);
+  CV_DESERIALIZE(Reader, L);
   return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
                               L->CallConv, L->Options, L->NumParameters,
                               L->ArgListType, L->ThisAdjustment);
 }
 
 Expected<MemberFuncIdRecord>
-MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+MemberFuncIdRecord::deserialize(TypeRecordKind Kind,
+                                msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
 }
 
 Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
-                                                   ArrayRef<uint8_t> &Data) {
+                                                   msf::StreamReader &Reader) {
   if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
     return make_error<CodeViewError>(
         cv_error_code::corrupt_record,
@@ -80,14 +82,14 @@ Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
 
   const Layout *L = nullptr;
   ArrayRef<TypeIndex> Indices;
-  CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+  CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
   return ArgListRecord(Kind, Indices);
 }
 
 Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
-                                                   ArrayRef<uint8_t> &Data) {
+                                                   msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
 
   PointerKind PtrKind = L->getPtrKind();
@@ -97,7 +99,7 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
   uint8_t Size = L->getPtrSize();
 
   if (L->isPointerToMember()) {
-    if (auto ExpectedMPI = MemberPointerInfo::deserialize(Data))
+    if (auto ExpectedMPI = MemberPointerInfo::deserialize(Reader))
       return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size,
                            *ExpectedMPI);
     else
@@ -108,38 +110,39 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
 }
 
 Expected<NestedTypeRecord>
-NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+NestedTypeRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return NestedTypeRecord(L->Type, Name);
 }
 
 Expected<FieldListRecord>
-FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
-  auto FieldListData = Data;
-  Data = ArrayRef<uint8_t>();
-  return FieldListRecord(FieldListData);
+FieldListRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
+  ArrayRef<uint8_t> Data;
+  if (auto EC = Reader.readBytes(Data, Reader.bytesRemaining()))
+    return std::move(EC);
+  return FieldListRecord(Data);
 }
 
 Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data) {
+                                               msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   uint64_t Size;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name);
   return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
 }
 
 Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data) {
+                                               msf::StreamReader &Reader) {
   uint64_t Size = 0;
   StringRef Name;
   StringRef UniqueName;
   uint16_t Props;
   const Layout *L = nullptr;
 
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
                  CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
 
   Props = L->Properties;
@@ -154,14 +157,14 @@ Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
 }
 
 Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data) {
+                                               msf::StreamReader &Reader) {
   uint64_t Size = 0;
   StringRef Name;
   StringRef UniqueName;
   uint16_t Props;
 
   const Layout *L = nullptr;
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Size), Name,
                  CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
 
   Props = L->Properties;
@@ -174,11 +177,11 @@ Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
 }
 
 Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
-                                             ArrayRef<uint8_t> &Data) {
+                                             msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
   StringRef UniqueName;
-  CV_DESERIALIZE(Data, L, Name,
+  CV_DESERIALIZE(Reader, L, Name,
                  CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
 
   uint16_t P = L->Properties;
@@ -187,97 +190,98 @@ Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
                     UniqueName, L->UnderlyingType);
 }
 
-Expected<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind,
-                                                     ArrayRef<uint8_t> &Data) {
+Expected<BitFieldRecord>
+BitFieldRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  CV_DESERIALIZE(Data, L);
+  CV_DESERIALIZE(Reader, L);
   return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
 }
 
 Expected<VFTableShapeRecord>
-VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+VFTableShapeRecord::deserialize(TypeRecordKind Kind,
+                                msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
 
   std::vector<VFTableSlotKind> Slots;
   uint16_t Count = L->VFEntryCount;
   while (Count > 0) {
-    if (Data.empty())
-      return make_error<CodeViewError>(cv_error_code::corrupt_record,
-                                       "VTableShapeRecord contains no entries");
-
     // Process up to 2 nibbles at a time (if there are at least 2 remaining)
-    uint8_t Value = Data[0] & 0x0F;
+    uint8_t Data;
+    if (auto EC = Reader.readInteger(Data))
+      return std::move(EC);
+
+    uint8_t Value = Data & 0x0F;
     Slots.push_back(static_cast<VFTableSlotKind>(Value));
     if (--Count > 0) {
-      Value = (Data[0] & 0xF0) >> 4;
+      Value = (Data & 0xF0) >> 4;
       Slots.push_back(static_cast<VFTableSlotKind>(Value));
       --Count;
     }
-    Data = Data.slice(1);
   }
 
   return VFTableShapeRecord(Slots);
 }
 
 Expected<TypeServer2Record>
-TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+TypeServer2Record::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
 }
 
-Expected<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
-                                                     ArrayRef<uint8_t> &Data) {
+Expected<StringIdRecord>
+StringIdRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return StringIdRecord(L->id, Name);
 }
 
 Expected<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
-                                                 ArrayRef<uint8_t> &Data) {
+                                                 msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
 }
 
 Expected<UdtSourceLineRecord>
-UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+UdtSourceLineRecord::deserialize(TypeRecordKind Kind,
+                                 msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  CV_DESERIALIZE(Data, L);
+  CV_DESERIALIZE(Reader, L);
   return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
 }
 
 Expected<BuildInfoRecord>
-BuildInfoRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+BuildInfoRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   ArrayRef<TypeIndex> Indices;
-  CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+  CV_DESERIALIZE(Reader, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
   return BuildInfoRecord(Indices);
 }
 
 Expected<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
-                                                   ArrayRef<uint8_t> &Data) {
+                                                   msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
   std::vector<StringRef> Names;
-  CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names));
+  CV_DESERIALIZE(Reader, L, Name, CV_ARRAY_FIELD_TAIL(Names));
   return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
                        Name, Names);
 }
 
 Expected<OneMethodRecord>
-OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+OneMethodRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
   int32_t VFTableOffset = -1;
 
-  CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset,
-                                               L->Attrs.isIntroducedVirtual()),
+  CV_DESERIALIZE(Reader, L, CV_CONDITIONAL_FIELD(
+                                VFTableOffset, L->Attrs.isIntroducedVirtual()),
                  Name);
 
   MethodOptions Options = L->Attrs.getFlags();
@@ -294,13 +298,14 @@ OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
 
 Expected<MethodOverloadListRecord>
 MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
-                                      ArrayRef<uint8_t> &Data) {
+                                      msf::StreamReader &Reader) {
   std::vector<OneMethodRecord> Methods;
-  while (!Data.empty()) {
+  while (!Reader.empty()) {
     const Layout *L = nullptr;
     int32_t VFTableOffset = -1;
-    CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(
-                                VFTableOffset, L->Attrs.isIntroducedVirtual()));
+    CV_DESERIALIZE(
+        Reader, L,
+        CV_CONDITIONAL_FIELD(VFTableOffset, L->Attrs.isIntroducedVirtual()));
 
     MethodOptions Options = L->Attrs.getFlags();
     MethodKind MethKind = L->Attrs.getMethodKind();
@@ -320,72 +325,72 @@ MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
 
 Expected<OverloadedMethodRecord>
 OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
-                                    ArrayRef<uint8_t> &Data) {
+                                    msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
 }
 
 Expected<DataMemberRecord>
-DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+DataMemberRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   uint64_t Offset;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset), Name);
   return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
 }
 
 Expected<StaticDataMemberRecord>
 StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
-                                    ArrayRef<uint8_t> &Data) {
+                                    msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Name);
+  CV_DESERIALIZE(Reader, L, Name);
   return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
 }
 
 Expected<EnumeratorRecord>
-EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+EnumeratorRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   APSInt Value;
   StringRef Name;
-  CV_DESERIALIZE(Data, L, Value, Name);
+  CV_DESERIALIZE(Reader, L, Value, Name);
   return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
 }
 
 Expected<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
-                                               ArrayRef<uint8_t> &Data) {
+                                               msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  if (auto EC = consumeObject(Data, L))
+  if (auto EC = Reader.readObject(L))
     return std::move(EC);
   return VFPtrRecord(L->Type);
 }
 
 Expected<BaseClassRecord>
-BaseClassRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+BaseClassRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   uint64_t Offset;
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset));
   return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
 }
 
 Expected<VirtualBaseClassRecord>
 VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
-                                    ArrayRef<uint8_t> &Data) {
+                                    msf::StreamReader &Reader) {
   const Layout *L = nullptr;
   uint64_t Offset;
   uint64_t Index;
-  CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
+  CV_DESERIALIZE(Reader, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
   return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
                                 Offset, Index);
 }
 
 Expected<ListContinuationRecord>
 ListContinuationRecord::deserialize(TypeRecordKind Kind,
-                                    ArrayRef<uint8_t> &Data) {
+                                    msf::StreamReader &Reader) {
   const Layout *L = nullptr;
-  CV_DESERIALIZE(Data, L);
+  CV_DESERIALIZE(Reader, L);
   return ListContinuationRecord(L->ContinuationIndex);
 }
 
index eb3d3e82d4d23c0b487769fa6d141f23a3bb6ded..b85fd14a3b7f70acd326049ab10317bcf89d2ea3 100644 (file)
@@ -31,6 +31,14 @@ Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
   return Error::success();
 }
 
+Error StreamReader::readInteger(uint8_t &Dest) {
+  const uint8_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
 Error StreamReader::readInteger(uint16_t &Dest) {
   const support::ulittle16_t *P;
   if (auto EC = readObject(P))
@@ -47,6 +55,46 @@ Error StreamReader::readInteger(uint32_t &Dest) {
   return Error::success();
 }
 
+Error StreamReader::readInteger(uint64_t &Dest) {
+  const support::ulittle64_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
+Error StreamReader::readInteger(int8_t &Dest) {
+  const int8_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
+Error StreamReader::readInteger(int16_t &Dest) {
+  const support::little16_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
+Error StreamReader::readInteger(int32_t &Dest) {
+  const support::little32_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
+Error StreamReader::readInteger(int64_t &Dest) {
+  const support::little64_t *P;
+  if (auto EC = readObject(P))
+    return EC;
+  Dest = *P;
+  return Error::success();
+}
+
 Error StreamReader::readZeroString(StringRef &Dest) {
   uint32_t Length = 0;
   // First compute the length of the string by reading 1 byte at a time.
@@ -91,3 +139,18 @@ Error StreamReader::readStreamRef(ReadableStreamRef &Ref, uint32_t Length) {
   Offset += Length;
   return Error::success();
 }
+
+Error StreamReader::skip(uint32_t Amount) {
+  if (Amount > bytesRemaining())
+    return make_error<MSFError>(msf_error_code::insufficient_buffer);
+  Offset += Amount;
+  return Error::success();
+}
+
+uint8_t StreamReader::peek() const {
+  ArrayRef<uint8_t> Buffer;
+  auto EC = Stream.readBytes(Offset, 1, Buffer);
+  assert(!EC && "Cannot peek an empty buffer!");
+  llvm::consumeError(std::move(EC));
+  return Buffer[0];
+}
index 2b45d1de1434a1b968884dc5f91ffbef73906d93..73118eb7cd0744379f1087231c8c4b907e5a3931 100644 (file)
@@ -154,8 +154,13 @@ public:
     Sec = Obj->getCOFFSection(SR);
   }
 
-  uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override {
-    return Record.data() - SectionContents.bytes_begin();
+  uint32_t getRecordOffset(msf::StreamReader Reader) override {
+    ArrayRef<uint8_t> Data;
+    if (auto EC = Reader.readLongestContiguousChunk(Data)) {
+      llvm::consumeError(std::move(EC));
+      return 0;
+    }
+    return Data.data() - SectionContents.bytes_begin();
   }
 
   void printRelocatedField(StringRef Label, uint32_t RelocOffset,
@@ -835,8 +840,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
     }
     case ModuleSubstreamKind::FrameData: {
       // First four bytes is a relocation against the function.
+      msf::ByteStream S(Contents);
+      msf::StreamReader SR(S);
       const uint32_t *CodePtr;
-      error(consumeObject(Contents, CodePtr));
+      error(SR.readObject(CodePtr));
       StringRef LinkageName;
       error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
                               CodePtr, LinkageName));
@@ -844,9 +851,9 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
 
       // To find the active frame description, search this array for the
       // smallest PC range that includes the current PC.
-      while (!Contents.empty()) {
+      while (!SR.empty()) {
         const FrameData *FD;
-        error(consumeObject(Contents, FD));
+        error(SR.readObject(FD));
 
         if (FD->FrameFunc >= CVStringTable.size())
           error(object_error::parse_failed);
@@ -974,11 +981,12 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
 }
 
 void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
-  StringRef Data = Subsection;
-  while (!Data.empty()) {
+  msf::ByteStream S(Subsection);
+  msf::StreamReader SR(S);
+  while (!SR.empty()) {
     DictScope S(W, "FileChecksum");
     const FileChecksum *FC;
-    error(consumeObject(Data, FC));
+    error(SR.readObject(FC));
     if (FC->FileNameOffset >= CVStringTable.size())
       error(object_error::parse_failed);
     StringRef Filename =
@@ -987,27 +995,30 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
     W.printHex("ChecksumSize", FC->ChecksumSize);
     W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind),
                 makeArrayRef(FileChecksumKindNames));
-    if (FC->ChecksumSize >= Data.size())
+    if (FC->ChecksumSize >= SR.bytesRemaining())
       error(object_error::parse_failed);
-    StringRef ChecksumBytes = Data.substr(0, FC->ChecksumSize);
+    ArrayRef<uint8_t> ChecksumBytes;
+    error(SR.readBytes(ChecksumBytes, FC->ChecksumSize));
     W.printBinary("ChecksumBytes", ChecksumBytes);
     unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) -
                           sizeof(FileChecksum);
-    if (PaddedSize > Data.size())
+    PaddedSize -= ChecksumBytes.size();
+    if (PaddedSize > SR.bytesRemaining())
       error(object_error::parse_failed);
-    Data = Data.drop_front(PaddedSize);
+    error(SR.skip(PaddedSize));
   }
 }
 
 void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
-  StringRef Data = Subsection;
+  msf::ByteStream S(Subsection);
+  msf::StreamReader SR(S);
   uint32_t Signature;
-  error(consume(Data, Signature));
+  error(SR.readInteger(Signature));
   bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
 
-  while (!Data.empty()) {
+  while (!SR.empty()) {
     const InlineeSourceLine *ISL;
-    error(consumeObject(Data, ISL));
+    error(SR.readObject(ISL));
     DictScope S(W, "InlineeSourceLine");
     printTypeIndex("Inlinee", ISL->Inlinee);
     printFileNameForOffset("FileID", ISL->FileID);
@@ -1015,12 +1026,12 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
 
     if (HasExtraFiles) {
       uint32_t ExtraFileCount;
-      error(consume(Data, ExtraFileCount));
+      error(SR.readInteger(ExtraFileCount));
       W.printNumber("ExtraFileCount", ExtraFileCount);
       ListScope ExtraFiles(W, "ExtraFiles");
       for (unsigned I = 0; I < ExtraFileCount; ++I) {
         uint32_t FileID;
-        error(consume(Data, FileID));
+        error(SR.readInteger(FileID));
         printFileNameForOffset("FileID", FileID);
       }
     }