1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01: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

llvm-svn: 284762
This commit is contained in:
Zachary Turner 2016-10-20 18:31:19 +00:00
parent e9c9763529
commit 2d85414032
14 changed files with 476 additions and 447 deletions

View File

@ -30,6 +30,7 @@ public:
Error visitTypeStream(const CVTypeArray &Types); Error visitTypeStream(const CVTypeArray &Types);
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList); Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
Error visitFieldListMemberStream(msf::StreamReader Reader);
private: private:
/// The interface to the class that gets notified of each visitation. /// The interface to the class that gets notified of each visitation.

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
#include <cinttypes> #include <cinttypes>
@ -40,53 +41,40 @@ struct RecordPrefix {
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData); StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData); StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
/// 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(); }
/// Decodes a numeric "leaf" value. These are integer literals encountered in /// 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 << /// 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 /// 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. /// that indicates the bitwidth and sign of the numeric data.
Error consume(ArrayRef<uint8_t> &Data, APSInt &Num); Error consume(msf::StreamReader &Reader, APSInt &Num);
Error consume(StringRef &Data, APSInt &Num);
/// Decodes a numeric leaf value that is known to be a particular type. /// 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. /// Decodes signed and unsigned fixed-length integers.
Error consume(ArrayRef<uint8_t> &Data, uint32_t &Item); Error consume(msf::StreamReader &Reader, uint32_t &Item);
Error consume(StringRef &Data, uint32_t &Item); Error consume(msf::StreamReader &Reader, int32_t &Item);
Error consume(ArrayRef<uint8_t> &Data, int32_t &Item);
/// Decodes a null terminated string. /// 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 /// Decodes an arbitrary object whose layout matches that of the underlying
/// byte sequence, and returns a pointer to the object. /// byte sequence, and returns a pointer to the object.
template <typename T> Error consume(ArrayRef<uint8_t> &Data, T *&Item) { template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
return consumeObject(Data, Item); return Reader.readObject(Item);
} }
template <typename T, typename U> struct serialize_conditional_impl { template <typename T, typename U> struct serialize_conditional_impl {
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {} 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()) if (!Func())
return Error::success(); return Error::success();
return consume(Data, Item); return consume(Reader, Item);
} }
T &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 { template <typename T, typename U> struct serialize_array_impl {
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {} serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
Error deserialize(ArrayRef<uint8_t> &Data) const { Error deserialize(msf::StreamReader &Reader) const {
uint32_t N = Func(); return Reader.readArray(Item, 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();
} }
ArrayRef<T> &Item; ArrayRef<T> &Item;
@ -130,11 +100,11 @@ template <typename T, typename U> struct serialize_array_impl {
template <typename T> struct serialize_vector_tail_impl { template <typename T> struct serialize_vector_tail_impl {
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {} 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; T Field;
// Stop when we run out of bytes or we hit record padding bytes. // Stop when we run out of bytes or we hit record padding bytes.
while (!Data.empty() && Data.front() < LF_PAD0) { while (!Reader.empty() && Reader.peek() < LF_PAD0) {
if (auto EC = consume(Data, Field)) if (auto EC = consume(Reader, Field))
return EC; return EC;
Item.push_back(Field); 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) serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
: Item(Item) {} : Item(Item) {}
Error deserialize(ArrayRef<uint8_t> &Data) const { Error deserialize(msf::StreamReader &Reader) const {
if (Data.empty()) if (Reader.empty())
return make_error<CodeViewError>(cv_error_code::insufficient_buffer, return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
"Null terminated string is empty!"); "Null terminated string is empty!");
StringRef Field; while (Reader.peek() != 0) {
// Stop when we run out of bytes or we hit record padding bytes. StringRef Field;
while (Data.front() != 0) { if (auto EC = Reader.readZeroString(Field))
if (auto EC = consume(Data, Field))
return EC; return EC;
Item.push_back(Field); 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 Reader.skip(1);
return Error::success();
} }
std::vector<StringRef> &Item; std::vector<StringRef> &Item;
@ -174,10 +138,9 @@ struct serialize_null_term_string_array_impl {
template <typename T> struct serialize_arrayref_tail_impl { template <typename T> struct serialize_arrayref_tail_impl {
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {} serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
Error deserialize(ArrayRef<uint8_t> &Data) const { Error deserialize(msf::StreamReader &Reader) const {
uint32_t Count = Data.size() / sizeof(T); uint32_t Count = Reader.bytesRemaining() / sizeof(T);
Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count); return Reader.readArray(Item, Count);
return Error::success();
} }
ArrayRef<T> &Item; ArrayRef<T> &Item;
@ -186,8 +149,8 @@ template <typename T> struct serialize_arrayref_tail_impl {
template <typename T> struct serialize_numeric_impl { template <typename T> struct serialize_numeric_impl {
serialize_numeric_impl(T &Item) : Item(Item) {} serialize_numeric_impl(T &Item) : Item(Item) {}
Error deserialize(ArrayRef<uint8_t> &Data) const { Error deserialize(msf::StreamReader &Reader) const {
return consume_numeric(Data, Item); return consume_numeric(Reader, Item);
} }
T &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) #define CV_NUMERIC_FIELD(I) serialize_numeric(I)
template <typename T, typename U> template <typename T, typename U>
Error consume(ArrayRef<uint8_t> &Data, Error consume(msf::StreamReader &Reader,
const serialize_conditional_impl<T, U> &Item) { const serialize_conditional_impl<T, U> &Item) {
return Item.deserialize(Data); return Item.deserialize(Reader);
} }
template <typename T, typename U> template <typename T, typename U>
Error consume(ArrayRef<uint8_t> &Data, const serialize_array_impl<T, U> &Item) { Error consume(msf::StreamReader &Reader,
return Item.deserialize(Data); 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) { const serialize_null_term_string_array_impl &Item) {
return Item.deserialize(Data); return Item.deserialize(Reader);
} }
template <typename T> template <typename T>
Error consume(ArrayRef<uint8_t> &Data, Error consume(msf::StreamReader &Reader,
const serialize_vector_tail_impl<T> &Item) { const serialize_vector_tail_impl<T> &Item) {
return Item.deserialize(Data); return Item.deserialize(Reader);
} }
template <typename T> template <typename T>
Error consume(ArrayRef<uint8_t> &Data, Error consume(msf::StreamReader &Reader,
const serialize_arrayref_tail_impl<T> &Item) { const serialize_arrayref_tail_impl<T> &Item) {
return Item.deserialize(Data); return Item.deserialize(Reader);
} }
template <typename T> template <typename T>
Error consume(ArrayRef<uint8_t> &Data, const serialize_numeric_impl<T> &Item) { Error consume(msf::StreamReader &Reader,
return Item.deserialize(Data); const serialize_numeric_impl<T> &Item) {
return Item.deserialize(Reader);
} }
template <typename T, typename U, typename... Args> template <typename T, typename U, typename... Args>
Error consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y, Args &&... Rest) { Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
if (auto EC = consume(Data, X)) if (auto EC = consume(Reader, X))
return EC; return EC;
return consume(Data, Y, std::forward<Args>(Rest)...); return consume(Reader, Y, std::forward<Args>(Rest)...);
} }
#define CV_DESERIALIZE(...) \ #define CV_DESERIALIZE(...) \

View File

@ -14,6 +14,8 @@
#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
namespace llvm { namespace llvm {
@ -33,11 +35,11 @@ public:
protected: protected:
template <typename T> template <typename T>
Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind, Error deserializeRecord(msf::StreamReader &Reader, SymbolKind Kind,
T &Record) const { 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); SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data); auto ExpectedRecord = T::deserialize(RK, RecordOffset, Reader);
if (!ExpectedRecord) if (!ExpectedRecord)
return ExpectedRecord.takeError(); return ExpectedRecord.takeError();
Record = std::move(*ExpectedRecord); Record = std::move(*ExpectedRecord);
@ -47,8 +49,9 @@ protected:
private: private:
template <typename T> template <typename T>
Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) { Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
ArrayRef<uint8_t> RD = CVR.content(); msf::ByteStream S(CVR.content());
if (auto EC = deserializeRecord(RD, CVR.Type, Record)) msf::StreamReader SR(S);
if (auto EC = deserializeRecord(SR, CVR.Type, Record))
return EC; return EC;
return Error::success(); return Error::success();
} }

View File

@ -64,10 +64,10 @@ public:
static Expected<ProcSym> deserialize(SymbolRecordKind Kind, static Expected<ProcSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return ProcSym(Kind, RecordOffset, H, Name); return ProcSym(Kind, RecordOffset, H, Name);
} }
@ -104,12 +104,12 @@ public:
static Expected<Thunk32Sym> deserialize(SymbolRecordKind Kind, static Expected<Thunk32Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
ArrayRef<uint8_t> VariantData; 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); return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
} }
@ -138,10 +138,10 @@ public:
static Expected<TrampolineSym> deserialize(SymbolRecordKind Kind, static Expected<TrampolineSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return TrampolineSym(Kind, RecordOffset, H); return TrampolineSym(Kind, RecordOffset, H);
} }
@ -171,11 +171,11 @@ public:
static Expected<SectionSym> deserialize(SymbolRecordKind Kind, static Expected<SectionSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return SectionSym(Kind, RecordOffset, H, Name); return SectionSym(Kind, RecordOffset, H, Name);
} }
@ -204,11 +204,11 @@ public:
static Expected<CoffGroupSym> deserialize(SymbolRecordKind Kind, static Expected<CoffGroupSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return CoffGroupSym(Kind, RecordOffset, H, Name); return CoffGroupSym(Kind, RecordOffset, H, Name);
} }
@ -226,7 +226,7 @@ public:
static Expected<ScopeEndSym> deserialize(SymbolRecordKind Kind, static Expected<ScopeEndSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
return ScopeEndSym(Kind, RecordOffset); return ScopeEndSym(Kind, RecordOffset);
} }
uint32_t RecordOffset; uint32_t RecordOffset;
@ -246,11 +246,11 @@ public:
static Expected<CallerSym> deserialize(SymbolRecordKind Kind, static Expected<CallerSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *Header; const Hdr *Header;
ArrayRef<TypeIndex> Indices; 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); return CallerSym(Kind, RecordOffset, Header, Indices);
} }
@ -456,10 +456,10 @@ public:
static Expected<InlineSiteSym> deserialize(SymbolRecordKind Kind, static Expected<InlineSiteSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<uint8_t> Annotations; 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); return InlineSiteSym(RecordOffset, H, Annotations);
} }
@ -493,10 +493,10 @@ public:
static Expected<PublicSym32> deserialize(SymbolRecordKind Kind, static Expected<PublicSym32> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return PublicSym32(RecordOffset, H, Name); return PublicSym32(RecordOffset, H, Name);
} }
@ -522,10 +522,10 @@ public:
static Expected<RegisterSym> deserialize(SymbolRecordKind Kind, static Expected<RegisterSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return RegisterSym(RecordOffset, H, Name); return RegisterSym(RecordOffset, H, Name);
} }
@ -552,10 +552,10 @@ public:
static Expected<ProcRefSym> deserialize(SymbolRecordKind Kind, static Expected<ProcRefSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return ProcRefSym(RecordOffset, H, Name); return ProcRefSym(RecordOffset, H, Name);
} }
@ -581,10 +581,10 @@ public:
static Expected<LocalSym> deserialize(SymbolRecordKind Kind, static Expected<LocalSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return LocalSym(RecordOffset, H, Name); return LocalSym(RecordOffset, H, Name);
} }
@ -624,10 +624,10 @@ public:
static Expected<DefRangeSym> deserialize(SymbolRecordKind Kind, static Expected<DefRangeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeSym(RecordOffset, H, Gaps);
} }
@ -658,10 +658,10 @@ public:
static Expected<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind, static Expected<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeSubfieldSym(RecordOffset, H, Gaps);
} }
@ -702,10 +702,10 @@ public:
static Expected<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind, static Expected<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeRegisterSym(RecordOffset, H, Gaps);
} }
@ -750,10 +750,10 @@ public:
static Expected<DefRangeSubfieldRegisterSym> static Expected<DefRangeSubfieldRegisterSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
} }
@ -785,10 +785,10 @@ public:
static Expected<DefRangeFramePointerRelSym> static Expected<DefRangeFramePointerRelSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
} }
@ -830,12 +830,12 @@ public:
Header.Range = {}; Header.Range = {};
} }
static Expected<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind, static Expected<DefRangeRegisterRelSym>
uint32_t RecordOffset, deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
ArrayRef<LocalVariableAddrGap> Gaps; 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); return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
} }
@ -876,9 +876,9 @@ public:
static Expected<DefRangeFramePointerRelFullScopeSym> static Expected<DefRangeFramePointerRelFullScopeSym>
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return DefRangeFramePointerRelFullScopeSym(RecordOffset, H); return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
} }
@ -906,10 +906,10 @@ public:
static Expected<BlockSym> deserialize(SymbolRecordKind Kind, static Expected<BlockSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return BlockSym(RecordOffset, H, Name); return BlockSym(RecordOffset, H, Name);
} }
@ -940,10 +940,10 @@ public:
static Expected<LabelSym> deserialize(SymbolRecordKind Kind, static Expected<LabelSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return LabelSym(RecordOffset, H, Name); return LabelSym(RecordOffset, H, Name);
} }
@ -972,10 +972,10 @@ public:
static Expected<ObjNameSym> deserialize(SymbolRecordKind Kind, static Expected<ObjNameSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return ObjNameSym(RecordOffset, H, Name); return ObjNameSym(RecordOffset, H, Name);
} }
@ -1001,10 +1001,10 @@ public:
static Expected<EnvBlockSym> deserialize(SymbolRecordKind Kind, static Expected<EnvBlockSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
std::vector<StringRef> Fields; 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); return EnvBlockSym(RecordOffset, H, Fields);
} }
@ -1030,10 +1030,10 @@ public:
static Expected<ExportSym> deserialize(SymbolRecordKind Kind, static Expected<ExportSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return ExportSym(RecordOffset, H, Name); return ExportSym(RecordOffset, H, Name);
} }
@ -1060,10 +1060,10 @@ public:
static Expected<FileStaticSym> deserialize(SymbolRecordKind Kind, static Expected<FileStaticSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return FileStaticSym(RecordOffset, H, Name); return FileStaticSym(RecordOffset, H, Name);
} }
@ -1097,10 +1097,10 @@ public:
static Expected<Compile2Sym> deserialize(SymbolRecordKind Kind, static Expected<Compile2Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Version; StringRef Version;
CV_DESERIALIZE(Data, H, Version); CV_DESERIALIZE(Reader, H, Version);
return Compile2Sym(RecordOffset, H, Version); return Compile2Sym(RecordOffset, H, Version);
} }
@ -1135,10 +1135,10 @@ public:
static Expected<Compile3Sym> deserialize(SymbolRecordKind Kind, static Expected<Compile3Sym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Version; StringRef Version;
CV_DESERIALIZE(Data, H, Version); CV_DESERIALIZE(Reader, H, Version);
return Compile3Sym(RecordOffset, H, Version); return Compile3Sym(RecordOffset, H, Version);
} }
@ -1168,9 +1168,9 @@ public:
static Expected<FrameProcSym> deserialize(SymbolRecordKind Kind, static Expected<FrameProcSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return FrameProcSym(RecordOffset, H); return FrameProcSym(RecordOffset, H);
} }
@ -1196,9 +1196,9 @@ public:
static Expected<CallSiteInfoSym> deserialize(SymbolRecordKind Kind, static Expected<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return CallSiteInfoSym(RecordOffset, H); return CallSiteInfoSym(RecordOffset, H);
} }
@ -1226,11 +1226,11 @@ public:
: SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym), : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
RecordOffset(RecordOffset), Header(*H) {} RecordOffset(RecordOffset), Header(*H) {}
static Expected<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind, static Expected<HeapAllocationSiteSym>
uint32_t RecordOffset, deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return HeapAllocationSiteSym(RecordOffset, H); return HeapAllocationSiteSym(RecordOffset, H);
} }
@ -1260,9 +1260,9 @@ public:
static Expected<FrameCookieSym> deserialize(SymbolRecordKind Kind, static Expected<FrameCookieSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return FrameCookieSym(RecordOffset, H); return FrameCookieSym(RecordOffset, H);
} }
@ -1290,10 +1290,10 @@ public:
static Expected<UDTSym> deserialize(SymbolRecordKind Kind, static Expected<UDTSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return UDTSym(RecordOffset, H, Name); return UDTSym(RecordOffset, H, Name);
} }
@ -1317,9 +1317,9 @@ public:
static Expected<BuildInfoSym> deserialize(SymbolRecordKind Kind, static Expected<BuildInfoSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
CV_DESERIALIZE(Data, H); CV_DESERIALIZE(Reader, H);
return BuildInfoSym(RecordOffset, H); return BuildInfoSym(RecordOffset, H);
} }
@ -1344,10 +1344,10 @@ public:
static Expected<BPRelativeSym> deserialize(SymbolRecordKind Kind, static Expected<BPRelativeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return BPRelativeSym(RecordOffset, H, Name); return BPRelativeSym(RecordOffset, H, Name);
} }
@ -1374,10 +1374,10 @@ public:
static Expected<RegRelativeSym> deserialize(SymbolRecordKind Kind, static Expected<RegRelativeSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return RegRelativeSym(RecordOffset, H, Name); return RegRelativeSym(RecordOffset, H, Name);
} }
@ -1404,11 +1404,11 @@ public:
static Expected<ConstantSym> deserialize(SymbolRecordKind Kind, static Expected<ConstantSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
APSInt Value; APSInt Value;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Value, Name); CV_DESERIALIZE(Reader, H, Value, Name);
return ConstantSym(RecordOffset, H, Value, Name); return ConstantSym(RecordOffset, H, Value, Name);
} }
@ -1436,10 +1436,10 @@ public:
static Expected<DataSym> deserialize(SymbolRecordKind Kind, static Expected<DataSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return DataSym(RecordOffset, H, Name); return DataSym(RecordOffset, H, Name);
} }
@ -1470,10 +1470,10 @@ public:
static Expected<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind, static Expected<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
uint32_t RecordOffset, uint32_t RecordOffset,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Hdr *H = nullptr; const Hdr *H = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, H, Name); CV_DESERIALIZE(Reader, H, Name);
return ThreadLocalDataSym(RecordOffset, H, Name); return ThreadLocalDataSym(RecordOffset, H, Name);
} }

