• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
MappingInfoMappingInfo31     explicit MappingInfo(ArrayRef<uint8_t> RecordData)
32         : Stream(RecordData, llvm::support::little), Reader(Stream),
33           Mapping(Reader) {}
34 
35     BinaryByteStream Stream;
36     BinaryStreamReader Reader;
37     TypeRecordMapping Mapping;
38   };
39 
40 public:
41   TypeDeserializer() = default;
42 
deserializeAs(CVType & CVT,T & Record)43   template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
44     Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
45     MappingInfo I(CVT.content());
46     if (auto EC = I.Mapping.visitTypeBegin(CVT))
47       return EC;
48     if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
49       return EC;
50     if (auto EC = I.Mapping.visitTypeEnd(CVT))
51       return EC;
52     return Error::success();
53   }
54 
55   template <typename T>
deserializeAs(ArrayRef<uint8_t> Data)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 
visitTypeBegin(CVType & Record)68   Error visitTypeBegin(CVType &Record) override {
69     assert(!Mapping && "Already in a type mapping!");
70     Mapping = llvm::make_unique<MappingInfo>(Record.content());
71     return Mapping->Mapping.visitTypeBegin(Record);
72   }
73 
visitTypeBegin(CVType & Record,TypeIndex Index)74   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
75     return visitTypeBegin(Record);
76   }
77 
visitTypeEnd(CVType & Record)78   Error visitTypeEnd(CVType &Record) override {
79     assert(Mapping && "Not in a type mapping!");
80     auto EC = Mapping->Mapping.visitTypeEnd(Record);
81     Mapping.reset();
82     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>
visitKnownRecordImpl(CVType & CVR,RecordType & Record)96   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
97     return Mapping->Mapping.visitKnownRecord(CVR, Record);
98   }
99 
100   std::unique_ptr<MappingInfo> Mapping;
101 };
102 
103 class FieldListDeserializer : public TypeVisitorCallbacks {
104   struct MappingInfo {
MappingInfoMappingInfo105     explicit MappingInfo(BinaryStreamReader &R)
106         : Reader(R), Mapping(Reader), StartOffset(0) {}
107 
108     BinaryStreamReader &Reader;
109     TypeRecordMapping Mapping;
110     uint32_t StartOffset;
111   };
112 
113 public:
FieldListDeserializer(BinaryStreamReader & Reader)114   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
115     CVType FieldList;
116     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
117     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
118   }
119 
~FieldListDeserializer()120   ~FieldListDeserializer() override {
121     CVType FieldList;
122     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
123     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
124   }
125 
visitMemberBegin(CVMemberRecord & Record)126   Error visitMemberBegin(CVMemberRecord &Record) override {
127     Mapping.StartOffset = Mapping.Reader.getOffset();
128     return Mapping.Mapping.visitMemberBegin(Record);
129   }
130 
visitMemberEnd(CVMemberRecord & Record)131   Error visitMemberEnd(CVMemberRecord &Record) override {
132     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
133       return EC;
134     return Error::success();
135   }
136 
137 #define TYPE_RECORD(EnumName, EnumVal, Name)
138 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
139   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
140     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
141   }
142 #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>
visitKnownMemberImpl(CVMemberRecord & CVR,RecordType & Record)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     return Error::success();
159   }
160   MappingInfo Mapping;
161 };
162 
163 } // end namespace codeview
164 } // end namespace llvm
165 
166 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
167