mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 04:09:45 +00:00
[CodeView] Refactor serialization to use StreamInterface.
This was all using ArrayRef<>s before which presents a problem when you want to serialize to or deserialize from an actual PDB stream. An ArrayRef<> is really just a special case of what can be handled with StreamInterface though (e.g. by using a ByteStream), so changing this to use StreamInterface allows us to plug in a PDB stream and get all the record serialization and deserialization for free on a MappedBlockStream. Subsequent patches will try to remove TypeTableBuilder and TypeRecordBuilder in favor of class that operate on Streams as well, which should allow us to completely merge the reading and writing codepaths for both types and symbols. Differential Revision: https://reviews.llvm.org/D25831 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284762 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
37962abba1
commit
a459ab93aa
@ -30,6 +30,7 @@ public:
|
||||
Error visitTypeStream(const CVTypeArray &Types);
|
||||
|
||||
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
|
||||
Error visitFieldListMemberStream(msf::StreamReader Reader);
|
||||
|
||||
private:
|
||||
/// The interface to the class that gets notified of each visitation.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/DebugInfo/MSF/StreamReader.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cinttypes>
|
||||
@ -40,53 +41,40 @@ struct RecordPrefix {
|
||||
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
|
||||
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
|
||||
|
||||
/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
|
||||
/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
|
||||
/// T object and points 'Res' at them.
|
||||
template <typename T, typename U>
|
||||
inline Error consumeObject(U &Data, const T *&Res) {
|
||||
if (Data.size() < sizeof(*Res))
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::insufficient_buffer,
|
||||
"Insufficient bytes for expected object type");
|
||||
Res = reinterpret_cast<const T *>(Data.data());
|
||||
Data = Data.drop_front(sizeof(*Res));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
inline Error consume(ArrayRef<uint8_t> &Data) { return Error::success(); }
|
||||
inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
|
||||
|
||||
/// Decodes a numeric "leaf" value. These are integer literals encountered in
|
||||
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
|
||||
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
|
||||
/// that indicates the bitwidth and sign of the numeric data.
|
||||
Error consume(ArrayRef<uint8_t> &Data, APSInt &Num);
|
||||
Error consume(StringRef &Data, APSInt &Num);
|
||||
Error consume(msf::StreamReader &Reader, APSInt &Num);
|
||||
|
||||
/// Decodes a numeric leaf value that is known to be a particular type.
|
||||
Error consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Value);
|
||||
Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value);
|
||||
|
||||
/// Decodes signed and unsigned fixed-length integers.
|
||||
Error consume(ArrayRef<uint8_t> &Data, uint32_t &Item);
|
||||
Error consume(StringRef &Data, uint32_t &Item);
|
||||
Error consume(ArrayRef<uint8_t> &Data, int32_t &Item);
|
||||
Error consume(msf::StreamReader &Reader, uint32_t &Item);
|
||||
Error consume(msf::StreamReader &Reader, int32_t &Item);
|
||||
|
||||
/// Decodes a null terminated string.
|
||||
Error consume(ArrayRef<uint8_t> &Data, StringRef &Item);
|
||||
Error consume(msf::StreamReader &Reader, StringRef &Item);
|
||||
|
||||
Error consume(StringRef &Data, APSInt &Num);
|
||||
Error consume(StringRef &Data, uint32_t &Item);
|
||||
|
||||
/// Decodes an arbitrary object whose layout matches that of the underlying
|
||||
/// byte sequence, and returns a pointer to the object.
|
||||
template <typename T> Error consume(ArrayRef<uint8_t> &Data, T *&Item) {
|
||||
return consumeObject(Data, Item);
|
||||
template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
|
||||
return Reader.readObject(Item);
|
||||
}
|
||||
|
||||
template <typename T, typename U> struct serialize_conditional_impl {
|
||||
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
if (!Func())
|
||||
return Error::success();
|
||||
return consume(Data, Item);
|
||||
return consume(Reader, Item);
|
||||
}
|
||||
|
||||
T &Item;
|
||||
@ -101,26 +89,8 @@ serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) {
|
||||
template <typename T, typename U> struct serialize_array_impl {
|
||||
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
uint32_t N = Func();
|
||||
if (N == 0)
|
||||
return Error::success();
|
||||
|
||||
uint32_t Size = sizeof(T) * N;
|
||||
|
||||
if (Size / sizeof(T) != N)
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::corrupt_record,
|
||||
"Array<T> length is not a multiple of sizeof(T)");
|
||||
|
||||
if (Data.size() < Size)
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::corrupt_record,
|
||||
"Array<T> does not contain enough data for all elements");
|
||||
|
||||
Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N);
|
||||
Data = Data.drop_front(Size);
|
||||
return Error::success();
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
return Reader.readArray(Item, Func());
|
||||
}
|
||||
|
||||
ArrayRef<T> &Item;
|
||||
@ -130,11 +100,11 @@ template <typename T, typename U> struct serialize_array_impl {
|
||||
template <typename T> struct serialize_vector_tail_impl {
|
||||
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
T Field;
|
||||
// Stop when we run out of bytes or we hit record padding bytes.
|
||||
while (!Data.empty() && Data.front() < LF_PAD0) {
|
||||
if (auto EC = consume(Data, Field))
|
||||
while (!Reader.empty() && Reader.peek() < LF_PAD0) {
|
||||
if (auto EC = consume(Reader, Field))
|
||||
return EC;
|
||||
Item.push_back(Field);
|
||||
}
|
||||
@ -148,24 +118,18 @@ struct serialize_null_term_string_array_impl {
|
||||
serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
|
||||
: Item(Item) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
if (Data.empty())
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
if (Reader.empty())
|
||||
return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
|
||||
"Null terminated string is empty!");
|
||||
|
||||
StringRef Field;
|
||||
// Stop when we run out of bytes or we hit record padding bytes.
|
||||
while (Data.front() != 0) {
|
||||
if (auto EC = consume(Data, Field))
|
||||
while (Reader.peek() != 0) {
|
||||
StringRef Field;
|
||||
if (auto EC = Reader.readZeroString(Field))
|
||||
return EC;
|
||||
Item.push_back(Field);
|
||||
if (Data.empty())
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::insufficient_buffer,
|
||||
"Null terminated string has no null terminator!");
|
||||
}
|
||||
Data = Data.drop_front(1);
|
||||
return Error::success();
|
||||
return Reader.skip(1);
|
||||
}
|
||||
|
||||
std::vector<StringRef> &Item;
|
||||
@ -174,10 +138,9 @@ struct serialize_null_term_string_array_impl {
|
||||
template <typename T> struct serialize_arrayref_tail_impl {
|
||||
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
uint32_t Count = Data.size() / sizeof(T);
|
||||
Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count);
|
||||
return Error::success();
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
uint32_t Count = Reader.bytesRemaining() / sizeof(T);
|
||||
return Reader.readArray(Item, Count);
|
||||
}
|
||||
|
||||
ArrayRef<T> &Item;
|
||||
@ -186,8 +149,8 @@ template <typename T> struct serialize_arrayref_tail_impl {
|
||||
template <typename T> struct serialize_numeric_impl {
|
||||
serialize_numeric_impl(T &Item) : Item(Item) {}
|
||||
|
||||
Error deserialize(ArrayRef<uint8_t> &Data) const {
|
||||
return consume_numeric(Data, Item);
|
||||
Error deserialize(msf::StreamReader &Reader) const {
|
||||
return consume_numeric(Reader, Item);
|
||||
}
|
||||
|
||||
T &Item;
|
||||
@ -238,43 +201,45 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
|
||||
#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
|
||||
|
||||
template <typename T, typename U>
|
||||
Error consume(ArrayRef<uint8_t> &Data,
|
||||
Error consume(msf::StreamReader &Reader,
|
||||
const serialize_conditional_impl<T, U> &Item) {
|
||||
return Item.deserialize(Data);
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
Error consume(ArrayRef<uint8_t> &Data, const serialize_array_impl<T, U> &Item) {
|
||||
return Item.deserialize(Data);
|
||||
Error consume(msf::StreamReader &Reader,
|
||||
const serialize_array_impl<T, U> &Item) {
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
inline Error consume(ArrayRef<uint8_t> &Data,
|
||||
inline Error consume(msf::StreamReader &Reader,
|
||||
const serialize_null_term_string_array_impl &Item) {
|
||||
return Item.deserialize(Data);
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Error consume(ArrayRef<uint8_t> &Data,
|
||||
Error consume(msf::StreamReader &Reader,
|
||||
const serialize_vector_tail_impl<T> &Item) {
|
||||
return Item.deserialize(Data);
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Error consume(ArrayRef<uint8_t> &Data,
|
||||
Error consume(msf::StreamReader &Reader,
|
||||
const serialize_arrayref_tail_impl<T> &Item) {
|
||||
return Item.deserialize(Data);
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Error consume(ArrayRef<uint8_t> &Data, const serialize_numeric_impl<T> &Item) {
|
||||
return Item.deserialize(Data);
|
||||
Error consume(msf::StreamReader &Reader,
|
||||
const serialize_numeric_impl<T> &Item) {
|
||||
return Item.deserialize(Reader);
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename... Args>
|
||||
Error consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y, Args &&... Rest) {
|
||||
if (auto EC = consume(Data, X))
|
||||
Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
|
||||
if (auto EC = consume(Reader, X))
|
||||
return EC;
|
||||
return consume(Data, Y, std::forward<Args>(Rest)...);
|
||||
return consume(Reader, Y, std::forward<Args>(Rest)...);
|
||||
}
|
||||
|
||||
#define CV_DESERIALIZE(...) \
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
|
||||
#include "llvm/DebugInfo/MSF/ByteStream.h"
|
||||
#include "llvm/DebugInfo/MSF/StreamReader.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -33,11 +35,11 @@ public:
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
|
||||
Error deserializeRecord(msf::StreamReader &Reader, SymbolKind Kind,
|
||||
T &Record) const {
|
||||
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
|
||||
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Reader) : 0;
|
||||
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
|
||||
auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
|
||||
auto ExpectedRecord = T::deserialize(RK, RecordOffset, Reader);
|
||||
if (!ExpectedRecord)
|
||||
return ExpectedRecord.takeError();
|
||||
Record = std::move(*ExpectedRecord);
|
||||
@ -47,8 +49,9 @@ protected:
|
||||
private:
|
||||
template <typename T>
|
||||
Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVR.content();
|
||||
if (auto EC = deserializeRecord(RD, CVR.Type, Record))
|
||||
msf::ByteStream S(CVR.content());
|
||||
msf::StreamReader SR(S);
|
||||
if (auto EC = deserializeRecord(SR, CVR.Type, Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -64,10 +64,10 @@ public:
|
||||
|
||||
static Expected<ProcSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return ProcSym(Kind, RecordOffset, H, Name);
|
||||
}
|
||||
@ -104,12 +104,12 @@ public:
|
||||
|
||||
static Expected<Thunk32Sym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
ArrayRef<uint8_t> VariantData;
|
||||
|
||||
CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
|
||||
CV_DESERIALIZE(Reader, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
|
||||
|
||||
return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
|
||||
}
|
||||
@ -138,10 +138,10 @@ public:
|
||||
|
||||
static Expected<TrampolineSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return TrampolineSym(Kind, RecordOffset, H);
|
||||
}
|
||||
@ -171,11 +171,11 @@ public:
|
||||
|
||||
static Expected<SectionSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return SectionSym(Kind, RecordOffset, H, Name);
|
||||
}
|
||||
@ -204,11 +204,11 @@ public:
|
||||
|
||||
static Expected<CoffGroupSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return CoffGroupSym(Kind, RecordOffset, H, Name);
|
||||
}
|
||||
@ -226,7 +226,7 @@ public:
|
||||
|
||||
static Expected<ScopeEndSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
return ScopeEndSym(Kind, RecordOffset);
|
||||
}
|
||||
uint32_t RecordOffset;
|
||||
@ -246,11 +246,11 @@ public:
|
||||
|
||||
static Expected<CallerSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *Header;
|
||||
ArrayRef<TypeIndex> Indices;
|
||||
|
||||
CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
|
||||
CV_DESERIALIZE(Reader, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
|
||||
|
||||
return CallerSym(Kind, RecordOffset, Header, Indices);
|
||||
}
|
||||
@ -456,10 +456,10 @@ public:
|
||||
|
||||
static Expected<InlineSiteSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<uint8_t> Annotations;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Annotations));
|
||||
|
||||
return InlineSiteSym(RecordOffset, H, Annotations);
|
||||
}
|
||||
@ -493,10 +493,10 @@ public:
|
||||
|
||||
static Expected<PublicSym32> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return PublicSym32(RecordOffset, H, Name);
|
||||
}
|
||||
@ -522,10 +522,10 @@ public:
|
||||
|
||||
static Expected<RegisterSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return RegisterSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -552,10 +552,10 @@ public:
|
||||
|
||||
static Expected<ProcRefSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return ProcRefSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -581,10 +581,10 @@ public:
|
||||
|
||||
static Expected<LocalSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return LocalSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -624,10 +624,10 @@ public:
|
||||
|
||||
static Expected<DefRangeSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -658,10 +658,10 @@ public:
|
||||
|
||||
static Expected<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeSubfieldSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -702,10 +702,10 @@ public:
|
||||
|
||||
static Expected<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeRegisterSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -750,10 +750,10 @@ public:
|
||||
|
||||
static Expected<DefRangeSubfieldRegisterSym>
|
||||
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -785,10 +785,10 @@ public:
|
||||
|
||||
static Expected<DefRangeFramePointerRelSym>
|
||||
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -830,12 +830,12 @@ public:
|
||||
Header.Range = {};
|
||||
}
|
||||
|
||||
static Expected<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
static Expected<DefRangeRegisterRelSym>
|
||||
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
ArrayRef<LocalVariableAddrGap> Gaps;
|
||||
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
CV_DESERIALIZE(Reader, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
||||
|
||||
return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
|
||||
}
|
||||
@ -876,9 +876,9 @@ public:
|
||||
|
||||
static Expected<DefRangeFramePointerRelFullScopeSym>
|
||||
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
|
||||
}
|
||||
@ -906,10 +906,10 @@ public:
|
||||
|
||||
static Expected<BlockSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return BlockSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -940,10 +940,10 @@ public:
|
||||
|
||||
static Expected<LabelSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return LabelSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -972,10 +972,10 @@ public:
|
||||
|
||||
static Expected<ObjNameSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return ObjNameSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1001,10 +1001,10 @@ public:
|
||||
|
||||
static Expected<EnvBlockSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
std::vector<StringRef> Fields;
|
||||
CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
|
||||
CV_DESERIALIZE(Reader, H, CV_STRING_ARRAY_NULL_TERM(Fields));
|
||||
|
||||
return EnvBlockSym(RecordOffset, H, Fields);
|
||||
}
|
||||
@ -1030,10 +1030,10 @@ public:
|
||||
|
||||
static Expected<ExportSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return ExportSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1060,10 +1060,10 @@ public:
|
||||
|
||||
static Expected<FileStaticSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return FileStaticSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1097,10 +1097,10 @@ public:
|
||||
|
||||
static Expected<Compile2Sym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Version;
|
||||
CV_DESERIALIZE(Data, H, Version);
|
||||
CV_DESERIALIZE(Reader, H, Version);
|
||||
|
||||
return Compile2Sym(RecordOffset, H, Version);
|
||||
}
|
||||
@ -1135,10 +1135,10 @@ public:
|
||||
|
||||
static Expected<Compile3Sym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Version;
|
||||
CV_DESERIALIZE(Data, H, Version);
|
||||
CV_DESERIALIZE(Reader, H, Version);
|
||||
|
||||
return Compile3Sym(RecordOffset, H, Version);
|
||||
}
|
||||
@ -1168,9 +1168,9 @@ public:
|
||||
|
||||
static Expected<FrameProcSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return FrameProcSym(RecordOffset, H);
|
||||
}
|
||||
@ -1196,9 +1196,9 @@ public:
|
||||
|
||||
static Expected<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return CallSiteInfoSym(RecordOffset, H);
|
||||
}
|
||||
@ -1226,11 +1226,11 @@ public:
|
||||
: SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
|
||||
RecordOffset(RecordOffset), Header(*H) {}
|
||||
|
||||
static Expected<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
static Expected<HeapAllocationSiteSym>
|
||||
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return HeapAllocationSiteSym(RecordOffset, H);
|
||||
}
|
||||
@ -1260,9 +1260,9 @@ public:
|
||||
|
||||
static Expected<FrameCookieSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return FrameCookieSym(RecordOffset, H);
|
||||
}
|
||||
@ -1290,10 +1290,10 @@ public:
|
||||
|
||||
static Expected<UDTSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return UDTSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1317,9 +1317,9 @@ public:
|
||||
|
||||
static Expected<BuildInfoSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
CV_DESERIALIZE(Data, H);
|
||||
CV_DESERIALIZE(Reader, H);
|
||||
|
||||
return BuildInfoSym(RecordOffset, H);
|
||||
}
|
||||
@ -1344,10 +1344,10 @@ public:
|
||||
|
||||
static Expected<BPRelativeSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return BPRelativeSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1374,10 +1374,10 @@ public:
|
||||
|
||||
static Expected<RegRelativeSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return RegRelativeSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1404,11 +1404,11 @@ public:
|
||||
|
||||
static Expected<ConstantSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
APSInt Value;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Value, Name);
|
||||
CV_DESERIALIZE(Reader, H, Value, Name);
|
||||
|
||||
return ConstantSym(RecordOffset, H, Value, Name);
|
||||
}
|
||||
@ -1436,10 +1436,10 @@ public:
|
||||
|
||||
static Expected<DataSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return DataSym(RecordOffset, H, Name);
|
||||
}
|
||||
@ -1470,10 +1470,10 @@ public:
|
||||
|
||||
static Expected<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
msf::StreamReader &Reader) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Name;
|
||||
CV_DESERIALIZE(Data, H, Name);
|
||||
CV_DESERIALIZE(Reader, H, Name);
|
||||
|
||||
return ThreadLocalDataSym(RecordOffset, H, Name);
|
||||
}
|
||||
|
@ -17,13 +17,17 @@
|
||||
|
||||
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;
|
||||
};
|
||||
|
@ -11,6 +11,8 @@
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
||||
#include "llvm/DebugInfo/Msf/ByteStream.h"
|
||||
#include "llvm/DebugInfo/Msf/StreamReader.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -32,12 +34,11 @@ public:
|
||||
#include "TypeRecords.def"
|
||||
|
||||
protected:
|
||||
|
||||
template <typename T>
|
||||
Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
|
||||
Error deserializeRecord(msf::StreamReader &Reader, TypeLeafKind Kind,
|
||||
T &Record) const {
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
|
||||
auto ExpectedRecord = T::deserialize(RK, Data);
|
||||
auto ExpectedRecord = T::deserialize(RK, Reader);
|
||||
if (!ExpectedRecord)
|
||||
return ExpectedRecord.takeError();
|
||||
Record = std::move(*ExpectedRecord);
|
||||
@ -46,15 +47,17 @@ protected:
|
||||
|
||||
private:
|
||||
template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVR.content();
|
||||
if (auto EC = deserializeRecord(RD, CVR.Type, Record))
|
||||
msf::ByteStream S(CVR.content());
|
||||
msf::StreamReader SR(S);
|
||||
if (auto EC = deserializeRecord(SR, CVR.Type, Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
template <typename T>
|
||||
Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVMR.Data;
|
||||
if (auto EC = deserializeRecord(RD, CVMR.Kind, Record))
|
||||
msf::ByteStream S(CVMR.Data);
|
||||
msf::StreamReader SR(S);
|
||||
if (auto EC = deserializeRecord(SR, CVMR.Kind, Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace msf {
|
||||
class StreamReader;
|
||||
}
|
||||
|
||||
namespace codeview {
|
||||
|
||||
using llvm::support::little32_t;
|
||||
@ -92,7 +97,7 @@ public:
|
||||
/// is not in the map.
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data);
|
||||
static Expected<MemberPointerInfo> deserialize(msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getContainingType() const { return ContainingType; }
|
||||
PointerToMemberRepresentation getRepresentation() const {
|
||||
@ -134,7 +139,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ModifierRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getModifiedType() const { return ModifiedType; }
|
||||
ModifierOptions getModifiers() const { return Modifiers; }
|
||||
@ -165,7 +170,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ProcedureRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
|
||||
|
||||
@ -211,7 +216,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getReturnType() const { return ReturnType; }
|
||||
TypeIndex getClassType() const { return ClassType; }
|
||||
@ -258,7 +263,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
TypeIndex getClassType() const { return ClassType; }
|
||||
TypeIndex getFunctionType() const { return FunctionType; }
|
||||
StringRef getName() const { return Name; }
|
||||
@ -287,7 +292,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ArgListRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
|
||||
|
||||
@ -333,7 +338,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<PointerRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getReferentType() const { return ReferentType; }
|
||||
PointerKind getPointerKind() const { return PtrKind; }
|
||||
@ -410,7 +415,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<NestedTypeRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getNestedType() const { return Type; }
|
||||
StringRef getName() const { return Name; }
|
||||
@ -438,7 +443,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
|
||||
|
||||
static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
ArrayRef<uint8_t> Data;
|
||||
};
|
||||
@ -457,7 +462,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ArrayRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getElementType() const { return ElementType; }
|
||||
TypeIndex getIndexType() const { return IndexType; }
|
||||
@ -526,7 +531,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ClassRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
HfaKind getHfa() const { return Hfa; }
|
||||
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
|
||||
@ -568,7 +573,7 @@ struct UnionRecord : public TagRecord {
|
||||
Hfa(Hfa), Size(Size) {}
|
||||
|
||||
static Expected<UnionRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
HfaKind getHfa() const { return Hfa; }
|
||||
uint64_t getSize() const { return Size; }
|
||||
@ -605,7 +610,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<EnumRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getUnderlyingType() const { return UnderlyingType; }
|
||||
TypeIndex UnderlyingType;
|
||||
@ -638,7 +643,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<BitFieldRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getType() const { return Type; }
|
||||
uint8_t getBitOffset() const { return BitOffset; }
|
||||
@ -670,7 +675,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
ArrayRef<VFTableSlotKind> getSlots() const {
|
||||
if (!SlotsRef.empty())
|
||||
@ -705,7 +710,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<TypeServer2Record> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
StringRef getGuid() const { return Guid; }
|
||||
|
||||
@ -736,7 +741,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<StringIdRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getId() const { return Id; }
|
||||
|
||||
@ -764,7 +769,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<FuncIdRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getParentScope() const { return ParentScope; }
|
||||
|
||||
@ -797,7 +802,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getUDT() const { return UDT; }
|
||||
TypeIndex getSourceFile() const { return SourceFile; }
|
||||
@ -826,10 +831,10 @@ public:
|
||||
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
static Expected<UdtModSourceLineRecord>
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
|
||||
const Layout *L = nullptr;
|
||||
CV_DESERIALIZE(Data, L);
|
||||
CV_DESERIALIZE(Reader, L);
|
||||
|
||||
return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
|
||||
L->Module);
|
||||
@ -867,7 +872,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<BuildInfoRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
|
||||
SmallVector<TypeIndex, 4> ArgIndices;
|
||||
@ -901,7 +906,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<VFTableRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getCompleteClass() const { return CompleteClass; }
|
||||
TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
|
||||
@ -947,7 +952,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<OneMethodRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getType() const { return Type; }
|
||||
MethodKind getKind() const { return Kind; }
|
||||
@ -990,7 +995,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<MethodOverloadListRecord>
|
||||
deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data);
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
|
||||
|
||||
ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
|
||||
std::vector<OneMethodRecord> Methods;
|
||||
@ -1020,8 +1025,8 @@ public:
|
||||
/// is not in the map.
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
static Expected<OverloadedMethodRecord>
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
|
||||
|
||||
uint16_t getNumOverloads() const { return NumOverloads; }
|
||||
TypeIndex getMethodList() const { return MethodList; }
|
||||
@ -1053,7 +1058,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<DataMemberRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
TypeIndex getType() const { return Type; }
|
||||
@ -1086,8 +1091,8 @@ public:
|
||||
/// is not in the map.
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
static Expected<StaticDataMemberRecord>
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
TypeIndex getType() const { return Type; }
|
||||
@ -1118,7 +1123,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<EnumeratorRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
APSInt getValue() const { return Value; }
|
||||
@ -1148,7 +1153,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<VFPtrRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
TypeIndex getType() const { return Type; }
|
||||
TypeIndex Type;
|
||||
@ -1173,7 +1178,7 @@ public:
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<BaseClassRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
msf::StreamReader &Reader);
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
TypeIndex getBaseType() const { return Type; }
|
||||
@ -1204,8 +1209,8 @@ public:
|
||||
/// is not in the map.
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
static Expected<VirtualBaseClassRecord>
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
TypeIndex getBaseType() const { return BaseType; }
|
||||
@ -1241,8 +1246,8 @@ public:
|
||||
|
||||
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
|
||||
|
||||
static Expected<ListContinuationRecord> deserialize(TypeRecordKind Kind,
|
||||
ArrayRef<uint8_t> &Data);
|
||||
static Expected<ListContinuationRecord>
|
||||
deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
|
||||
TypeIndex ContinuationIndex;
|
||||
|
||||
private:
|
||||
|
@ -28,6 +28,8 @@ class ByteStream : public ReadableStream {
|
||||
public:
|
||||
ByteStream() {}
|
||||
explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
|
||||
explicit ByteStream(StringRef Data)
|
||||
: Data(Data.bytes_begin(), Data.bytes_end()) {}
|
||||
|
||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||
ArrayRef<uint8_t> &Buffer) const override {
|
||||
|
@ -29,8 +29,14 @@ public:
|
||||
|
||||
Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
|
||||
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
|
||||
Error readInteger(uint8_t &Dest);
|
||||
Error readInteger(uint16_t &Dest);
|
||||
Error readInteger(uint32_t &Dest);
|
||||
Error readInteger(uint64_t &Dest);
|
||||
Error readInteger(int8_t &Dest);
|
||||
Error readInteger(int16_t &Dest);
|
||||
Error readInteger(int32_t &Dest);
|
||||
Error readInteger(int64_t &Dest);
|
||||
Error readZeroString(StringRef &Dest);
|
||||
Error readFixedString(StringRef &Dest, uint32_t Length);
|
||||
Error readStreamRef(ReadableStreamRef &Ref);
|
||||
@ -101,6 +107,10 @@ public:
|
||||
uint32_t getLength() const { return Stream.getLength(); }
|
||||
uint32_t bytesRemaining() const { return getLength() - getOffset(); }
|
||||
|
||||
Error skip(uint32_t Amount);
|
||||
|
||||
uint8_t peek() const;
|
||||
|
||||
private:
|
||||
ReadableStreamRef Stream;
|
||||
uint32_t Offset;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -154,8 +154,13 @@ public:
|
||||
Sec = Obj->getCOFFSection(SR);
|
||||
}
|
||||
|
||||
uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override {
|
||||
return Record.data() - SectionContents.bytes_begin();
|
||||
uint32_t getRecordOffset(msf::StreamReader Reader) override {
|
||||
ArrayRef<uint8_t> Data;
|
||||
if (auto EC = Reader.readLongestContiguousChunk(Data)) {
|
||||
llvm::consumeError(std::move(EC));
|
||||
return 0;
|
||||
}
|
||||
return Data.data() - SectionContents.bytes_begin();
|
||||
}
|
||||
|
||||
void printRelocatedField(StringRef Label, uint32_t RelocOffset,
|
||||
@ -835,8 +840,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
|
||||
}
|
||||
case ModuleSubstreamKind::FrameData: {
|
||||
// First four bytes is a relocation against the function.
|
||||
msf::ByteStream S(Contents);
|
||||
msf::StreamReader SR(S);
|
||||
const uint32_t *CodePtr;
|
||||
error(consumeObject(Contents, CodePtr));
|
||||
error(SR.readObject(CodePtr));
|
||||
StringRef LinkageName;
|
||||
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
|
||||
CodePtr, LinkageName));
|
||||
@ -844,9 +851,9 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
|
||||
|
||||
// To find the active frame description, search this array for the
|
||||
// smallest PC range that includes the current PC.
|
||||
while (!Contents.empty()) {
|
||||
while (!SR.empty()) {
|
||||
const FrameData *FD;
|
||||
error(consumeObject(Contents, FD));
|
||||
error(SR.readObject(FD));
|
||||
|
||||
if (FD->FrameFunc >= CVStringTable.size())
|
||||
error(object_error::parse_failed);
|
||||
@ -974,11 +981,12 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
||||
}
|
||||
|
||||
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
||||
StringRef Data = Subsection;
|
||||
while (!Data.empty()) {
|
||||
msf::ByteStream S(Subsection);
|
||||
msf::StreamReader SR(S);
|
||||
while (!SR.empty()) {
|
||||
DictScope S(W, "FileChecksum");
|
||||
const FileChecksum *FC;
|
||||
error(consumeObject(Data, FC));
|
||||
error(SR.readObject(FC));
|
||||
if (FC->FileNameOffset >= CVStringTable.size())
|
||||
error(object_error::parse_failed);
|
||||
StringRef Filename =
|
||||
@ -987,27 +995,30 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
||||
W.printHex("ChecksumSize", FC->ChecksumSize);
|
||||
W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind),
|
||||
makeArrayRef(FileChecksumKindNames));
|
||||
if (FC->ChecksumSize >= Data.size())
|
||||
if (FC->ChecksumSize >= SR.bytesRemaining())
|
||||
error(object_error::parse_failed);
|
||||
StringRef ChecksumBytes = Data.substr(0, FC->ChecksumSize);
|
||||
ArrayRef<uint8_t> ChecksumBytes;
|
||||
error(SR.readBytes(ChecksumBytes, FC->ChecksumSize));
|
||||
W.printBinary("ChecksumBytes", ChecksumBytes);
|
||||
unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) -
|
||||
sizeof(FileChecksum);
|
||||
if (PaddedSize > Data.size())
|
||||
PaddedSize -= ChecksumBytes.size();
|
||||
if (PaddedSize > SR.bytesRemaining())
|
||||
error(object_error::parse_failed);
|
||||
Data = Data.drop_front(PaddedSize);
|
||||
error(SR.skip(PaddedSize));
|
||||
}
|
||||
}
|
||||
|
||||
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
||||
StringRef Data = Subsection;
|
||||
msf::ByteStream S(Subsection);
|
||||
msf::StreamReader SR(S);
|
||||
uint32_t Signature;
|
||||
error(consume(Data, Signature));
|
||||
error(SR.readInteger(Signature));
|
||||
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
|
||||
|
||||
while (!Data.empty()) {
|
||||
while (!SR.empty()) {
|
||||
const InlineeSourceLine *ISL;
|
||||
error(consumeObject(Data, ISL));
|
||||
error(SR.readObject(ISL));
|
||||
DictScope S(W, "InlineeSourceLine");
|
||||
printTypeIndex("Inlinee", ISL->Inlinee);
|
||||
printFileNameForOffset("FileID", ISL->FileID);
|
||||
@ -1015,12 +1026,12 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
||||
|
||||
if (HasExtraFiles) {
|
||||
uint32_t ExtraFileCount;
|
||||
error(consume(Data, ExtraFileCount));
|
||||
error(SR.readInteger(ExtraFileCount));
|
||||
W.printNumber("ExtraFileCount", ExtraFileCount);
|
||||
ListScope ExtraFiles(W, "ExtraFiles");
|
||||
for (unsigned I = 0; I < ExtraFileCount; ++I) {
|
||||
uint32_t FileID;
|
||||
error(consume(Data, FileID));
|
||||
error(SR.readInteger(FileID));
|
||||
printFileNameForOffset("FileID", FileID);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user