View File

@ -17,13 +17,17 @@
namespace llvm { namespace llvm {
namespace msf {
class StreamReader;
}
namespace codeview { namespace codeview {
class SymbolVisitorDelegate { class SymbolVisitorDelegate {
public: public:
virtual ~SymbolVisitorDelegate() {} 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 getFileNameForFileOffset(uint32_t FileOffset) = 0;
virtual StringRef getStringTable() = 0; virtual StringRef getStringTable() = 0;
}; };

View File

@ -11,6 +11,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/DebugInfo/Msf/ByteStream.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
namespace llvm { namespace llvm {
@ -32,12 +34,11 @@ public:
#include "TypeRecords.def" #include "TypeRecords.def"
protected: protected:
template <typename T> template <typename T>
Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind, Error deserializeRecord(msf::StreamReader &Reader, TypeLeafKind Kind,
T &Record) const { T &Record) const {
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind); TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
auto ExpectedRecord = T::deserialize(RK, Data); auto ExpectedRecord = T::deserialize(RK, Reader);
if (!ExpectedRecord) if (!ExpectedRecord)
return ExpectedRecord.takeError(); return ExpectedRecord.takeError();
Record = std::move(*ExpectedRecord); Record = std::move(*ExpectedRecord);
@ -46,15 +47,17 @@ protected:
private: private:
template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) { template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
ArrayRef<uint8_t> RD = CVR.content(); msf::ByteStream S(CVR.content());
if (auto EC = deserializeRecord(RD, CVR.Type, Record)) msf::StreamReader SR(S);
if (auto EC = deserializeRecord(SR, CVR.Type, Record))
return EC; return EC;
return Error::success(); return Error::success();
} }
template <typename T> template <typename T>
Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) { Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
ArrayRef<uint8_t> RD = CVMR.Data; msf::ByteStream S(CVMR.Data);
if (auto EC = deserializeRecord(RD, CVMR.Kind, Record)) msf::StreamReader SR(S);
if (auto EC = deserializeRecord(SR, CVMR.Kind, Record))
return EC; return EC;
return Error::success(); return Error::success();
} }

View File

@ -22,6 +22,11 @@
#include <utility> #include <utility>
namespace llvm { namespace llvm {
namespace msf {
class StreamReader;
}
namespace codeview { namespace codeview {
using llvm::support::little32_t; using llvm::support::little32_t;
@ -92,7 +97,7 @@ public:
/// is not in the map. /// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); 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; } TypeIndex getContainingType() const { return ContainingType; }
PointerToMemberRepresentation getRepresentation() const { PointerToMemberRepresentation getRepresentation() const {
@ -134,7 +139,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ModifierRecord> deserialize(TypeRecordKind Kind, static Expected<ModifierRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getModifiedType() const { return ModifiedType; } TypeIndex getModifiedType() const { return ModifiedType; }
ModifierOptions getModifiers() const { return Modifiers; } ModifierOptions getModifiers() const { return Modifiers; }
@ -165,7 +170,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ProcedureRecord> deserialize(TypeRecordKind Kind, static Expected<ProcedureRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
@ -211,7 +216,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MemberFunctionRecord> deserialize(TypeRecordKind Kind, static Expected<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getReturnType() const { return ReturnType; } TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; } TypeIndex getClassType() const { return ClassType; }
@ -258,7 +263,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MemberFuncIdRecord> deserialize(TypeRecordKind Kind, static Expected<MemberFuncIdRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getClassType() const { return ClassType; } TypeIndex getClassType() const { return ClassType; }
TypeIndex getFunctionType() const { return FunctionType; } TypeIndex getFunctionType() const { return FunctionType; }
StringRef getName() const { return Name; } StringRef getName() const { return Name; }
@ -287,7 +292,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ArgListRecord> deserialize(TypeRecordKind Kind, static Expected<ArgListRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
ArrayRef<TypeIndex> getIndices() const { return StringIndices; } ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
@ -333,7 +338,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<PointerRecord> deserialize(TypeRecordKind Kind, static Expected<PointerRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getReferentType() const { return ReferentType; } TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const { return PtrKind; } PointerKind getPointerKind() const { return PtrKind; }
@ -410,7 +415,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<NestedTypeRecord> deserialize(TypeRecordKind Kind, static Expected<NestedTypeRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getNestedType() const { return Type; } TypeIndex getNestedType() const { return Type; }
StringRef getName() const { return Name; } StringRef getName() const { return Name; }
@ -438,7 +443,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; } bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
static Expected<FieldListRecord> deserialize(TypeRecordKind Kind, static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
ArrayRef<uint8_t> Data; ArrayRef<uint8_t> Data;
}; };
@ -457,7 +462,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ArrayRecord> deserialize(TypeRecordKind Kind, static Expected<ArrayRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getElementType() const { return ElementType; } TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; } TypeIndex getIndexType() const { return IndexType; }
@ -526,7 +531,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ClassRecord> deserialize(TypeRecordKind Kind, static Expected<ClassRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
HfaKind getHfa() const { return Hfa; } HfaKind getHfa() const { return Hfa; }
WindowsRTClassKind getWinRTKind() const { return WinRTKind; } WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
@ -568,7 +573,7 @@ struct UnionRecord : public TagRecord {
Hfa(Hfa), Size(Size) {} Hfa(Hfa), Size(Size) {}
static Expected<UnionRecord> deserialize(TypeRecordKind Kind, static Expected<UnionRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
HfaKind getHfa() const { return Hfa; } HfaKind getHfa() const { return Hfa; }
uint64_t getSize() const { return Size; } uint64_t getSize() const { return Size; }
@ -605,7 +610,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<EnumRecord> deserialize(TypeRecordKind Kind, static Expected<EnumRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getUnderlyingType() const { return UnderlyingType; } TypeIndex getUnderlyingType() const { return UnderlyingType; }
TypeIndex UnderlyingType; TypeIndex UnderlyingType;
@ -638,7 +643,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BitFieldRecord> deserialize(TypeRecordKind Kind, static Expected<BitFieldRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getType() const { return Type; } TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; } uint8_t getBitOffset() const { return BitOffset; }
@ -670,7 +675,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFTableShapeRecord> deserialize(TypeRecordKind Kind, static Expected<VFTableShapeRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
ArrayRef<VFTableSlotKind> getSlots() const { ArrayRef<VFTableSlotKind> getSlots() const {
if (!SlotsRef.empty()) if (!SlotsRef.empty())
@ -705,7 +710,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<TypeServer2Record> deserialize(TypeRecordKind Kind, static Expected<TypeServer2Record> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
StringRef getGuid() const { return Guid; } StringRef getGuid() const { return Guid; }
@ -736,7 +741,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<StringIdRecord> deserialize(TypeRecordKind Kind, static Expected<StringIdRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getId() const { return Id; } TypeIndex getId() const { return Id; }
@ -764,7 +769,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<FuncIdRecord> deserialize(TypeRecordKind Kind, static Expected<FuncIdRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getParentScope() const { return ParentScope; } TypeIndex getParentScope() const { return ParentScope; }
@ -797,7 +802,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<UdtSourceLineRecord> deserialize(TypeRecordKind Kind, static Expected<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getUDT() const { return UDT; } TypeIndex getUDT() const { return UDT; }
TypeIndex getSourceFile() const { return SourceFile; } TypeIndex getSourceFile() const { return SourceFile; }
@ -826,10 +831,10 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind, static Expected<UdtModSourceLineRecord>
ArrayRef<uint8_t> &Data) { deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
CV_DESERIALIZE(Data, L); CV_DESERIALIZE(Reader, L);
return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber, return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber,
L->Module); L->Module);
@ -867,7 +872,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BuildInfoRecord> deserialize(TypeRecordKind Kind, static Expected<BuildInfoRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
SmallVector<TypeIndex, 4> ArgIndices; SmallVector<TypeIndex, 4> ArgIndices;
@ -901,7 +906,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFTableRecord> deserialize(TypeRecordKind Kind, static Expected<VFTableRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getCompleteClass() const { return CompleteClass; } TypeIndex getCompleteClass() const { return CompleteClass; }
TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
@ -947,7 +952,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<OneMethodRecord> deserialize(TypeRecordKind Kind, static Expected<OneMethodRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getType() const { return Type; } TypeIndex getType() const { return Type; }
MethodKind getKind() const { return Kind; } MethodKind getKind() const { return Kind; }
@ -990,7 +995,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<MethodOverloadListRecord> static Expected<MethodOverloadListRecord>
deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data); deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
ArrayRef<OneMethodRecord> getMethods() const { return Methods; } ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
std::vector<OneMethodRecord> Methods; std::vector<OneMethodRecord> Methods;
@ -1020,8 +1025,8 @@ public:
/// is not in the map. /// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<OverloadedMethodRecord> deserialize(TypeRecordKind Kind, static Expected<OverloadedMethodRecord>
ArrayRef<uint8_t> &Data); deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
uint16_t getNumOverloads() const { return NumOverloads; } uint16_t getNumOverloads() const { return NumOverloads; }
TypeIndex getMethodList() const { return MethodList; } TypeIndex getMethodList() const { return MethodList; }
@ -1053,7 +1058,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<DataMemberRecord> deserialize(TypeRecordKind Kind, static Expected<DataMemberRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; } MemberAccess getAccess() const { return Access; }
TypeIndex getType() const { return Type; } TypeIndex getType() const { return Type; }
@ -1086,8 +1091,8 @@ public:
/// is not in the map. /// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<StaticDataMemberRecord> deserialize(TypeRecordKind Kind, static Expected<StaticDataMemberRecord>
ArrayRef<uint8_t> &Data); deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; } MemberAccess getAccess() const { return Access; }
TypeIndex getType() const { return Type; } TypeIndex getType() const { return Type; }
@ -1118,7 +1123,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<EnumeratorRecord> deserialize(TypeRecordKind Kind, static Expected<EnumeratorRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; } MemberAccess getAccess() const { return Access; }
APSInt getValue() const { return Value; } APSInt getValue() const { return Value; }
@ -1148,7 +1153,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VFPtrRecord> deserialize(TypeRecordKind Kind, static Expected<VFPtrRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
TypeIndex getType() const { return Type; } TypeIndex getType() const { return Type; }
TypeIndex Type; TypeIndex Type;
@ -1173,7 +1178,7 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<BaseClassRecord> deserialize(TypeRecordKind Kind, static Expected<BaseClassRecord> deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data); msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; } MemberAccess getAccess() const { return Access; }
TypeIndex getBaseType() const { return Type; } TypeIndex getBaseType() const { return Type; }
@ -1204,8 +1209,8 @@ public:
/// is not in the map. /// is not in the map.
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind, static Expected<VirtualBaseClassRecord>
ArrayRef<uint8_t> &Data); deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
MemberAccess getAccess() const { return Access; } MemberAccess getAccess() const { return Access; }
TypeIndex getBaseType() const { return BaseType; } TypeIndex getBaseType() const { return BaseType; }
@ -1241,8 +1246,8 @@ public:
bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
static Expected<ListContinuationRecord> deserialize(TypeRecordKind Kind, static Expected<ListContinuationRecord>
ArrayRef<uint8_t> &Data); deserialize(TypeRecordKind Kind, msf::StreamReader &Reader);
TypeIndex ContinuationIndex; TypeIndex ContinuationIndex;
private: private:

View File

@ -28,6 +28,8 @@ class ByteStream : public ReadableStream {
public: public:
ByteStream() {} ByteStream() {}
explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {} 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, Error readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const override { ArrayRef<uint8_t> &Buffer) const override {

View File

@ -29,8 +29,14 @@ public:
Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer); Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size); Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
Error readInteger(uint8_t &Dest);
Error readInteger(uint16_t &Dest); Error readInteger(uint16_t &Dest);
Error readInteger(uint32_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 readZeroString(StringRef &Dest);
Error readFixedString(StringRef &Dest, uint32_t Length); Error readFixedString(StringRef &Dest, uint32_t Length);
Error readStreamRef(ReadableStreamRef &Ref); Error readStreamRef(ReadableStreamRef &Ref);
@ -101,6 +107,10 @@ public:
uint32_t getLength() const { return Stream.getLength(); } uint32_t getLength() const { return Stream.getLength(); }
uint32_t bytesRemaining() const { return getLength() - getOffset(); } uint32_t bytesRemaining() const { return getLength() - getOffset(); }
Error skip(uint32_t Amount);
uint8_t peek() const;
private: private:
ReadableStreamRef Stream; ReadableStreamRef Stream;
uint32_t Offset; uint32_t Offset;

View File

@ -15,47 +15,38 @@
using namespace llvm; using namespace llvm;
using namespace llvm::codeview; using namespace llvm::codeview;
template <typename T> static Error skipPadding(msf::StreamReader &Reader) {
static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) { if (Reader.empty())
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())
return Error::success(); return Error::success();
uint8_t Leaf = Data.front();
uint8_t Leaf = Reader.peek();
if (Leaf < LF_PAD0) if (Leaf < LF_PAD0)
return Error::success(); return Error::success();
// Leaf is greater than 0xf0. We should advance by the number of bytes in // Leaf is greater than 0xf0. We should advance by the number of bytes in
// the low 4 bits. // the low 4 bits.
unsigned BytesToAdvance = Leaf & 0x0F; unsigned BytesToAdvance = Leaf & 0x0F;
if (Data.size() < BytesToAdvance) { return Reader.skip(BytesToAdvance);
return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
"Invalid padding bytes!");
}
Data = Data.drop_front(BytesToAdvance);
return Error::success();
} }
template <typename T> template <typename T>
static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data, static Expected<CVMemberRecord>
TypeLeafKind Kind) { deserializeMemberRecord(msf::StreamReader &Reader, TypeLeafKind Kind) {
ArrayRef<uint8_t> OldData = Data; msf::StreamReader OldReader = Reader;
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind); TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
auto ExpectedRecord = T::deserialize(RK, Data); auto ExpectedRecord = T::deserialize(RK, Reader);
if (!ExpectedRecord) if (!ExpectedRecord)
return ExpectedRecord.takeError(); return ExpectedRecord.takeError();
assert(Data.size() < OldData.size()); assert(Reader.bytesRemaining() < OldReader.bytesRemaining());
if (auto EC = skipPadding(Data)) if (auto EC = skipPadding(Reader))
return std::move(EC); return std::move(EC);
CVMemberRecord CVMR; CVMemberRecord CVMR;
CVMR.Kind = Kind; 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; return CVMR;
} }
@ -147,9 +138,9 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
} }
template <typename MR> template <typename MR>
static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf, static Error visitKnownMember(msf::StreamReader &Reader, TypeLeafKind Leaf,
TypeVisitorCallbacks &Callbacks) { TypeVisitorCallbacks &Callbacks) {
auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf); auto ExpectedRecord = deserializeMemberRecord<MR>(Reader, Leaf);
if (!ExpectedRecord) if (!ExpectedRecord)
return ExpectedRecord.takeError(); return ExpectedRecord.takeError();
CVMemberRecord &Record = *ExpectedRecord; CVMemberRecord &Record = *ExpectedRecord;
@ -162,13 +153,12 @@ static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
return Error::success(); return Error::success();
} }
Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) { Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) {
while (!Data.empty()) { TypeLeafKind Leaf;
const support::ulittle16_t *LeafValue; while (!Reader.empty()) {
if (auto EC = takeObject(Data, LeafValue)) if (auto EC = Reader.readEnum(Leaf))
return EC; return EC;
TypeLeafKind Leaf = static_cast<TypeLeafKind>(uint16_t(*LeafValue));
CVType Record; CVType Record;
switch (Leaf) { switch (Leaf) {
default: default:
@ -178,7 +168,7 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
cv_error_code::unknown_member_record); cv_error_code::unknown_member_record);
#define MEMBER_RECORD(EnumName, EnumVal, Name) \ #define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \ case EnumName: { \
if (auto EC = visitKnownMember<Name##Record>(Data, Leaf, Callbacks)) \ if (auto EC = visitKnownMember<Name##Record>(Reader, Leaf, Callbacks)) \
return EC; \ return EC; \
break; \ break; \
} }
@ -189,3 +179,9 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
} }
return Error::success(); return Error::success();
} }
Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
msf::ByteStream S(Data);
msf::StreamReader SR(S);
return visitFieldListMemberStream(SR);
}

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/APSInt.h" #include "llvm/ADT/APSInt.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm; using namespace llvm;
using namespace llvm::codeview; using namespace llvm::codeview;
@ -32,114 +33,88 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
return getBytesAsCharacters(LeafData).split('\0').first; 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. // Used to avoid overload ambiguity on APInt construtor.
bool FalseVal = false; bool FalseVal = false;
if (Data.size() < 2) uint16_t Short;
return make_error<CodeViewError>( if (auto EC = Reader.readInteger(Short))
cv_error_code::insufficient_buffer, return EC;
"Buffer does not contain enough data for an APSInt");
uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
Data = Data.drop_front(2);
if (Short < LF_NUMERIC) { if (Short < LF_NUMERIC) {
Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
/*isUnsigned=*/true); /*isUnsigned=*/true);
return Error::success(); return Error::success();
} }
switch (Short) { switch (Short) {
case LF_CHAR: case LF_CHAR: {
if (Data.size() < 1) int8_t N;
return make_error<CodeViewError>( if (auto EC = Reader.readInteger(N))
cv_error_code::insufficient_buffer, return EC;
"Buffer does not contain enough data for an LF_CHAR"); Num = APSInt(APInt(8, N, true), false);
Num = APSInt(APInt(/*numBits=*/8,
*reinterpret_cast<const int8_t *>(Data.data()),
/*isSigned=*/true),
/*isUnsigned=*/false);
Data = Data.drop_front(1);
return Error::success(); return Error::success();
case LF_SHORT: }
if (Data.size() < 2) case LF_SHORT: {
return make_error<CodeViewError>( int16_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_SHORT"); return EC;
Num = APSInt(APInt(/*numBits=*/16, Num = APSInt(APInt(16, N, true), false);
*reinterpret_cast<const little16_t *>(Data.data()),
/*isSigned=*/true),
/*isUnsigned=*/false);
Data = Data.drop_front(2);
return Error::success(); return Error::success();
case LF_USHORT: }
if (Data.size() < 2) case LF_USHORT: {
return make_error<CodeViewError>( uint16_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_USHORT"); return EC;
Num = APSInt(APInt(/*numBits=*/16, Num = APSInt(APInt(16, N, false), true);
*reinterpret_cast<const ulittle16_t *>(Data.data()),
/*isSigned=*/false),
/*isUnsigned=*/true);
Data = Data.drop_front(2);
return Error::success(); return Error::success();
case LF_LONG: }
if (Data.size() < 4) case LF_LONG: {
return make_error<CodeViewError>( int32_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_LONG"); return EC;
Num = APSInt(APInt(/*numBits=*/32, Num = APSInt(APInt(32, N, true), false);
*reinterpret_cast<const little32_t *>(Data.data()),
/*isSigned=*/true),
/*isUnsigned=*/false);
Data = Data.drop_front(4);
return Error::success(); return Error::success();
case LF_ULONG: }
if (Data.size() < 4) case LF_ULONG: {
return make_error<CodeViewError>( uint32_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_ULONG"); return EC;
Num = APSInt(APInt(/*numBits=*/32, Num = APSInt(APInt(32, N, FalseVal), true);
*reinterpret_cast<const ulittle32_t *>(Data.data()),
/*isSigned=*/FalseVal),
/*isUnsigned=*/true);
Data = Data.drop_front(4);
return Error::success(); return Error::success();
case LF_QUADWORD: }
if (Data.size() < 8) case LF_QUADWORD: {
return make_error<CodeViewError>( int64_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_QUADWORD"); return EC;
Num = APSInt(APInt(/*numBits=*/64, Num = APSInt(APInt(64, N, true), false);
*reinterpret_cast<const little64_t *>(Data.data()),
/*isSigned=*/true),
/*isUnsigned=*/false);
Data = Data.drop_front(8);
return Error::success(); return Error::success();
case LF_UQUADWORD: }
if (Data.size() < 8) case LF_UQUADWORD: {
return make_error<CodeViewError>( uint64_t N;
cv_error_code::insufficient_buffer, if (auto EC = Reader.readInteger(N))
"Buffer does not contain enough data for an LF_UQUADWORD"); return EC;
Num = APSInt(APInt(/*numBits=*/64, Num = APSInt(APInt(64, N, false), true);
*reinterpret_cast<const ulittle64_t *>(Data.data()),
/*isSigned=*/false),
/*isUnsigned=*/true);
Data = Data.drop_front(8);
return Error::success(); return Error::success();
} }
}
return make_error<CodeViewError>(cv_error_code::corrupt_record, return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Buffer contains invalid APSInt type"); "Buffer contains invalid APSInt type");
} }
Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
auto EC = consume(Bytes, Num); msf::ByteStream S(Bytes);
Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); msf::StreamReader SR(S);
auto EC = consume(SR, Num);
Data = Data.take_back(SR.bytesRemaining());
return EC; return EC;
} }
/// Decode a numeric leaf value that is known to be a uint64_t. /// 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; APSInt N;
if (auto EC = consume(Data, N)) if (auto EC = consume(Reader, N))
return EC; return EC;
if (N.isSigned() || !N.isIntN(64)) if (N.isSigned() || !N.isIntN(64))
return make_error<CodeViewError>(cv_error_code::corrupt_record, 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(); return Error::success();
} }
Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) { Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
const support::ulittle32_t *IntPtr; return Reader.readInteger(Item);
if (auto EC = consumeObject(Data, IntPtr))
return EC;
Item = *IntPtr;
return Error::success();
} }
Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) { Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
auto EC = consume(Bytes, Item); msf::ByteStream S(Bytes);
Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); msf::StreamReader SR(S);
auto EC = consume(SR, Item);
Data = Data.take_back(SR.bytesRemaining());
return EC; return EC;
} }
Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) { Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
const support::little32_t *IntPtr; return Reader.readInteger(Item);
if (auto EC = consumeObject(Data, IntPtr))
return EC;
Item = *IntPtr;
return Error::success();
} }
Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) { Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) {
if (Data.empty()) if (Reader.empty())
return make_error<CodeViewError>(cv_error_code::corrupt_record, return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Null terminated string buffer is empty!"); "Null terminated string buffer is empty!");
StringRef Rest; return Reader.readZeroString(Item);
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();
} }

