File indexing completed on 2026-05-10 08:43:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
0010 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/STLExtras.h"
0014 #include "llvm/DebugInfo/CodeView/CodeView.h"
0015 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
0016 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
0017 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
0018 #include "llvm/Support/BinaryByteStream.h"
0019 #include "llvm/Support/BinaryStreamReader.h"
0020 #include "llvm/Support/Error.h"
0021 #include <cassert>
0022 #include <cstdint>
0023 #include <memory>
0024
0025 namespace llvm {
0026 namespace codeview {
0027
0028 class TypeDeserializer : public TypeVisitorCallbacks {
0029 struct MappingInfo {
0030 explicit MappingInfo(ArrayRef<uint8_t> RecordData)
0031 : Stream(RecordData, llvm::endianness::little), Reader(Stream),
0032 Mapping(Reader) {}
0033
0034 BinaryByteStream Stream;
0035 BinaryStreamReader Reader;
0036 TypeRecordMapping Mapping;
0037 };
0038
0039 public:
0040 TypeDeserializer() = default;
0041
0042 template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
0043 Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
0044 MappingInfo I(CVT.content());
0045 if (auto EC = I.Mapping.visitTypeBegin(CVT))
0046 return EC;
0047 if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
0048 return EC;
0049 if (auto EC = I.Mapping.visitTypeEnd(CVT))
0050 return EC;
0051 return Error::success();
0052 }
0053
0054 template <typename T>
0055 static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
0056 const RecordPrefix *Prefix =
0057 reinterpret_cast<const RecordPrefix *>(Data.data());
0058 TypeRecordKind K =
0059 static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
0060 T Record(K);
0061 CVType CVT(Data);
0062 if (auto EC = deserializeAs<T>(CVT, Record))
0063 return std::move(EC);
0064 return Record;
0065 }
0066
0067 Error visitTypeBegin(CVType &Record) override {
0068 assert(!Mapping && "Already in a type mapping!");
0069 Mapping = std::make_unique<MappingInfo>(Record.content());
0070 return Mapping->Mapping.visitTypeBegin(Record);
0071 }
0072
0073 Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
0074 return visitTypeBegin(Record);
0075 }
0076
0077 Error visitTypeEnd(CVType &Record) override {
0078 assert(Mapping && "Not in a type mapping!");
0079 auto EC = Mapping->Mapping.visitTypeEnd(Record);
0080 Mapping.reset();
0081 return EC;
0082 }
0083
0084 #define TYPE_RECORD(EnumName, EnumVal, Name) \
0085 Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
0086 return visitKnownRecordImpl<Name##Record>(CVR, Record); \
0087 }
0088 #define MEMBER_RECORD(EnumName, EnumVal, Name)
0089 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0090 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0091 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
0092
0093 private:
0094 template <typename RecordType>
0095 Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
0096 return Mapping->Mapping.visitKnownRecord(CVR, Record);
0097 }
0098
0099 std::unique_ptr<MappingInfo> Mapping;
0100 };
0101
0102 class FieldListDeserializer : public TypeVisitorCallbacks {
0103 struct MappingInfo {
0104 explicit MappingInfo(BinaryStreamReader &R)
0105 : Reader(R), Mapping(Reader), StartOffset(0) {}
0106
0107 BinaryStreamReader &Reader;
0108 TypeRecordMapping Mapping;
0109 uint32_t StartOffset;
0110 };
0111
0112 public:
0113 explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
0114 RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
0115 CVType FieldList(&Pre, sizeof(Pre));
0116 consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
0117 }
0118
0119 ~FieldListDeserializer() override {
0120 RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
0121 CVType FieldList(&Pre, sizeof(Pre));
0122 consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
0123 }
0124
0125 Error visitMemberBegin(CVMemberRecord &Record) override {
0126 Mapping.StartOffset = Mapping.Reader.getOffset();
0127 return Mapping.Mapping.visitMemberBegin(Record);
0128 }
0129
0130 Error visitMemberEnd(CVMemberRecord &Record) override {
0131 if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
0132 return EC;
0133 return Error::success();
0134 }
0135
0136 #define TYPE_RECORD(EnumName, EnumVal, Name)
0137 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
0138 Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
0139 return visitKnownMemberImpl<Name##Record>(CVR, Record); \
0140 }
0141 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0142 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0143 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
0144
0145 private:
0146 template <typename RecordType>
0147 Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
0148 if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
0149 return EC;
0150
0151 uint32_t EndOffset = Mapping.Reader.getOffset();
0152 uint32_t RecordLength = EndOffset - Mapping.StartOffset;
0153 Mapping.Reader.setOffset(Mapping.StartOffset);
0154 if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
0155 return EC;
0156 assert(Mapping.Reader.getOffset() == EndOffset);
0157 return Error::success();
0158 }
0159 MappingInfo Mapping;
0160 };
0161
0162 }
0163 }
0164
0165 #endif