summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp62
-rw-r--r--llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp173
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp161
-rw-r--r--llvm/lib/DebugInfo/MSF/StreamReader.cpp63
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];
+}
OpenPOWER on IntegriCloud