mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-13 14:46:53 +00:00
[pdb] Get rid of Data and RawData in CVType.
The `CVType` had two redundant fields which were confusing and error-prone to fill out. By treating member records as a distinct type from leaf records, we are able to simplify this quite a bit. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D24432 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281556 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a9d16c9445
commit
b5689e754e
@ -22,14 +22,27 @@
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
template <typename Kind> struct CVRecord {
|
||||
uint32_t Length;
|
||||
template <typename Kind> class CVRecord {
|
||||
public:
|
||||
CVRecord() {}
|
||||
CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
|
||||
|
||||
uint32_t length() const { return RecordData.size(); }
|
||||
Kind kind() const { return Type; }
|
||||
ArrayRef<uint8_t> data() const { return RecordData; }
|
||||
ArrayRef<uint8_t> content() const {
|
||||
return RecordData.drop_front(sizeof(RecordPrefix));
|
||||
}
|
||||
Optional<uint32_t> hash() const { return Hash; }
|
||||
|
||||
void setHash(uint32_t Value) { Hash = Value; }
|
||||
|
||||
Kind Type;
|
||||
ArrayRef<uint8_t> Data;
|
||||
ArrayRef<uint8_t> RawData;
|
||||
ArrayRef<uint8_t> RecordData;
|
||||
Optional<uint32_t> Hash;
|
||||
};
|
||||
}
|
||||
|
||||
namespace msf {
|
||||
|
||||
template <typename Kind>
|
||||
@ -43,17 +56,17 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
|
||||
|
||||
if (auto EC = Reader.readObject(Prefix))
|
||||
return EC;
|
||||
Item.Length = Prefix->RecordLen;
|
||||
if (Item.Length < 2)
|
||||
if (Prefix->RecordLen < 2)
|
||||
return make_error<CodeViewError>(cv_error_code::corrupt_record);
|
||||
Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind));
|
||||
Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
|
||||
|
||||
Reader.setOffset(Offset);
|
||||
ArrayRef<uint8_t> RawData;
|
||||
if (auto EC =
|
||||
Reader.readBytes(Item.RawData, Item.Length + sizeof(uint16_t)))
|
||||
Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
|
||||
return EC;
|
||||
Item.Data = Item.RawData.slice(sizeof(RecordPrefix));
|
||||
Len = Prefix->RecordLen + 2;
|
||||
Item = codeview::CVRecord<Kind>(K, RawData);
|
||||
Len = Item.length();
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
#include "CVSymbolTypes.def"
|
||||
|
||||
void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
|
||||
ArrayRef<uint8_t> Data = Record.Data;
|
||||
ArrayRef<uint8_t> Data = Record.content();
|
||||
auto *DerivedThis = static_cast<Derived *>(this);
|
||||
DerivedThis->visitSymbolBegin(Record.Type, Data);
|
||||
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
|
||||
@ -70,7 +70,7 @@ public:
|
||||
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#include "CVSymbolTypes.def"
|
||||
}
|
||||
DerivedThis->visitSymbolEnd(Record.Type, Record.Data);
|
||||
DerivedThis->visitSymbolEnd(Record.Type, Record.content());
|
||||
}
|
||||
|
||||
/// Visits the symbol records in Data. Sets the error flag on parse failures.
|
||||
|
@ -23,7 +23,8 @@ class CVTypeVisitor {
|
||||
public:
|
||||
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
|
||||
|
||||
Error visitTypeRecord(CVRecord<TypeLeafKind> &Record);
|
||||
Error visitTypeRecord(CVType &Record);
|
||||
Error visitMemberRecord(CVMemberRecord &Record);
|
||||
|
||||
/// Visits the type records in Data. Sets the error flag on parse failures.
|
||||
Error visitTypeStream(const CVTypeArray &Types);
|
||||
|
@ -20,12 +20,13 @@ public:
|
||||
TypeDeserializer() {}
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
|
||||
override { \
|
||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
|
||||
return defaultVisitKnownRecord(CVR, Record); \
|
||||
}
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
|
||||
return defaultVisitKnownMember(CVR, Record); \
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "TypeRecords.def"
|
||||
@ -44,13 +45,19 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
Error defaultVisitKnownRecord(CVRecord<TypeLeafKind> &CVR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVR.Data;
|
||||
template <typename T> Error defaultVisitKnownRecord(CVType &CVR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVR.content();
|
||||
if (auto EC = deserializeRecord(RD, CVR.Type, Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
template <typename T>
|
||||
Error defaultVisitKnownMember(CVMemberRecord &CVMR, T &Record) {
|
||||
ArrayRef<uint8_t> RD = CVMR.Data;
|
||||
if (auto EC = deserializeRecord(RD, CVMR.Kind, Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -63,19 +63,20 @@ public:
|
||||
ScopedPrinter *getPrinter() { return W; }
|
||||
|
||||
/// Action to take on unknown types. By default, they are ignored.
|
||||
Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitUnknownType(CVType &Record) override;
|
||||
Error visitUnknownMember(CVMemberRecord &Record) override;
|
||||
|
||||
/// Paired begin/end actions for all types. Receives all record data,
|
||||
/// including the fixed-length record prefix.
|
||||
Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitTypeBegin(CVType &Record) override;
|
||||
Error visitTypeEnd(CVType &Record) override;
|
||||
Error visitMemberBegin(CVMemberRecord &Record) override;
|
||||
Error visitMemberEnd(CVMemberRecord &Record) override;
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
|
||||
override;
|
||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "TypeRecords.def"
|
||||
|
@ -29,6 +29,11 @@ using llvm::support::ulittle16_t;
|
||||
using llvm::support::ulittle32_t;
|
||||
|
||||
typedef CVRecord<TypeLeafKind> CVType;
|
||||
|
||||
struct CVMemberRecord {
|
||||
TypeLeafKind Kind;
|
||||
ArrayRef<uint8_t> Data;
|
||||
};
|
||||
typedef msf::VarStreamArray<CVType> CVTypeArray;
|
||||
|
||||
/// Equvalent to CV_fldattr_t in cvinfo.h.
|
||||
|
@ -51,7 +51,8 @@ public:
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
|
||||
virtual Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) \
|
||||
override { \
|
||||
visitMemberRecordImpl(Record); \
|
||||
return Error::success(); \
|
||||
}
|
||||
@ -61,10 +62,7 @@ public:
|
||||
private:
|
||||
void updateCVRecord(CVType &Record) {
|
||||
StringRef S = TypeTableBuilder.getRecords().back();
|
||||
ArrayRef<uint8_t> Data(S.bytes_begin(), S.bytes_end());
|
||||
Record.RawData = Data;
|
||||
Record.Data = Record.RawData.drop_front(sizeof(RecordPrefix));
|
||||
Record.Length = Data.size() - sizeof(ulittle16_t);
|
||||
Record.RecordData = ArrayRef<uint8_t>(S.bytes_begin(), S.bytes_end());
|
||||
}
|
||||
template <typename RecordKind>
|
||||
void visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
virtual Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) override {
|
||||
virtual Error visitUnknownMember(CVMemberRecord &Record) override {
|
||||
for (auto Visitor : Pipeline) {
|
||||
if (auto EC = Visitor->visitUnknownMember(Record))
|
||||
return EC;
|
||||
@ -38,14 +38,14 @@ public:
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override {
|
||||
virtual Error visitTypeBegin(CVType &Record) override {
|
||||
for (auto Visitor : Pipeline) {
|
||||
if (auto EC = Visitor->visitTypeBegin(Record))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
virtual Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override {
|
||||
virtual Error visitTypeEnd(CVType &Record) override {
|
||||
for (auto Visitor : Pipeline) {
|
||||
if (auto EC = Visitor->visitTypeEnd(Record))
|
||||
return EC;
|
||||
@ -53,13 +53,27 @@ public:
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
virtual Error visitMemberBegin(CVMemberRecord &Record) override {
|
||||
for (auto Visitor : Pipeline) {
|
||||
if (auto EC = Visitor->visitMemberBegin(Record))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
virtual Error visitMemberEnd(CVMemberRecord &Record) override {
|
||||
for (auto Visitor : Pipeline) {
|
||||
if (auto EC = Visitor->visitMemberEnd(Record))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks) {
|
||||
Pipeline.push_back(&Callbacks);
|
||||
}
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
|
||||
override { \
|
||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
|
||||
for (auto Visitor : Pipeline) { \
|
||||
if (auto EC = Visitor->visitKnownRecord(CVR, Record)) \
|
||||
return EC; \
|
||||
@ -67,7 +81,14 @@ public:
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
Error visitKnownMember(CVMemberRecord &CVMR, Name##Record &Record) \
|
||||
override { \
|
||||
for (auto Visitor : Pipeline) { \
|
||||
if (auto EC = Visitor->visitKnownMember(CVMR, Record)) \
|
||||
return EC; \
|
||||
} \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
@ -25,30 +25,32 @@ public:
|
||||
virtual ~TypeVisitorCallbacks() {}
|
||||
|
||||
/// Action to take on unknown types. By default, they are ignored.
|
||||
virtual Error visitUnknownType(CVRecord<TypeLeafKind> &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
virtual Error visitUnknownMember(CVRecord<TypeLeafKind> &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
virtual Error visitUnknownType(CVType &Record) { return Error::success(); }
|
||||
/// Paired begin/end actions for all types. Receives all record data,
|
||||
/// including the fixed-length record prefix. visitTypeBegin() should return
|
||||
/// the type of the Record, or an error if it cannot be determined.
|
||||
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
|
||||
virtual Error visitTypeBegin(CVType &Record) { return Error::success(); }
|
||||
virtual Error visitTypeEnd(CVType &Record) { return Error::success(); }
|
||||
|
||||
virtual Error visitUnknownMember(CVMemberRecord &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
virtual Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) {
|
||||
virtual Error visitMemberBegin(CVMemberRecord &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
virtual Error visitMemberEnd(CVMemberRecord &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
virtual Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
|
||||
Name##Record &Record) { \
|
||||
virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) { \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
virtual Error visitKnownMember(CVMemberRecord &CVM, Name##Record &Record) { \
|
||||
return Error::success(); \
|
||||
}
|
||||
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "TypeRecords.def"
|
||||
|
@ -32,11 +32,9 @@ class ReadableStreamRef;
|
||||
class WritableStream;
|
||||
|
||||
template <> struct SequencedItemTraits<llvm::codeview::CVType> {
|
||||
static size_t length(const codeview::CVType &Item) {
|
||||
return Item.RawData.size();
|
||||
}
|
||||
static size_t length(const codeview::CVType &Item) { return Item.length(); }
|
||||
static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
|
||||
return Item.RawData;
|
||||
return Item.data();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ static Error skipPadding(ArrayRef<uint8_t> &Data) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
|
||||
TypeLeafKind Kind) {
|
||||
static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
|
||||
TypeLeafKind Kind) {
|
||||
ArrayRef<uint8_t> OldData = Data;
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
|
||||
auto ExpectedRecord = T::deserialize(RK, Data);
|
||||
@ -53,20 +53,17 @@ static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
|
||||
if (auto EC = skipPadding(Data))
|
||||
return std::move(EC);
|
||||
|
||||
CVType CVR;
|
||||
CVR.Type = Kind;
|
||||
CVR.Length = OldData.size() - Data.size();
|
||||
CVR.Data = OldData.slice(0, CVR.Length);
|
||||
CVR.RawData = CVR.Data;
|
||||
return CVR;
|
||||
CVMemberRecord CVMR;
|
||||
CVMR.Kind = Kind;
|
||||
CVMR.Data = OldData.drop_back(Data.size());
|
||||
return CVMR;
|
||||
}
|
||||
|
||||
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
|
||||
: Callbacks(Callbacks) {}
|
||||
|
||||
template <typename T>
|
||||
static Error visitKnownRecord(CVRecord<TypeLeafKind> &Record,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
|
||||
T KnownRecord(RK);
|
||||
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
|
||||
@ -74,7 +71,17 @@ static Error visitKnownRecord(CVRecord<TypeLeafKind> &Record,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
|
||||
template <typename T>
|
||||
static Error visitKnownMember(CVMemberRecord &Record,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
|
||||
T KnownRecord(RK);
|
||||
if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
|
||||
if (auto EC = Callbacks.visitTypeBegin(Record))
|
||||
return EC;
|
||||
|
||||
@ -91,10 +98,8 @@ Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
TYPE_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
MEMBER_RECORD(EnumName, EnumVal, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
}
|
||||
|
||||
@ -104,6 +109,34 @@ Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
|
||||
if (auto EC = Callbacks.visitMemberBegin(Record))
|
||||
return EC;
|
||||
|
||||
switch (Record.Kind) {
|
||||
default:
|
||||
if (auto EC = Callbacks.visitUnknownMember(Record))
|
||||
return EC;
|
||||
break;
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
case EnumName: { \
|
||||
if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
|
||||
return EC; \
|
||||
break; \
|
||||
}
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
}
|
||||
|
||||
if (auto EC = Callbacks.visitMemberEnd(Record))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Visits the type records in Data. Sets the error flag on parse failures.
|
||||
Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
|
||||
for (auto I : Types) {
|
||||
@ -119,12 +152,12 @@ static Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Leaf,
|
||||
auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf);
|
||||
if (!ExpectedRecord)
|
||||
return ExpectedRecord.takeError();
|
||||
CVType &Record = *ExpectedRecord;
|
||||
if (auto EC = Callbacks.visitTypeBegin(Record))
|
||||
CVMemberRecord &Record = *ExpectedRecord;
|
||||
if (auto EC = Callbacks.visitMemberBegin(Record))
|
||||
return EC;
|
||||
if (auto EC = visitKnownRecord<MR>(Record, Callbacks))
|
||||
if (auto EC = visitKnownMember<MR>(Record, Callbacks))
|
||||
return EC;
|
||||
if (auto EC = Callbacks.visitTypeEnd(Record))
|
||||
if (auto EC = Callbacks.visitMemberEnd(Record))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -204,15 +204,12 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
|
||||
assert(!IsInFieldList);
|
||||
// Reset Name to the empty string. If the visitor sets it, we know it.
|
||||
Name = "";
|
||||
|
||||
W->startLine() << getLeafTypeName(Record.Type);
|
||||
if (!IsInFieldList) {
|
||||
// If this is a field list member, don't record its type index because it
|
||||
// doesn't have one. Only the outer field list has a type index.
|
||||
W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
|
||||
}
|
||||
W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
|
||||
W->getOStream() << " {\n";
|
||||
W->indent();
|
||||
W->printEnum("TypeLeafKind", unsigned(Record.Type),
|
||||
@ -220,7 +217,6 @@ Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
|
||||
if (Record.Type == LF_FIELDLIST) {
|
||||
// Record that we're in a field list so that members do not get assigned
|
||||
// type indices.
|
||||
assert(!IsInFieldList);
|
||||
IsInFieldList = true;
|
||||
}
|
||||
return Error::success();
|
||||
@ -231,15 +227,37 @@ Error CVTypeDumper::visitTypeEnd(CVRecord<TypeLeafKind> &Record) {
|
||||
assert(IsInFieldList);
|
||||
IsInFieldList = false;
|
||||
}
|
||||
assert(!IsInFieldList);
|
||||
|
||||
if (!IsInFieldList) {
|
||||
// Record every type that is not a field list member, even if Name is empty.
|
||||
// CVUDTNames is indexed by type index, and must have one entry for every
|
||||
// type. Field list members are not recorded, and are only referenced by
|
||||
// their containing field list record.
|
||||
recordType(Name);
|
||||
}
|
||||
// Record every type that is not a field list member, even if Name is empty.
|
||||
// CVUDTNames is indexed by type index, and must have one entry for every
|
||||
// type. Field list members are not recorded, and are only referenced by
|
||||
// their containing field list record.
|
||||
recordType(Name);
|
||||
|
||||
if (PrintRecordBytes)
|
||||
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
|
||||
|
||||
W->unindent();
|
||||
W->startLine() << "}\n";
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) {
|
||||
assert(IsInFieldList);
|
||||
// Reset Name to the empty string. If the visitor sets it, we know it.
|
||||
Name = "";
|
||||
|
||||
W->startLine() << getLeafTypeName(Record.Kind);
|
||||
W->getOStream() << " {\n";
|
||||
W->indent();
|
||||
W->printEnum("TypeLeafKind", unsigned(Record.Kind),
|
||||
makeArrayRef(LeafTypeNames));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
|
||||
assert(IsInFieldList);
|
||||
if (PrintRecordBytes)
|
||||
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
|
||||
|
||||
@ -573,18 +591,18 @@ void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
|
||||
}
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitUnknownMember(CVRecord<TypeLeafKind> &Record) {
|
||||
W->printHex("UnknownMember", unsigned(Record.Type));
|
||||
Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) {
|
||||
W->printHex("UnknownMember", unsigned(Record.Kind));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitUnknownType(CVRecord<TypeLeafKind> &Record) {
|
||||
W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
|
||||
W->printNumber("Length", uint32_t(Record.Data.size()));
|
||||
W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
|
||||
W->printNumber("Length", uint32_t(Record.content().size()));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
NestedTypeRecord &Nested) {
|
||||
printTypeIndex("Type", Nested.getNestedType());
|
||||
W->printString("Name", Nested.getName());
|
||||
@ -592,7 +610,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
OneMethodRecord &Method) {
|
||||
MethodKind K = Method.getKind();
|
||||
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
|
||||
@ -605,7 +623,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
OverloadedMethodRecord &Method) {
|
||||
W->printHex("MethodCount", Method.getNumOverloads());
|
||||
printTypeIndex("MethodListIndex", Method.getMethodList());
|
||||
@ -614,7 +632,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
DataMemberRecord &Field) {
|
||||
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
@ -625,7 +643,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
StaticDataMemberRecord &Field) {
|
||||
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
@ -635,13 +653,13 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
VFPtrRecord &VFTable) {
|
||||
printTypeIndex("Type", VFTable.getType());
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
EnumeratorRecord &Enum) {
|
||||
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
@ -651,7 +669,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
BaseClassRecord &Base) {
|
||||
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
@ -660,7 +678,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
VirtualBaseClassRecord &Base) {
|
||||
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
|
||||
MethodOptions::None);
|
||||
@ -671,7 +689,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
||||
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
|
||||
ListContinuationRecord &Cont) {
|
||||
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
|
||||
return Error::success();
|
||||
|
@ -60,18 +60,18 @@ public:
|
||||
|
||||
/// TypeVisitorCallbacks overrides.
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
|
||||
override;
|
||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
||||
Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitUnknownType(CVType &Record) override;
|
||||
|
||||
Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override;
|
||||
Error visitTypeBegin(CVType &Record) override;
|
||||
Error visitTypeEnd(CVType &Record) override;
|
||||
Error visitMemberEnd(CVMemberRecord &Record) override;
|
||||
|
||||
bool mergeStream(const CVTypeArray &Types);
|
||||
|
||||
@ -137,27 +137,30 @@ Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) {
|
||||
IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
|
||||
FieldBuilder.reset();
|
||||
IsInFieldList = false;
|
||||
} else if (!IsInFieldList) {
|
||||
assert(IndexMap.size() == BeginIndexMapSize + 1);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
|
||||
assert(IndexMap.size() == BeginIndexMapSize + 1);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
|
||||
Error TypeStreamMerger::visitKnownRecord(CVType &CVR, \
|
||||
Name##Record &Record) { \
|
||||
return visitKnownRecordImpl(Record); \
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, \
|
||||
Error TypeStreamMerger::visitKnownMember(CVMemberRecord &CVR, \
|
||||
Name##Record &Record) { \
|
||||
return visitKnownMemberRecordImpl(Record); \
|
||||
}
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
||||
Error TypeStreamMerger::visitUnknownType(CVRecord<TypeLeafKind> &Rec) {
|
||||
Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
|
||||
// We failed to translate a type. Translate this index as "not translated".
|
||||
IndexMap.push_back(
|
||||
TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));
|
||||
|
@ -58,15 +58,15 @@ void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
|
||||
}
|
||||
|
||||
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
|
||||
CVR.Hash = getTpiHash(Rec, CVR.RawData);
|
||||
CVR.Hash = getTpiHash(Rec, CVR.data());
|
||||
}
|
||||
|
||||
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
|
||||
CVR.Hash = getTpiHash(Rec, CVR.RawData);
|
||||
CVR.Hash = getTpiHash(Rec, CVR.data());
|
||||
}
|
||||
|
||||
void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
|
||||
CVR.Hash = getTpiHash(Rec, CVR.RawData);
|
||||
CVR.Hash = getTpiHash(Rec, CVR.data());
|
||||
}
|
||||
|
||||
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
|
||||
@ -79,17 +79,17 @@ Error TpiHashVerifier::visitKnownRecord(CVType &CVR,
|
||||
}
|
||||
|
||||
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
|
||||
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
|
||||
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
|
||||
return errorInvalidHash();
|
||||
return Error::success();
|
||||
}
|
||||
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
|
||||
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
|
||||
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
|
||||
return errorInvalidHash();
|
||||
return Error::success();
|
||||
}
|
||||
Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
|
||||
if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
|
||||
if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
|
||||
return errorInvalidHash();
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -15,7 +15,9 @@
|
||||
#include "llvm/DebugInfo/CodeView/EnumTables.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeSerializationVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
@ -27,33 +29,33 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(CVType)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiFieldListRecord)
|
||||
|
||||
namespace {
|
||||
struct FieldListRecordSplitter : public TypeVisitorCallbacks {
|
||||
public:
|
||||
explicit FieldListRecordSplitter(
|
||||
std::vector<llvm::pdb::yaml::PdbTpiRecord> &Records)
|
||||
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> &Records)
|
||||
: Records(Records) {}
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVType &CVT, Name##Record &Record) override { \
|
||||
visitKnownRecordImpl(CVT); \
|
||||
Error visitKnownMember(CVMemberRecord &CVT, Name##Record &Record) override { \
|
||||
visitKnownMemberImpl(CVT); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
||||
private:
|
||||
void visitKnownRecordImpl(CVType &CVT) {
|
||||
llvm::pdb::yaml::PdbTpiRecord R;
|
||||
void visitKnownMemberImpl(CVMemberRecord &CVT) {
|
||||
llvm::pdb::yaml::PdbTpiFieldListRecord R;
|
||||
R.Record = CVT;
|
||||
Records.push_back(std::move(R));
|
||||
}
|
||||
|
||||
std::vector<llvm::pdb::yaml::PdbTpiRecord> &Records;
|
||||
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> &Records;
|
||||
};
|
||||
}
|
||||
|
||||
@ -525,14 +527,20 @@ void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
|
||||
}
|
||||
|
||||
Error llvm::codeview::yaml::YamlTypeDumperCallbacks::visitTypeBegin(
|
||||
CVRecord<TypeLeafKind> &CVR) {
|
||||
CVType &CVR) {
|
||||
YamlIO.mapRequired("Kind", CVR.Type);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error llvm::codeview::yaml::YamlTypeDumperCallbacks::visitMemberBegin(
|
||||
CVMemberRecord &Record) {
|
||||
YamlIO.mapRequired("Kind", Record.Kind);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
|
||||
const char *Name, CVType &CVR, FieldListRecord &FieldList) {
|
||||
std::vector<llvm::pdb::yaml::PdbTpiRecord> FieldListRecords;
|
||||
std::vector<llvm::pdb::yaml::PdbTpiFieldListRecord> FieldListRecords;
|
||||
if (YamlIO.outputting()) {
|
||||
// If we are outputting, then `FieldList.Data` contains a huge chunk of data
|
||||
// representing the serialized list of members. We need to split it up into
|
||||
@ -551,3 +559,36 @@ void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
|
||||
}
|
||||
YamlIO.mapRequired("FieldList", FieldListRecords, Context);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
template <>
|
||||
struct MappingContextTraits<pdb::yaml::PdbTpiFieldListRecord,
|
||||
pdb::yaml::SerializationContext> {
|
||||
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj,
|
||||
pdb::yaml::SerializationContext &Context) {
|
||||
codeview::TypeVisitorCallbackPipeline Pipeline;
|
||||
codeview::TypeDeserializer Deserializer;
|
||||
codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder,
|
||||
Context.TypeTableBuilder);
|
||||
pdb::TpiHashUpdater Hasher;
|
||||
|
||||
if (IO.outputting()) {
|
||||
// For PDB to Yaml, deserialize into a high level record type, then dump
|
||||
// it.
|
||||
Pipeline.addCallbackToPipeline(Deserializer);
|
||||
Pipeline.addCallbackToPipeline(Context.Dumper);
|
||||
} else {
|
||||
// For Yaml to PDB, extract from the high level record type, then write it
|
||||
// to bytes.
|
||||
Pipeline.addCallbackToPipeline(Context.Dumper);
|
||||
Pipeline.addCallbackToPipeline(Serializer);
|
||||
Pipeline.addCallbackToPipeline(Hasher);
|
||||
}
|
||||
|
||||
codeview::CVTypeVisitor Visitor(Pipeline);
|
||||
consumeError(Visitor.visitMemberRecord(Obj.Record));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ public:
|
||||
llvm::pdb::yaml::SerializationContext &Context)
|
||||
: YamlIO(IO), Context(Context) {}
|
||||
|
||||
virtual Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
|
||||
virtual Error visitTypeBegin(CVType &Record) override;
|
||||
virtual Error visitMemberBegin(CVMemberRecord &Record) override;
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record) \
|
||||
@ -38,12 +39,19 @@ public:
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
|
||||
visitKnownMemberImpl(#Name, Record); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
|
||||
|
||||
private:
|
||||
template <typename T> void visitKnownMemberImpl(const char *Name, T &Record) {
|
||||
YamlIO.mapRequired(Name, Record);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void visitKnownRecordImpl(const char *Name, CVType &Type, T &Record) {
|
||||
YamlIO.mapRequired(Name, Record);
|
||||
|
@ -497,7 +497,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||
}
|
||||
|
||||
if (DumpRecordBytes)
|
||||
P.printBinaryBlock("Bytes", Type.Data);
|
||||
P.printBinaryBlock("Bytes", Type.content());
|
||||
}
|
||||
dumpTpiHash(P, *Tpi);
|
||||
if (HadError)
|
||||
@ -604,7 +604,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
||||
if (opts::raw::DumpModuleSyms)
|
||||
SD.dump(S);
|
||||
if (opts::raw::DumpSymRecordBytes)
|
||||
P.printBinaryBlock("Bytes", S.Data);
|
||||
P.printBinaryBlock("Bytes", S.content());
|
||||
}
|
||||
if (HadError)
|
||||
return make_error<RawError>(
|
||||
@ -813,7 +813,7 @@ Error LLVMOutputStyle::dumpPublicsStream() {
|
||||
|
||||
SD.dump(S);
|
||||
if (opts::raw::DumpSymRecordBytes)
|
||||
P.printBinaryBlock("Bytes", S.Data);
|
||||
P.printBinaryBlock("Bytes", S.content());
|
||||
}
|
||||
if (HadError)
|
||||
return make_error<RawError>(
|
||||
|
@ -75,6 +75,10 @@ struct PdbTpiRecord {
|
||||
codeview::CVType Record;
|
||||
};
|
||||
|
||||
struct PdbTpiFieldListRecord {
|
||||
codeview::CVMemberRecord Record;
|
||||
};
|
||||
|
||||
struct PdbTpiStream {
|
||||
PdbRaw_TpiVer Version;
|
||||
std::vector<PdbTpiRecord> Records;
|
||||
|
Loading…
Reference in New Issue
Block a user