diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 62 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp | 173 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecord.cpp | 161 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/MSF/StreamReader.cpp | 63 |
4 files changed, 242 insertions, 217 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index deefa8d4ef0..2dee8988df9 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -15,47 +15,38 @@ 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); +} diff --git a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp index 9386d29f223..6f29caa9bbf 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp +++ b/llvm/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 @@ 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); } diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp index 47aa04fe76a..a7a1bb9228c 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp +++ b/llvm/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 @@ 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); } diff --git a/llvm/lib/DebugInfo/MSF/StreamReader.cpp b/llvm/lib/DebugInfo/MSF/StreamReader.cpp index eb3d3e82d4d..b85fd14a3b7 100644 --- a/llvm/lib/DebugInfo/MSF/StreamReader.cpp +++ b/llvm/lib/DebugInfo/MSF/StreamReader.cpp @@ -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]; +} |