Index: include/llvm/DebugInfo/CodeView/CVTypeVisitor.h =================================================================== --- include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -30,6 +30,7 @@ Error visitTypeStream(const CVTypeArray &Types); Error visitFieldListMemberStream(ArrayRef FieldList); + Error visitFieldListMemberStream(msf::StreamReader Reader); private: /// The interface to the class that gets notified of each visitation. Index: include/llvm/DebugInfo/CodeView/RecordSerialization.h =================================================================== --- include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -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 @@ -40,53 +41,40 @@ StringRef getBytesAsCharacters(ArrayRef LeafData); StringRef getBytesAsCString(ArrayRef 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 -inline Error consumeObject(U &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return make_error( - cv_error_code::insufficient_buffer, - "Insufficient bytes for expected object type"); - Res = reinterpret_cast(Data.data()); - Data = Data.drop_front(sizeof(*Res)); - return Error::success(); -} - -inline Error consume(ArrayRef &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 &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 &Data, uint64_t &Value); +Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value); /// Decodes signed and unsigned fixed-length integers. -Error consume(ArrayRef &Data, uint32_t &Item); -Error consume(StringRef &Data, uint32_t &Item); -Error consume(ArrayRef &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 &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 Error consume(ArrayRef &Data, T *&Item) { - return consumeObject(Data, Item); +template Error consume(msf::StreamReader &Reader, T *&Item) { + return Reader.readObject(Item); } template struct serialize_conditional_impl { serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {} - Error deserialize(ArrayRef &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 @@ template struct serialize_array_impl { serialize_array_impl(ArrayRef &Item, U Func) : Item(Item), Func(Func) {} - Error deserialize(ArrayRef &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( - cv_error_code::corrupt_record, - "Array length is not a multiple of sizeof(T)"); - - if (Data.size() < Size) - return make_error( - cv_error_code::corrupt_record, - "Array does not contain enough data for all elements"); - - Item = ArrayRef(reinterpret_cast(Data.data()), N); - Data = Data.drop_front(Size); - return Error::success(); + Error deserialize(msf::StreamReader &Reader) const { + return Reader.readArray(Item, Func()); } ArrayRef &Item; @@ -130,11 +100,11 @@ template struct serialize_vector_tail_impl { serialize_vector_tail_impl(std::vector &Item) : Item(Item) {} - Error deserialize(ArrayRef &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 @@ serialize_null_term_string_array_impl(std::vector &Item) : Item(Item) {} - Error deserialize(ArrayRef &Data) const { - if (Data.empty()) + Error deserialize(msf::StreamReader &Reader) const { + if (Reader.empty()) return make_error(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( - 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 &Item; @@ -174,10 +138,9 @@ template struct serialize_arrayref_tail_impl { serialize_arrayref_tail_impl(ArrayRef &Item) : Item(Item) {} - Error deserialize(ArrayRef &Data) const { - uint32_t Count = Data.size() / sizeof(T); - Item = ArrayRef(reinterpret_cast(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 &Item; @@ -186,8 +149,8 @@ template struct serialize_numeric_impl { serialize_numeric_impl(T &Item) : Item(Item) {} - Error deserialize(ArrayRef &Data) const { - return consume_numeric(Data, Item); + Error deserialize(msf::StreamReader &Reader) const { + return consume_numeric(Reader, Item); } T &Item; @@ -238,43 +201,45 @@ #define CV_NUMERIC_FIELD(I) serialize_numeric(I) template -Error consume(ArrayRef &Data, +Error consume(msf::StreamReader &Reader, const serialize_conditional_impl &Item) { - return Item.deserialize(Data); + return Item.deserialize(Reader); } template -Error consume(ArrayRef &Data, const serialize_array_impl &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_array_impl &Item) { + return Item.deserialize(Reader); } -inline Error consume(ArrayRef &Data, +inline Error consume(msf::StreamReader &Reader, const serialize_null_term_string_array_impl &Item) { - return Item.deserialize(Data); + return Item.deserialize(Reader); } template -Error consume(ArrayRef &Data, +Error consume(msf::StreamReader &Reader, const serialize_vector_tail_impl &Item) { - return Item.deserialize(Data); + return Item.deserialize(Reader); } template -Error consume(ArrayRef &Data, +Error consume(msf::StreamReader &Reader, const serialize_arrayref_tail_impl &Item) { - return Item.deserialize(Data); + return Item.deserialize(Reader); } template -Error consume(ArrayRef &Data, const serialize_numeric_impl &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_numeric_impl &Item) { + return Item.deserialize(Reader); } template -Error consume(ArrayRef &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(Rest)...); + return consume(Reader, Y, std::forward(Rest)...); } #define CV_DESERIALIZE(...) \ Index: include/llvm/DebugInfo/CodeView/SymbolDeserializer.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -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 @@ protected: template - Error deserializeRecord(ArrayRef &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(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 @@ private: template Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) { - ArrayRef 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: include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -64,10 +64,10 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; StringRef Name; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { return ScopeEndSym(Kind, RecordOffset); } uint32_t RecordOffset; @@ -246,11 +246,11 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *Header; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ Header.Range = {}; } - static Expected deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef &Data) { + static Expected + deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, + msf::StreamReader &Reader) { const Hdr *H = nullptr; ArrayRef 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + CV_DESERIALIZE(Reader, H); return DefRangeFramePointerRelFullScopeSym(RecordOffset, H); } @@ -906,10 +906,10 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; std::vector 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + CV_DESERIALIZE(Reader, H); return FrameProcSym(RecordOffset, H); } @@ -1196,9 +1196,9 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + CV_DESERIALIZE(Reader, H); return CallSiteInfoSym(RecordOffset, H); } @@ -1226,11 +1226,11 @@ : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym), RecordOffset(RecordOffset), Header(*H) {} - static Expected deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef &Data) { + static Expected + 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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + CV_DESERIALIZE(Reader, H); return FrameCookieSym(RecordOffset, H); } @@ -1290,10 +1290,10 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + CV_DESERIALIZE(Reader, H); return BuildInfoSym(RecordOffset, H); } @@ -1344,10 +1344,10 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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 @@ static Expected deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef &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: include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -17,13 +17,17 @@ namespace llvm { +namespace msf { +class StreamReader; +} + namespace codeview { class SymbolVisitorDelegate { public: virtual ~SymbolVisitorDelegate() {} - virtual uint32_t getRecordOffset(ArrayRef Record) = 0; + virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0; virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; virtual StringRef getStringTable() = 0; }; Index: include/llvm/DebugInfo/CodeView/TypeDeserializer.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -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 @@ #include "TypeRecords.def" protected: - template - Error deserializeRecord(ArrayRef &Data, TypeLeafKind Kind, + Error deserializeRecord(msf::StreamReader &Reader, TypeLeafKind Kind, T &Record) const { TypeRecordKind RK = static_cast(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 @@ private: template Error defaultVisitKnownRecord(CVType &CVR, T &Record) { - ArrayRef 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 Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) { - ArrayRef 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: include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeRecord.h +++ include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -22,6 +22,11 @@ #include namespace llvm { + +namespace msf { +class StreamReader; +} + namespace codeview { using llvm::support::little32_t; @@ -92,7 +97,7 @@ /// is not in the map. bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(ArrayRef &Data); + static Expected deserialize(msf::StreamReader &Reader); TypeIndex getContainingType() const { return ContainingType; } PointerToMemberRepresentation getRepresentation() const { @@ -134,7 +139,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getModifiedType() const { return ModifiedType; } ModifierOptions getModifiers() const { return Modifiers; } @@ -165,7 +170,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } @@ -211,7 +216,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getReturnType() const { return ReturnType; } TypeIndex getClassType() const { return ClassType; } @@ -258,7 +263,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getClassType() const { return ClassType; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } @@ -287,7 +292,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); ArrayRef getIndices() const { return StringIndices; } @@ -333,7 +338,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getReferentType() const { return ReferentType; } PointerKind getPointerKind() const { return PtrKind; } @@ -410,7 +415,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getNestedType() const { return Type; } StringRef getName() const { return Name; } @@ -438,7 +443,7 @@ bool remapTypeIndices(ArrayRef IndexMap) { return false; } static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); ArrayRef Data; }; @@ -457,7 +462,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getElementType() const { return ElementType; } TypeIndex getIndexType() const { return IndexType; } @@ -526,7 +531,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); HfaKind getHfa() const { return Hfa; } WindowsRTClassKind getWinRTKind() const { return WinRTKind; } @@ -568,7 +573,7 @@ Hfa(Hfa), Size(Size) {} static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); HfaKind getHfa() const { return Hfa; } uint64_t getSize() const { return Size; } @@ -605,7 +610,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getUnderlyingType() const { return UnderlyingType; } TypeIndex UnderlyingType; @@ -638,7 +643,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getType() const { return Type; } uint8_t getBitOffset() const { return BitOffset; } @@ -670,7 +675,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); ArrayRef getSlots() const { if (!SlotsRef.empty()) @@ -705,7 +710,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); StringRef getGuid() const { return Guid; } @@ -736,7 +741,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getId() const { return Id; } @@ -764,7 +769,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getParentScope() const { return ParentScope; } @@ -797,7 +802,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } @@ -826,10 +831,10 @@ bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data) { + static Expected + 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 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); ArrayRef getArgs() const { return ArgIndices; } SmallVector ArgIndices; @@ -901,7 +906,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getCompleteClass() const { return CompleteClass; } TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } @@ -947,7 +952,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getType() const { return Type; } MethodKind getKind() const { return Kind; } @@ -990,7 +995,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected - deserialize(TypeRecordKind Kind, ArrayRef &Data); + deserialize(TypeRecordKind Kind, msf::StreamReader &Reader); ArrayRef getMethods() const { return Methods; } std::vector Methods; @@ -1020,8 +1025,8 @@ /// is not in the map. bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + static Expected + deserialize(TypeRecordKind Kind, msf::StreamReader &Reader); uint16_t getNumOverloads() const { return NumOverloads; } TypeIndex getMethodList() const { return MethodList; } @@ -1053,7 +1058,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); MemberAccess getAccess() const { return Access; } TypeIndex getType() const { return Type; } @@ -1086,8 +1091,8 @@ /// is not in the map. bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + static Expected + deserialize(TypeRecordKind Kind, msf::StreamReader &Reader); MemberAccess getAccess() const { return Access; } TypeIndex getType() const { return Type; } @@ -1118,7 +1123,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); MemberAccess getAccess() const { return Access; } APSInt getValue() const { return Value; } @@ -1148,7 +1153,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); TypeIndex getType() const { return Type; } TypeIndex Type; @@ -1173,7 +1178,7 @@ bool remapTypeIndices(ArrayRef IndexMap); static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + msf::StreamReader &Reader); MemberAccess getAccess() const { return Access; } TypeIndex getBaseType() const { return Type; } @@ -1204,8 +1209,8 @@ /// is not in the map. bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + static Expected + deserialize(TypeRecordKind Kind, msf::StreamReader &Reader); MemberAccess getAccess() const { return Access; } TypeIndex getBaseType() const { return BaseType; } @@ -1241,8 +1246,8 @@ bool remapTypeIndices(ArrayRef IndexMap); - static Expected deserialize(TypeRecordKind Kind, - ArrayRef &Data); + static Expected + deserialize(TypeRecordKind Kind, msf::StreamReader &Reader); TypeIndex ContinuationIndex; private: Index: include/llvm/DebugInfo/MSF/ByteStream.h =================================================================== --- include/llvm/DebugInfo/MSF/ByteStream.h +++ include/llvm/DebugInfo/MSF/ByteStream.h @@ -28,6 +28,8 @@ public: ByteStream() {} explicit ByteStream(ArrayRef Data) : Data(Data) {} + explicit ByteStream(StringRef Data) + : Data(Data.bytes_begin(), Data.bytes_end()) {} Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const override { Index: include/llvm/DebugInfo/MSF/StreamReader.h =================================================================== --- include/llvm/DebugInfo/MSF/StreamReader.h +++ include/llvm/DebugInfo/MSF/StreamReader.h @@ -29,8 +29,14 @@ Error readLongestContiguousChunk(ArrayRef &Buffer); Error readBytes(ArrayRef &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 @@ 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: lib/DebugInfo/CodeView/CVTypeVisitor.cpp =================================================================== --- lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -15,47 +15,38 @@ using namespace llvm; using namespace llvm::codeview; -template -static Error takeObject(ArrayRef &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return llvm::make_error(cv_error_code::insufficient_buffer); - Res = reinterpret_cast(Data.data()); - Data = Data.drop_front(sizeof(*Res)); - return Error::success(); -} - -static Error skipPadding(ArrayRef &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(cv_error_code::corrupt_record, - "Invalid padding bytes!"); - } - Data = Data.drop_front(BytesToAdvance); - return Error::success(); + return Reader.skip(BytesToAdvance); } template -static Expected deserializeMemberRecord(ArrayRef &Data, - TypeLeafKind Kind) { - ArrayRef OldData = Data; +static Expected +deserializeMemberRecord(msf::StreamReader &Reader, TypeLeafKind Kind) { + msf::StreamReader OldReader = Reader; TypeRecordKind RK = static_cast(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 @@ } template -static Error visitKnownMember(ArrayRef &Data, TypeLeafKind Leaf, +static Error visitKnownMember(msf::StreamReader &Reader, TypeLeafKind Leaf, TypeVisitorCallbacks &Callbacks) { - auto ExpectedRecord = deserializeMemberRecord(Data, Leaf); + auto ExpectedRecord = deserializeMemberRecord(Reader, Leaf); if (!ExpectedRecord) return ExpectedRecord.takeError(); CVMemberRecord &Record = *ExpectedRecord; @@ -162,13 +153,12 @@ return Error::success(); } -Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef 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(uint16_t(*LeafValue)); CVType Record; switch (Leaf) { default: @@ -178,7 +168,7 @@ cv_error_code::unknown_member_record); #define MEMBER_RECORD(EnumName, EnumVal, Name) \ case EnumName: { \ - if (auto EC = visitKnownMember(Data, Leaf, Callbacks)) \ + if (auto EC = visitKnownMember(Reader, Leaf, Callbacks)) \ return EC; \ break; \ } @@ -189,3 +179,9 @@ } return Error::success(); } + +Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef Data) { + msf::ByteStream S(Data); + msf::StreamReader SR(S); + return visitFieldListMemberStream(SR); +} Index: lib/DebugInfo/CodeView/RecordSerialization.cpp =================================================================== --- lib/DebugInfo/CodeView/RecordSerialization.cpp +++ lib/DebugInfo/CodeView/RecordSerialization.cpp @@ -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 @@ return getBytesAsCharacters(LeafData).split('\0').first; } -Error llvm::codeview::consume(ArrayRef &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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an APSInt"); - uint16_t Short = *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_CHAR"); - Num = APSInt(APInt(/*numBits=*/8, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_SHORT"); - Num = APSInt(APInt(/*numBits=*/16, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_USHORT"); - Num = APSInt(APInt(/*numBits=*/16, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_LONG"); - Num = APSInt(APInt(/*numBits=*/32, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_ULONG"); - Num = APSInt(APInt(/*numBits=*/32, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_QUADWORD"); - Num = APSInt(APInt(/*numBits=*/64, - *reinterpret_cast(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( - cv_error_code::insufficient_buffer, - "Buffer does not contain enough data for an LF_UQUADWORD"); - Num = APSInt(APInt(/*numBits=*/64, - *reinterpret_cast(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(cv_error_code::corrupt_record, "Buffer contains invalid APSInt type"); } Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { ArrayRef Bytes(Data.bytes_begin(), Data.bytes_end()); - auto EC = consume(Bytes, Num); - Data = StringRef(reinterpret_cast(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 &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(cv_error_code::corrupt_record, @@ -148,41 +123,27 @@ return Error::success(); } -Error llvm::codeview::consume(ArrayRef &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 Bytes(Data.bytes_begin(), Data.bytes_end()); - auto EC = consume(Bytes, Item); - Data = StringRef(reinterpret_cast(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 &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 &Data, StringRef &Item) { - if (Data.empty()) +Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) { + if (Reader.empty()) return make_error(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(cv_error_code::corrupt_record, - "Expected null terminator!"); - - Data = ArrayRef(Rest.bytes_begin(), Rest.bytes_end()); - return Error::success(); + return Reader.readZeroString(Item); } Index: lib/DebugInfo/CodeView/TypeRecord.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeRecord.cpp +++ lib/DebugInfo/CodeView/TypeRecord.cpp @@ -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 @@ //===----------------------------------------------------------------------===// Expected -MemberPointerInfo::deserialize(ArrayRef &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 @@ return MemberPointerInfo(T, PMR); } -Expected ModifierRecord::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { +Expected +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 -ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef &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 @@ Expected MemberFunctionRecord::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { + msf::StreamReader &Reader) { if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList) return make_error( cv_error_code::corrupt_record, @@ -80,14 +82,14 @@ const Layout *L = nullptr; ArrayRef 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::deserialize(TypeRecordKind Kind, - ArrayRef &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 @@ 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 -NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &Data) { - auto FieldListData = Data; - Data = ArrayRef(); - return FieldListRecord(FieldListData); +FieldListRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) { + ArrayRef Data; + if (auto EC = Reader.readBytes(Data, Reader.bytesRemaining())) + return std::move(EC); + return FieldListRecord(Data); } Expected ArrayRecord::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &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 UnionRecord::deserialize(TypeRecordKind Kind, - ArrayRef &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 EnumRecord::deserialize(TypeRecordKind Kind, - ArrayRef &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 @@ UniqueName, L->UnderlyingType); } -Expected BitFieldRecord::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { +Expected +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::deserialize(TypeRecordKind Kind, ArrayRef &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 Slots; uint16_t Count = L->VFEntryCount; while (Count > 0) { - if (Data.empty()) - return make_error(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(Value)); if (--Count > 0) { - Value = (Data[0] & 0xF0) >> 4; + Value = (Data & 0xF0) >> 4; Slots.push_back(static_cast(Value)); --Count; } - Data = Data.slice(1); } return VFTableShapeRecord(Slots); } Expected -TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { +Expected +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::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &Data) { +BuildInfoRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) { const Layout *L = nullptr; ArrayRef 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::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Layout *L = nullptr; StringRef Name; std::vector 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::deserialize(TypeRecordKind Kind, ArrayRef &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 @@ Expected MethodOverloadListRecord::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { + msf::StreamReader &Reader) { std::vector 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 @@ Expected OverloadedMethodRecord::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &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::deserialize(TypeRecordKind Kind, - ArrayRef &Data) { + msf::StreamReader &Reader) { const Layout *L = nullptr; - CV_DESERIALIZE(Data, L); + CV_DESERIALIZE(Reader, L); return ListContinuationRecord(L->ContinuationIndex); } Index: lib/DebugInfo/MSF/StreamReader.cpp =================================================================== --- lib/DebugInfo/MSF/StreamReader.cpp +++ lib/DebugInfo/MSF/StreamReader.cpp @@ -31,6 +31,14 @@ 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 @@ 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 @@ Offset += Length; return Error::success(); } + +Error StreamReader::skip(uint32_t Amount) { + if (Amount > bytesRemaining()) + return make_error(msf_error_code::insufficient_buffer); + Offset += Amount; + return Error::success(); +} + +uint8_t StreamReader::peek() const { + ArrayRef Buffer; + auto EC = Stream.readBytes(Offset, 1, Buffer); + assert(!EC && "Cannot peek an empty buffer!"); + llvm::consumeError(std::move(EC)); + return Buffer[0]; +} Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -154,8 +154,13 @@ Sec = Obj->getCOFFSection(SR); } - uint32_t getRecordOffset(ArrayRef Record) override { - return Record.data() - SectionContents.bytes_begin(); + uint32_t getRecordOffset(msf::StreamReader Reader) override { + ArrayRef 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 @@ } 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 @@ // 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::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 @@ 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 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 @@ 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); } }