View File

@ -11,6 +11,7 @@
#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/MSF/ByteStream.h" #include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/MSF/StreamReader.h"
using namespace llvm; using namespace llvm;
using namespace llvm::codeview; using namespace llvm::codeview;
@ -20,9 +21,9 @@ using namespace llvm::codeview;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
Expected<MemberPointerInfo> Expected<MemberPointerInfo>
MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) { MemberPointerInfo::deserialize(msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
TypeIndex T = L->ClassType; TypeIndex T = L->ClassType;
@ -32,10 +33,10 @@ MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
return MemberPointerInfo(T, PMR); return MemberPointerInfo(T, PMR);
} }
Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind, Expected<ModifierRecord>
ArrayRef<uint8_t> &Data) { ModifierRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
TypeIndex M = L->ModifiedType; TypeIndex M = L->ModifiedType;
@ -45,9 +46,9 @@ Expected<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
} }
Expected<ProcedureRecord> Expected<ProcedureRecord>
ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { ProcedureRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
return ProcedureRecord(L->ReturnType, L->CallConv, L->Options, return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
L->NumParameters, L->ArgListType); L->NumParameters, L->ArgListType);
@ -55,24 +56,25 @@ ProcedureRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
Expected<MemberFunctionRecord> Expected<MemberFunctionRecord>
MemberFunctionRecord::deserialize(TypeRecordKind Kind, MemberFunctionRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
CV_DESERIALIZE(Data, L); CV_DESERIALIZE(Reader, L);
return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType, return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
L->CallConv, L->Options, L->NumParameters, L->CallConv, L->Options, L->NumParameters,
L->ArgListType, L->ThisAdjustment); L->ArgListType, L->ThisAdjustment);
} }
Expected<MemberFuncIdRecord> Expected<MemberFuncIdRecord>
MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { MemberFuncIdRecord::deserialize(TypeRecordKind Kind,
msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name); return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
} }
Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind, Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList) if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
return make_error<CodeViewError>( return make_error<CodeViewError>(
cv_error_code::corrupt_record, cv_error_code::corrupt_record,
@ -80,14 +82,14 @@ Expected<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
const Layout *L = nullptr; const Layout *L = nullptr;
ArrayRef<TypeIndex> Indices; 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); return ArgListRecord(Kind, Indices);
} }
Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind, Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
PointerKind PtrKind = L->getPtrKind(); PointerKind PtrKind = L->getPtrKind();
@ -97,7 +99,7 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
uint8_t Size = L->getPtrSize(); uint8_t Size = L->getPtrSize();
if (L->isPointerToMember()) { if (L->isPointerToMember()) {
if (auto ExpectedMPI = MemberPointerInfo::deserialize(Data)) if (auto ExpectedMPI = MemberPointerInfo::deserialize(Reader))
return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size,
*ExpectedMPI); *ExpectedMPI);
else else
@ -108,38 +110,39 @@ Expected<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
} }
Expected<NestedTypeRecord> Expected<NestedTypeRecord>
NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { NestedTypeRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return NestedTypeRecord(L->Type, Name); return NestedTypeRecord(L->Type, Name);
} }
Expected<FieldListRecord> Expected<FieldListRecord>
FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { FieldListRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
auto FieldListData = Data; ArrayRef<uint8_t> Data;
Data = ArrayRef<uint8_t>(); if (auto EC = Reader.readBytes(Data, Reader.bytesRemaining()))
return FieldListRecord(FieldListData); return std::move(EC);
return FieldListRecord(Data);
} }
Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind, Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
uint64_t Size; uint64_t Size;
StringRef Name; 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); return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
} }
Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind, Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
uint64_t Size = 0; uint64_t Size = 0;
StringRef Name; StringRef Name;
StringRef UniqueName; StringRef UniqueName;
uint16_t Props; uint16_t Props;
const Layout *L = nullptr; 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())); CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
Props = L->Properties; Props = L->Properties;
@ -154,14 +157,14 @@ Expected<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
} }
Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind, Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
uint64_t Size = 0; uint64_t Size = 0;
StringRef Name; StringRef Name;
StringRef UniqueName; StringRef UniqueName;
uint16_t Props; uint16_t Props;
const Layout *L = nullptr; 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())); CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
Props = L->Properties; Props = L->Properties;
@ -174,11 +177,11 @@ Expected<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
} }
Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind, Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
StringRef UniqueName; StringRef UniqueName;
CV_DESERIALIZE(Data, L, Name, CV_DESERIALIZE(Reader, L, Name,
CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
uint16_t P = L->Properties; uint16_t P = L->Properties;
@ -187,97 +190,98 @@ Expected<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
UniqueName, L->UnderlyingType); UniqueName, L->UnderlyingType);
} }
Expected<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind, Expected<BitFieldRecord>
ArrayRef<uint8_t> &Data) { BitFieldRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
CV_DESERIALIZE(Data, L); CV_DESERIALIZE(Reader, L);
return BitFieldRecord(L->Type, L->BitSize, L->BitOffset); return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
} }
Expected<VFTableShapeRecord> Expected<VFTableShapeRecord>
VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { VFTableShapeRecord::deserialize(TypeRecordKind Kind,
msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
std::vector<VFTableSlotKind> Slots; std::vector<VFTableSlotKind> Slots;
uint16_t Count = L->VFEntryCount; uint16_t Count = L->VFEntryCount;
while (Count > 0) { 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) // 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)); Slots.push_back(static_cast<VFTableSlotKind>(Value));
if (--Count > 0) { if (--Count > 0) {
Value = (Data[0] & 0xF0) >> 4; Value = (Data & 0xF0) >> 4;
Slots.push_back(static_cast<VFTableSlotKind>(Value)); Slots.push_back(static_cast<VFTableSlotKind>(Value));
--Count; --Count;
} }
Data = Data.slice(1);
} }
return VFTableShapeRecord(Slots); return VFTableShapeRecord(Slots);
} }
Expected<TypeServer2Record> Expected<TypeServer2Record>
TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { TypeServer2Record::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name); return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
} }
Expected<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind, Expected<StringIdRecord>
ArrayRef<uint8_t> &Data) { StringIdRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return StringIdRecord(L->id, Name); return StringIdRecord(L->id, Name);
} }
Expected<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind, Expected<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return FuncIdRecord(L->ParentScope, L->FunctionType, Name); return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
} }
Expected<UdtSourceLineRecord> Expected<UdtSourceLineRecord>
UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { UdtSourceLineRecord::deserialize(TypeRecordKind Kind,
msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
CV_DESERIALIZE(Data, L); CV_DESERIALIZE(Reader, L);
return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber); return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
} }
Expected<BuildInfoRecord> Expected<BuildInfoRecord>
BuildInfoRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { BuildInfoRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
ArrayRef<TypeIndex> Indices; 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); return BuildInfoRecord(Indices);
} }
Expected<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind, Expected<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
std::vector<StringRef> Names; 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, return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
Name, Names); Name, Names);
} }
Expected<OneMethodRecord> Expected<OneMethodRecord>
OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { OneMethodRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
int32_t VFTableOffset = -1; int32_t VFTableOffset = -1;
CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset, CV_DESERIALIZE(Reader, L, CV_CONDITIONAL_FIELD(
L->Attrs.isIntroducedVirtual()), VFTableOffset, L->Attrs.isIntroducedVirtual()),
Name); Name);
MethodOptions Options = L->Attrs.getFlags(); MethodOptions Options = L->Attrs.getFlags();
@ -294,13 +298,14 @@ OneMethodRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
Expected<MethodOverloadListRecord> Expected<MethodOverloadListRecord>
MethodOverloadListRecord::deserialize(TypeRecordKind Kind, MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
std::vector<OneMethodRecord> Methods; std::vector<OneMethodRecord> Methods;
while (!Data.empty()) { while (!Reader.empty()) {
const Layout *L = nullptr; const Layout *L = nullptr;
int32_t VFTableOffset = -1; int32_t VFTableOffset = -1;
CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD( CV_DESERIALIZE(
VFTableOffset, L->Attrs.isIntroducedVirtual())); Reader, L,
CV_CONDITIONAL_FIELD(VFTableOffset, L->Attrs.isIntroducedVirtual()));
MethodOptions Options = L->Attrs.getFlags(); MethodOptions Options = L->Attrs.getFlags();
MethodKind MethKind = L->Attrs.getMethodKind(); MethodKind MethKind = L->Attrs.getMethodKind();
@ -320,72 +325,72 @@ MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
Expected<OverloadedMethodRecord> Expected<OverloadedMethodRecord>
OverloadedMethodRecord::deserialize(TypeRecordKind Kind, OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return OverloadedMethodRecord(L->MethodCount, L->MethList, Name); return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
} }
Expected<DataMemberRecord> Expected<DataMemberRecord>
DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { DataMemberRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
uint64_t Offset; uint64_t Offset;
StringRef Name; 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); return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
} }
Expected<StaticDataMemberRecord> Expected<StaticDataMemberRecord>
StaticDataMemberRecord::deserialize(TypeRecordKind Kind, StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Name); CV_DESERIALIZE(Reader, L, Name);
return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name); return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
} }
Expected<EnumeratorRecord> Expected<EnumeratorRecord>
EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { EnumeratorRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
APSInt Value; APSInt Value;
StringRef Name; StringRef Name;
CV_DESERIALIZE(Data, L, Value, Name); CV_DESERIALIZE(Reader, L, Value, Name);
return EnumeratorRecord(L->Attrs.getAccess(), Value, Name); return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
} }
Expected<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind, Expected<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
if (auto EC = consumeObject(Data, L)) if (auto EC = Reader.readObject(L))
return std::move(EC); return std::move(EC);
return VFPtrRecord(L->Type); return VFPtrRecord(L->Type);
} }
Expected<BaseClassRecord> Expected<BaseClassRecord>
BaseClassRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { BaseClassRecord::deserialize(TypeRecordKind Kind, msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
uint64_t Offset; 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); return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
} }
Expected<VirtualBaseClassRecord> Expected<VirtualBaseClassRecord>
VirtualBaseClassRecord::deserialize(TypeRecordKind Kind, VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
uint64_t Offset; uint64_t Offset;
uint64_t Index; 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, return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
Offset, Index); Offset, Index);
} }
Expected<ListContinuationRecord> Expected<ListContinuationRecord>
ListContinuationRecord::deserialize(TypeRecordKind Kind, ListContinuationRecord::deserialize(TypeRecordKind Kind,
ArrayRef<uint8_t> &Data) { msf::StreamReader &Reader) {
const Layout *L = nullptr; const Layout *L = nullptr;
CV_DESERIALIZE(Data, L); CV_DESERIALIZE(Reader, L);
return ListContinuationRecord(L->ContinuationIndex); return ListContinuationRecord(L->ContinuationIndex);
} }

