Error visitTypeStream(const CVTypeArray &Types);
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
+ Error visitFieldListMemberStream(msf::StreamReader Reader);
private:
/// The interface to the class that gets notified of each visitation.
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cinttypes>
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
-/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
-/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
-/// T object and points 'Res' at them.
-template <typename T, typename U>
-inline Error consumeObject(U &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res))
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Insufficient bytes for expected object type");
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
- return Error::success();
-}
-
-inline Error consume(ArrayRef<uint8_t> &Data) { return Error::success(); }
+inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
/// Decodes a numeric "leaf" value. These are integer literals encountered in
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
/// that indicates the bitwidth and sign of the numeric data.
-Error consume(ArrayRef<uint8_t> &Data, APSInt &Num);
-Error consume(StringRef &Data, APSInt &Num);
+Error consume(msf::StreamReader &Reader, APSInt &Num);
/// Decodes a numeric leaf value that is known to be a particular type.
-Error consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Value);
+Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value);
/// Decodes signed and unsigned fixed-length integers.
-Error consume(ArrayRef<uint8_t> &Data, uint32_t &Item);
-Error consume(StringRef &Data, uint32_t &Item);
-Error consume(ArrayRef<uint8_t> &Data, int32_t &Item);
+Error consume(msf::StreamReader &Reader, uint32_t &Item);
+Error consume(msf::StreamReader &Reader, int32_t &Item);
/// Decodes a null terminated string.
-Error consume(ArrayRef<uint8_t> &Data, StringRef &Item);
+Error consume(msf::StreamReader &Reader, StringRef &Item);
+
+Error consume(StringRef &Data, APSInt &Num);
+Error consume(StringRef &Data, uint32_t &Item);
/// Decodes an arbitrary object whose layout matches that of the underlying
/// byte sequence, and returns a pointer to the object.
-template <typename T> Error consume(ArrayRef<uint8_t> &Data, T *&Item) {
- return consumeObject(Data, Item);
+template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
+ return Reader.readObject(Item);
}
template <typename T, typename U> struct serialize_conditional_impl {
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
+ Error deserialize(msf::StreamReader &Reader) const {
if (!Func())
return Error::success();
- return consume(Data, Item);
+ return consume(Reader, Item);
}
T &Item;
template <typename T, typename U> struct serialize_array_impl {
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
- uint32_t N = Func();
- if (N == 0)
- return Error::success();
-
- uint32_t Size = sizeof(T) * N;
-
- if (Size / sizeof(T) != N)
- return make_error<CodeViewError>(
- cv_error_code::corrupt_record,
- "Array<T> length is not a multiple of sizeof(T)");
-
- if (Data.size() < Size)
- return make_error<CodeViewError>(
- cv_error_code::corrupt_record,
- "Array<T> does not contain enough data for all elements");
-
- Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N);
- Data = Data.drop_front(Size);
- return Error::success();
+ Error deserialize(msf::StreamReader &Reader) const {
+ return Reader.readArray(Item, Func());
}
ArrayRef<T> &Item;
template <typename T> struct serialize_vector_tail_impl {
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
+ Error deserialize(msf::StreamReader &Reader) const {
T Field;
// Stop when we run out of bytes or we hit record padding bytes.
- while (!Data.empty() && Data.front() < LF_PAD0) {
- if (auto EC = consume(Data, Field))
+ while (!Reader.empty() && Reader.peek() < LF_PAD0) {
+ if (auto EC = consume(Reader, Field))
return EC;
Item.push_back(Field);
}
serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
: Item(Item) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
- if (Data.empty())
+ Error deserialize(msf::StreamReader &Reader) const {
+ if (Reader.empty())
return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
"Null terminated string is empty!");
- StringRef Field;
- // Stop when we run out of bytes or we hit record padding bytes.
- while (Data.front() != 0) {
- if (auto EC = consume(Data, Field))
+ while (Reader.peek() != 0) {
+ StringRef Field;
+ if (auto EC = Reader.readZeroString(Field))
return EC;
Item.push_back(Field);
- if (Data.empty())
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Null terminated string has no null terminator!");
}
- Data = Data.drop_front(1);
- return Error::success();
+ return Reader.skip(1);
}
std::vector<StringRef> &Item;
template <typename T> struct serialize_arrayref_tail_impl {
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
- uint32_t Count = Data.size() / sizeof(T);
- Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count);
- return Error::success();
+ Error deserialize(msf::StreamReader &Reader) const {
+ uint32_t Count = Reader.bytesRemaining() / sizeof(T);
+ return Reader.readArray(Item, Count);
}
ArrayRef<T> &Item;
template <typename T> struct serialize_numeric_impl {
serialize_numeric_impl(T &Item) : Item(Item) {}
- Error deserialize(ArrayRef<uint8_t> &Data) const {
- return consume_numeric(Data, Item);
+ Error deserialize(msf::StreamReader &Reader) const {
+ return consume_numeric(Reader, Item);
}
T &Item;
#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
template <typename T, typename U>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
const serialize_conditional_impl<T, U> &Item) {
- return Item.deserialize(Data);
+ return Item.deserialize(Reader);
}
template <typename T, typename U>
-Error consume(ArrayRef<uint8_t> &Data, const serialize_array_impl<T, U> &Item) {
- return Item.deserialize(Data);
+Error consume(msf::StreamReader &Reader,
+ const serialize_array_impl<T, U> &Item) {
+ return Item.deserialize(Reader);
}
-inline Error consume(ArrayRef<uint8_t> &Data,
+inline Error consume(msf::StreamReader &Reader,
const serialize_null_term_string_array_impl &Item) {
- return Item.deserialize(Data);
+ return Item.deserialize(Reader);
}
template <typename T>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
const serialize_vector_tail_impl<T> &Item) {
- return Item.deserialize(Data);
+ return Item.deserialize(Reader);
}
template <typename T>
-Error consume(ArrayRef<uint8_t> &Data,
+Error consume(msf::StreamReader &Reader,
const serialize_arrayref_tail_impl<T> &Item) {
- return Item.deserialize(Data);
+ return Item.deserialize(Reader);
}
template <typename T>
-Error consume(ArrayRef<uint8_t> &Data, const serialize_numeric_impl<T> &Item) {
- return Item.deserialize(Data);
+Error consume(msf::StreamReader &Reader,
+ const serialize_numeric_impl<T> &Item) {
+ return Item.deserialize(Reader);
}
template <typename T, typename U, typename... Args>
-Error consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y, Args &&... Rest) {
- if (auto EC = consume(Data, X))
+Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
+ if (auto EC = consume(Reader, X))
return EC;
- return consume(Data, Y, std::forward<Args>(Rest)...);
+ return consume(Reader, Y, std::forward<Args>(Rest)...);
}
#define CV_DESERIALIZE(...) \
#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 {
protected:
template <typename T>
- Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
+ Error deserializeRecord(msf::StreamReader &Reader, SymbolKind Kind,
T &Record) const {
- uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
+ uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Reader) : 0;
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
- auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
+ auto ExpectedRecord = T::deserialize(RK, RecordOffset, Reader);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
Record = std::move(*ExpectedRecord);
private:
template <typename T>
Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
- ArrayRef<uint8_t> RD = CVR.content();
- if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+ msf::ByteStream S(CVR.content());
+ msf::StreamReader SR(S);
+ if (auto EC = deserializeRecord(SR, CVR.Type, Record))
return EC;
return Error::success();
}
static Expected<ProcSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return ProcSym(Kind, RecordOffset, H, Name);
}
static Expected<Thunk32Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
ArrayRef<uint8_t> VariantData;
- CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
+ CV_DESERIALIZE(Reader, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
}
static Expected<TrampolineSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return TrampolineSym(Kind, RecordOffset, H);
}
static Expected<SectionSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return SectionSym(Kind, RecordOffset, H, Name);
}
static Expected<CoffGroupSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return CoffGroupSym(Kind, RecordOffset, H, Name);
}
static Expected<ScopeEndSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
return ScopeEndSym(Kind, RecordOffset);
}
uint32_t RecordOffset;
static Expected<CallerSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *Header;
ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
+ CV_DESERIALIZE(Reader, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
return CallerSym(Kind, RecordOffset, Header, Indices);
}
static Expected<InlineSiteSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<uint8_t> Annotations;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Annotations));
return InlineSiteSym(RecordOffset, H, Annotations);
}
static Expected<PublicSym32> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return PublicSym32(RecordOffset, H, Name);
}
static Expected<RegisterSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return RegisterSym(RecordOffset, H, Name);
}
static Expected<ProcRefSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return ProcRefSym(RecordOffset, H, Name);
}
static Expected<LocalSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return LocalSym(RecordOffset, H, Name);
}
static Expected<DefRangeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeSym(RecordOffset, H, Gaps);
}
static Expected<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeSubfieldSym(RecordOffset, H, Gaps);
}
static Expected<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeRegisterSym(RecordOffset, H, Gaps);
}
static Expected<DefRangeSubfieldRegisterSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
}
static Expected<DefRangeFramePointerRelSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
}
Header.Range = {};
}
- static Expected<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
- uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ static Expected<DefRangeRegisterRelSym>
+ deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps;
- CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+ CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
}
static Expected<DefRangeFramePointerRelFullScopeSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
}
static Expected<BlockSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return BlockSym(RecordOffset, H, Name);
}
static Expected<LabelSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return LabelSym(RecordOffset, H, Name);
}
static Expected<ObjNameSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return ObjNameSym(RecordOffset, H, Name);
}
static Expected<EnvBlockSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
std::vector<StringRef> Fields;
- CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
+ CV_DESERIALIZE(Reader, H, CV_STRING_ARRAY_NULL_TERM(Fields));
return EnvBlockSym(RecordOffset, H, Fields);
}
static Expected<ExportSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return ExportSym(RecordOffset, H, Name);
}
static Expected<FileStaticSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return FileStaticSym(RecordOffset, H, Name);
}
static Expected<Compile2Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Version;
- CV_DESERIALIZE(Data, H, Version);
+ CV_DESERIALIZE(Reader, H, Version);
return Compile2Sym(RecordOffset, H, Version);
}
static Expected<Compile3Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Version;
- CV_DESERIALIZE(Data, H, Version);
+ CV_DESERIALIZE(Reader, H, Version);
return Compile3Sym(RecordOffset, H, Version);
}
static Expected<FrameProcSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return FrameProcSym(RecordOffset, H);
}
static Expected<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return CallSiteInfoSym(RecordOffset, H);
}
: SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
RecordOffset(RecordOffset), Header(*H) {}
- static Expected<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
- uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ static Expected<HeapAllocationSiteSym>
+ deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return HeapAllocationSiteSym(RecordOffset, H);
}
static Expected<FrameCookieSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return FrameCookieSym(RecordOffset, H);
}
static Expected<UDTSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return UDTSym(RecordOffset, H, Name);
}
static Expected<BuildInfoSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
- CV_DESERIALIZE(Data, H);
+ CV_DESERIALIZE(Reader, H);
return BuildInfoSym(RecordOffset, H);
}
static Expected<BPRelativeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return BPRelativeSym(RecordOffset, H, Name);
}
static Expected<RegRelativeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return RegRelativeSym(RecordOffset, H, Name);
}
static Expected<ConstantSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
APSInt Value;
StringRef Name;
- CV_DESERIALIZE(Data, H, Value, Name);
+ CV_DESERIALIZE(Reader, H, Value, Name);
return ConstantSym(RecordOffset, H, Value, Name);
}
static Expected<DataSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return DataSym(RecordOffset, H, Name);
}
static Expected<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset,
- ArrayRef<uint8_t> &Data) {
+ msf::StreamReader &Reader) {
const Hdr *H = nullptr;
StringRef Name;
- CV_DESERIALIZE(Data, H, Name);
+ CV_DESERIALIZE(Reader, H, Name);
return ThreadLocalDataSym(RecordOffset, H, Name);
}
namespace llvm {
+namespace msf {
+class StreamReader;
+}
+
namespace codeview {
class SymbolVisitorDelegate {
public:
virtual ~SymbolVisitorDelegate() {}
- virtual uint32_t getRecordOffset(ArrayRef<uint8_t> Record) = 0;
+ virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0;
virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
virtual StringRef getStringTable() = 0;
};
#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 {
#include "TypeRecords.def"
protected:
-
template <typename T>
- Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+ Error deserializeRecord(msf::StreamReader &Reader, TypeLeafKind Kind,
T &Record) const {
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
- auto ExpectedRecord = T::deserialize(RK, Data);
+ auto ExpectedRecord = T::deserialize(RK, Reader);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
Record = std::move(*ExpectedRecord);
private:
template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
- ArrayRef<uint8_t> RD = CVR.content();
- if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+ msf::ByteStream S(CVR.content());
+ msf::StreamReader SR(S);
+ if (auto EC = deserializeRecord(SR, CVR.Type, Record))
return EC;
return Error::success();
}
template <typename T>
Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
- ArrayRef<uint8_t> RD = CVMR.Data;
- if (auto EC = deserializeRecord(RD, CVMR.Kind, Record))
+ msf::ByteStream S(CVMR.Data);
+ msf::StreamReader SR(S);
+ if (auto EC = deserializeRecord(SR, CVMR.Kind, Record))
return EC;
return Error::success();
}
#include <utility>
namespace llvm {
+
+namespace msf {
+class StreamReader;
+}
+
namespace codeview {
using llvm::support::little32_t;
/// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data);
+ static Expected<MemberPointerInfo> deserialize(msf::StreamReader &Reader);
TypeIndex getContainingType() const { return ContainingType; }
PointerToMemberRepresentation getRepresentation() const {
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ModifierRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getModifiedType() const { return ModifiedType; }
ModifierOptions getModifiers() const { return Modifiers; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ProcedureRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getClassType() const { return ClassType; }
TypeIndex getFunctionType() const { return FunctionType; }
StringRef getName() const { return Name; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ArgListRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<PointerRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const { return PtrKind; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<NestedTypeRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getNestedType() const { return Type; }
StringRef getName() const { return Name; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
ArrayRef<uint8_t> Data;
};
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ArrayRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ClassRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
HfaKind getHfa() const { return Hfa; }
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
Hfa(Hfa), Size(Size) {}
static Expected<UnionRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
HfaKind getHfa() const { return Hfa; }
uint64_t getSize() const { return Size; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<EnumRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getUnderlyingType() const { return UnderlyingType; }
TypeIndex UnderlyingType;
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BitFieldRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
ArrayRef<VFTableSlotKind> getSlots() const {
if (!SlotsRef.empty())
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<TypeServer2Record> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
StringRef getGuid() const { return Guid; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<StringIdRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getId() const { return Id; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<FuncIdRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getParentScope() const { return ParentScope; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getUDT() const { return UDT; }
TypeIndex getSourceFile() const { return SourceFile; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
+ static Expected<UdtModSourceLineRecord>
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
+ CV_DESERIALIZE(Reader, L);
return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
L->Module);
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BuildInfoRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
SmallVector<TypeIndex, 4> ArgIndices;
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFTableRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getCompleteClass() const { return CompleteClass; }
TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<OneMethodRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getType() const { return Type; }
MethodKind getKind() const { return Kind; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MethodOverloadListRecord>
- deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data);
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
std::vector<OneMethodRecord> Methods;
/// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ static Expected<OverloadedMethodRecord>
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
uint16_t getNumOverloads() const { return NumOverloads; }
TypeIndex getMethodList() const { return MethodList; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<DataMemberRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; }
TypeIndex getType() const { return Type; }
/// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ static Expected<StaticDataMemberRecord>
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; }
TypeIndex getType() const { return Type; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<EnumeratorRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; }
APSInt getValue() const { return Value; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFPtrRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
TypeIndex getType() const { return Type; }
TypeIndex Type;
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BaseClassRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; }
TypeIndex getBaseType() const { return Type; }
/// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ static Expected<VirtualBaseClassRecord>
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; }
TypeIndex getBaseType() const { return BaseType; }
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
- static Expected<ListContinuationRecord> deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data);
+ static Expected<ListContinuationRecord>
+ deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
TypeIndex ContinuationIndex;
private:
public:
ByteStream() {}
explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
+ explicit ByteStream(StringRef Data)
+ : Data(Data.bytes_begin(), Data.bytes_end()) {}
Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const override {
Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
+ Error readInteger(uint8_t &Dest);
Error readInteger(uint16_t &Dest);
Error readInteger(uint32_t &Dest);
+ Error readInteger(uint64_t &Dest);
+ Error readInteger(int8_t &Dest);
+ Error readInteger(int16_t &Dest);
+ Error readInteger(int32_t &Dest);
+ Error readInteger(int64_t &Dest);
Error readZeroString(StringRef &Dest);
Error readFixedString(StringRef &Dest, uint32_t Length);
Error readStreamRef(ReadableStreamRef &Ref);
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;
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;
}
}
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;
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:
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; \
}
}
return Error::success();
}
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+ msf::ByteStream S(Data);
+ msf::StreamReader SR(S);
+ return visitFieldListMemberStream(SR);
+}
#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;
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,
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);
}
#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;
//===----------------------------------------------------------------------===//
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;
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;
}
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);
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,
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();
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
}
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;
}
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;
}
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;
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();
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();
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);
}
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))
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.
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];
+}
Sec = Obj->getCOFFSection(SR);
}
- uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override {
- return Record.data() - SectionContents.bytes_begin();
+ uint32_t getRecordOffset(msf::StreamReader Reader) override {
+ ArrayRef<uint8_t> Data;
+ if (auto EC = Reader.readLongestContiguousChunk(Data)) {
+ llvm::consumeError(std::move(EC));
+ return 0;
+ }
+ return Data.data() - SectionContents.bytes_begin();
}
void printRelocatedField(StringRef Label, uint32_t RelocOffset,
}
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));
// 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);
}
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 =
W.printHex("ChecksumSize", FC->ChecksumSize);
W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind),
makeArrayRef(FileChecksumKindNames));
- if (FC->ChecksumSize >= Data.size())
+ if (FC->ChecksumSize >= SR.bytesRemaining())
error(object_error::parse_failed);
- StringRef ChecksumBytes = Data.substr(0, FC->ChecksumSize);
+ ArrayRef<uint8_t> ChecksumBytes;
+ error(SR.readBytes(ChecksumBytes, FC->ChecksumSize));
W.printBinary("ChecksumBytes", ChecksumBytes);
unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) -
sizeof(FileChecksum);
- if (PaddedSize > Data.size())
+ PaddedSize -= ChecksumBytes.size();
+ if (PaddedSize > SR.bytesRemaining())
error(object_error::parse_failed);
- Data = Data.drop_front(PaddedSize);
+ error(SR.skip(PaddedSize));
}
}
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
- StringRef Data = Subsection;
+ msf::ByteStream S(Subsection);
+ msf::StreamReader SR(S);
uint32_t Signature;
- error(consume(Data, Signature));
+ error(SR.readInteger(Signature));
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
- while (!Data.empty()) {
+ while (!SR.empty()) {
const InlineeSourceLine *ISL;
- error(consumeObject(Data, ISL));
+ error(SR.readObject(ISL));
DictScope S(W, "InlineeSourceLine");
printTypeIndex("Inlinee", ISL->Inlinee);
printFileNameForOffset("FileID", ISL->FileID);
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);
}
}