Line data Source code
1 : //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
11 : #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
12 :
13 : #include "llvm/ADT/ArrayRef.h"
14 : #include "llvm/ADT/STLExtras.h"
15 : #include "llvm/DebugInfo/CodeView/CodeView.h"
16 : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 : #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
18 : #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
19 : #include "llvm/Support/BinaryByteStream.h"
20 : #include "llvm/Support/BinaryStreamReader.h"
21 : #include "llvm/Support/Error.h"
22 : #include <cassert>
23 : #include <cstdint>
24 : #include <memory>
25 :
26 : namespace llvm {
27 : namespace codeview {
28 :
29 : class TypeDeserializer : public TypeVisitorCallbacks {
30 : struct MappingInfo {
31 : explicit MappingInfo(ArrayRef<uint8_t> RecordData)
32 12007 : : Stream(RecordData, llvm::support::little), Reader(Stream),
33 12007 : Mapping(Reader) {}
34 :
35 : BinaryByteStream Stream;
36 : BinaryStreamReader Reader;
37 : TypeRecordMapping Mapping;
38 : };
39 :
40 : public:
41 4412 : TypeDeserializer() = default;
42 :
43 2646 : template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
44 2646 : Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
45 2646 : MappingInfo I(CVT.content());
46 5292 : if (auto EC = I.Mapping.visitTypeBegin(CVT))
47 : return EC;
48 5292 : if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
49 : return EC;
50 5292 : if (auto EC = I.Mapping.visitTypeEnd(CVT))
51 : return EC;
52 : return Error::success();
53 : }
54 :
55 : template <typename T>
56 : static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
57 : const RecordPrefix *Prefix =
58 : reinterpret_cast<const RecordPrefix *>(Data.data());
59 : TypeRecordKind K =
60 : static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
61 : T Record(K);
62 : CVType CVT(static_cast<TypeLeafKind>(K), Data);
63 : if (auto EC = deserializeAs<T>(CVT, Record))
64 : return std::move(EC);
65 : return Record;
66 : }
67 :
68 9361 : Error visitTypeBegin(CVType &Record) override {
69 : assert(!Mapping && "Already in a type mapping!");
70 9361 : Mapping = llvm::make_unique<MappingInfo>(Record.content());
71 9361 : return Mapping->Mapping.visitTypeBegin(Record);
72 : }
73 :
74 9361 : Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
75 9361 : return visitTypeBegin(Record);
76 : }
77 :
78 9361 : Error visitTypeEnd(CVType &Record) override {
79 : assert(Mapping && "Not in a type mapping!");
80 9361 : auto EC = Mapping->Mapping.visitTypeEnd(Record);
81 : Mapping.reset();
82 9361 : return EC;
83 : }
84 :
85 : #define TYPE_RECORD(EnumName, EnumVal, Name) \
86 : Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
87 : return visitKnownRecordImpl<Name##Record>(CVR, Record); \
88 : }
89 : #define MEMBER_RECORD(EnumName, EnumVal, Name)
90 : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
91 : #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
92 : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
93 :
94 : private:
95 : template <typename RecordType>
96 : Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
97 9361 : return Mapping->Mapping.visitKnownRecord(CVR, Record);
98 : }
99 :
100 : std::unique_ptr<MappingInfo> Mapping;
101 : };
102 :
103 : class FieldListDeserializer : public TypeVisitorCallbacks {
104 : struct MappingInfo {
105 : explicit MappingInfo(BinaryStreamReader &R)
106 903 : : Reader(R), Mapping(Reader), StartOffset(0) {}
107 :
108 : BinaryStreamReader &Reader;
109 : TypeRecordMapping Mapping;
110 : uint32_t StartOffset;
111 : };
112 :
113 : public:
114 903 : explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
115 : CVType FieldList;
116 903 : FieldList.Type = TypeLeafKind::LF_FIELDLIST;
117 903 : consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
118 903 : }
119 :
120 903 : ~FieldListDeserializer() override {
121 : CVType FieldList;
122 903 : FieldList.Type = TypeLeafKind::LF_FIELDLIST;
123 1806 : consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
124 903 : }
125 0 :
126 : Error visitMemberBegin(CVMemberRecord &Record) override {
127 : Mapping.StartOffset = Mapping.Reader.getOffset();
128 : return Mapping.Mapping.visitMemberBegin(Record);
129 0 : }
130 903 :
131 : Error visitMemberEnd(CVMemberRecord &Record) override {
132 903 : if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
133 1806 : return EC;
134 903 : return Error::success();
135 : }
136 9222 :
137 9222 : #define TYPE_RECORD(EnumName, EnumVal, Name)
138 9222 : #define MEMBER_RECORD(EnumName, EnumVal, Name) \
139 : Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
140 : return visitKnownMemberImpl<Name##Record>(CVR, Record); \
141 9222 : }
142 18444 : #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
143 : #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
144 : #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
145 :
146 : private:
147 : template <typename RecordType>
148 : Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
149 : if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
150 : return EC;
151 :
152 : uint32_t EndOffset = Mapping.Reader.getOffset();
153 : uint32_t RecordLength = EndOffset - Mapping.StartOffset;
154 : Mapping.Reader.setOffset(Mapping.StartOffset);
155 : if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
156 : return EC;
157 : assert(Mapping.Reader.getOffset() == EndOffset);
158 9132 : return Error::success();
159 18264 : }
160 : MappingInfo Mapping;
161 : };
162 9132 :
163 9132 : } // end namespace codeview
164 : } // end namespace llvm
165 18264 :
166 : #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
|