View File

@ -31,6 +31,14 @@ Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
return Error::success(); 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) { Error StreamReader::readInteger(uint16_t &Dest) {
const support::ulittle16_t *P; const support::ulittle16_t *P;
if (auto EC = readObject(P)) if (auto EC = readObject(P))
@ -47,6 +55,46 @@ Error StreamReader::readInteger(uint32_t &Dest) {
return Error::success(); 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) { Error StreamReader::readZeroString(StringRef &Dest) {
uint32_t Length = 0; uint32_t Length = 0;
// First compute the length of the string by reading 1 byte at a time. // 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; Offset += Length;
return Error::success(); 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];
}

View File

@ -154,8 +154,13 @@ public:
Sec = Obj->getCOFFSection(SR); Sec = Obj->getCOFFSection(SR);
} }
uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override { uint32_t getRecordOffset(msf::StreamReader Reader) override {
return Record.data() - SectionContents.bytes_begin(); 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, void printRelocatedField(StringRef Label, uint32_t RelocOffset,
@ -835,8 +840,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
} }
case ModuleSubstreamKind::FrameData: { case ModuleSubstreamKind::FrameData: {
// First four bytes is a relocation against the function. // First four bytes is a relocation against the function.
msf::ByteStream S(Contents);
msf::StreamReader SR(S);
const uint32_t *CodePtr; const uint32_t *CodePtr;
error(consumeObject(Contents, CodePtr)); error(SR.readObject(CodePtr));
StringRef LinkageName; StringRef LinkageName;
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents, error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
CodePtr, LinkageName)); CodePtr, LinkageName));
@ -844,9 +851,9 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
// To find the active frame description, search this array for the // To find the active frame description, search this array for the
// smallest PC range that includes the current PC. // smallest PC range that includes the current PC.
while (!Contents.empty()) { while (!SR.empty()) {
const FrameData *FD; const FrameData *FD;
error(consumeObject(Contents, FD)); error(SR.readObject(FD));
if (FD->FrameFunc >= CVStringTable.size()) if (FD->FrameFunc >= CVStringTable.size())
error(object_error::parse_failed); error(object_error::parse_failed);
@ -974,11 +981,12 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
} }
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
StringRef Data = Subsection; msf::ByteStream S(Subsection);
while (!Data.empty()) { msf::StreamReader SR(S);
while (!SR.empty()) {
DictScope S(W, "FileChecksum"); DictScope S(W, "FileChecksum");
const FileChecksum *FC; const FileChecksum *FC;
error(consumeObject(Data, FC)); error(SR.readObject(FC));
if (FC->FileNameOffset >= CVStringTable.size()) if (FC->FileNameOffset >= CVStringTable.size())
error(object_error::parse_failed); error(object_error::parse_failed);
StringRef Filename = StringRef Filename =
@ -987,27 +995,30 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
W.printHex("ChecksumSize", FC->ChecksumSize); W.printHex("ChecksumSize", FC->ChecksumSize);
W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind), W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind),
makeArrayRef(FileChecksumKindNames)); makeArrayRef(FileChecksumKindNames));
if (FC->ChecksumSize >= Data.size()) if (FC->ChecksumSize >= SR.bytesRemaining())
error(object_error::parse_failed); 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); W.printBinary("ChecksumBytes", ChecksumBytes);
unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) - unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) -
sizeof(FileChecksum); sizeof(FileChecksum);
if (PaddedSize > Data.size()) PaddedSize -= ChecksumBytes.size();
if (PaddedSize > SR.bytesRemaining())
error(object_error::parse_failed); error(object_error::parse_failed);
Data = Data.drop_front(PaddedSize); error(SR.skip(PaddedSize));
} }
} }
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
StringRef Data = Subsection; msf::ByteStream S(Subsection);
msf::StreamReader SR(S);
uint32_t Signature; uint32_t Signature;
error(consume(Data, Signature)); error(SR.readInteger(Signature));
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles); bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
while (!Data.empty()) { while (!SR.empty()) {
const InlineeSourceLine *ISL; const InlineeSourceLine *ISL;
error(consumeObject(Data, ISL)); error(SR.readObject(ISL));
DictScope S(W, "InlineeSourceLine"); DictScope S(W, "InlineeSourceLine");
printTypeIndex("Inlinee", ISL->Inlinee); printTypeIndex("Inlinee", ISL->Inlinee);
printFileNameForOffset("FileID", ISL->FileID); printFileNameForOffset("FileID", ISL->FileID);
@ -1015,12 +1026,12 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
if (HasExtraFiles) { if (HasExtraFiles) {
uint32_t ExtraFileCount; uint32_t ExtraFileCount;
error(consume(Data, ExtraFileCount)); error(SR.readInteger(ExtraFileCount));
W.printNumber("ExtraFileCount", ExtraFileCount); W.printNumber("ExtraFileCount", ExtraFileCount);
ListScope ExtraFiles(W, "ExtraFiles"); ListScope ExtraFiles(W, "ExtraFiles");
for (unsigned I = 0; I < ExtraFileCount; ++I) { for (unsigned I = 0; I < ExtraFileCount; ++I) {
uint32_t FileID; uint32_t FileID;
error(consume(Data, FileID)); error(SR.readInteger(FileID));
printFileNameForOffset("FileID", FileID); printFileNameForOffset("FileID", FileID);
} }
} }