1 //===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
12 #include "llvm/ADT/TinyPtrVector.h"
13 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
14 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
15 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
16 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
19 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
20 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
21 #include "llvm/Support/BinaryByteStream.h"
22 #include "llvm/Support/BinaryStreamReader.h"
25 using namespace llvm::codeview;
29 static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
30 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
32 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
34 return Error::success();
38 static Error visitKnownMember(CVMemberRecord &Record,
39 TypeVisitorCallbacks &Callbacks) {
40 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
42 if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
44 return Error::success();
47 static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
48 TypeServer2Record R(TypeRecordKind::TypeServer2);
49 if (auto EC = TypeDeserializer::deserializeAs(Record, R))
54 static Error visitMemberRecord(CVMemberRecord &Record,
55 TypeVisitorCallbacks &Callbacks) {
56 if (auto EC = Callbacks.visitMemberBegin(Record))
59 switch (Record.Kind) {
61 if (auto EC = Callbacks.visitUnknownMember(Record))
64 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
66 if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
70 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
71 MEMBER_RECORD(EnumVal, EnumVal, AliasName)
72 #define TYPE_RECORD(EnumName, EnumVal, Name)
73 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
74 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
77 if (auto EC = Callbacks.visitMemberEnd(Record))
80 return Error::success();
87 explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
89 void addTypeServerHandler(TypeServerHandler &Handler);
91 Error visitTypeRecord(CVType &Record, TypeIndex Index);
92 Error visitTypeRecord(CVType &Record);
94 /// Visits the type records in Data. Sets the error flag on parse failures.
95 Error visitTypeStream(const CVTypeArray &Types);
96 Error visitTypeStream(CVTypeRange Types);
97 Error visitTypeStream(TypeCollection &Types);
99 Error visitMemberRecord(CVMemberRecord Record);
100 Error visitFieldListMemberStream(BinaryStreamReader &Stream);
103 Expected<bool> handleTypeServer(CVType &Record);
104 Error finishVisitation(CVType &Record);
106 /// The interface to the class that gets notified of each visitation.
107 TypeVisitorCallbacks &Callbacks;
109 TinyPtrVector<TypeServerHandler *> Handlers;
112 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
113 : Callbacks(Callbacks) {}
115 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
116 Handlers.push_back(&Handler);
119 Expected<bool> CVTypeVisitor::handleTypeServer(CVType &Record) {
120 if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
121 auto TS = deserializeTypeServerRecord(Record);
123 return TS.takeError();
125 for (auto Handler : Handlers) {
126 auto ExpectedResult = Handler->handle(*TS, Callbacks);
127 // If there was an error, return the error.
129 return ExpectedResult.takeError();
131 // If the handler processed the record, return success.
135 // Otherwise keep searching for a handler, eventually falling out and
136 // using the default record handler.
142 Error CVTypeVisitor::finishVisitation(CVType &Record) {
143 switch (Record.Type) {
145 if (auto EC = Callbacks.visitUnknownType(Record))
148 #define TYPE_RECORD(EnumName, EnumVal, Name) \
150 if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
154 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
155 TYPE_RECORD(EnumVal, EnumVal, AliasName)
156 #define MEMBER_RECORD(EnumName, EnumVal, Name)
157 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
158 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
161 if (auto EC = Callbacks.visitTypeEnd(Record))
164 return Error::success();
167 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
168 auto ExpectedResult = handleTypeServer(Record);
170 return ExpectedResult.takeError();
172 return Error::success();
174 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
177 return finishVisitation(Record);
180 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
181 auto ExpectedResult = handleTypeServer(Record);
183 return ExpectedResult.takeError();
185 return Error::success();
187 if (auto EC = Callbacks.visitTypeBegin(Record))
190 return finishVisitation(Record);
193 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
194 return ::visitMemberRecord(Record, Callbacks);
197 /// Visits the type records in Data. Sets the error flag on parse failures.
198 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
199 for (auto I : Types) {
200 if (auto EC = visitTypeRecord(I))
203 return Error::success();
206 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
207 for (auto I : Types) {
208 if (auto EC = visitTypeRecord(I))
211 return Error::success();
214 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
215 Optional<TypeIndex> I = Types.getFirst();
217 CVType Type = Types.getType(*I);
218 if (auto EC = visitTypeRecord(Type, *I))
220 I = Types.getNext(*I);
222 return Error::success();
225 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
227 while (!Reader.empty()) {
228 if (auto EC = Reader.readEnum(Leaf))
231 CVMemberRecord Record;
233 if (auto EC = ::visitMemberRecord(Record, Callbacks))
237 return Error::success();
240 struct FieldListVisitHelper {
241 FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
242 VisitorDataSource Source)
243 : Stream(Data, llvm::support::little), Reader(Stream),
244 Deserializer(Reader),
245 Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
246 if (Source == VDS_BytesPresent) {
247 Pipeline.addCallbackToPipeline(Deserializer);
248 Pipeline.addCallbackToPipeline(Callbacks);
252 BinaryByteStream Stream;
253 BinaryStreamReader Reader;
254 FieldListDeserializer Deserializer;
255 TypeVisitorCallbackPipeline Pipeline;
256 CVTypeVisitor Visitor;
260 VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
261 : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
262 if (Source == VDS_BytesPresent) {
263 Pipeline.addCallbackToPipeline(Deserializer);
264 Pipeline.addCallbackToPipeline(Callbacks);
268 TypeDeserializer Deserializer;
269 TypeVisitorCallbackPipeline Pipeline;
270 CVTypeVisitor Visitor;
274 Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
275 TypeVisitorCallbacks &Callbacks,
276 VisitorDataSource Source,
277 TypeServerHandler *TS) {
278 VisitHelper V(Callbacks, Source);
280 V.Visitor.addTypeServerHandler(*TS);
281 return V.Visitor.visitTypeRecord(Record, Index);
284 Error llvm::codeview::visitTypeRecord(CVType &Record,
285 TypeVisitorCallbacks &Callbacks,
286 VisitorDataSource Source,
287 TypeServerHandler *TS) {
288 VisitHelper V(Callbacks, Source);
290 V.Visitor.addTypeServerHandler(*TS);
291 return V.Visitor.visitTypeRecord(Record);
294 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
295 TypeVisitorCallbacks &Callbacks,
296 VisitorDataSource Source,
297 TypeServerHandler *TS) {
298 VisitHelper V(Callbacks, Source);
300 V.Visitor.addTypeServerHandler(*TS);
301 return V.Visitor.visitTypeStream(Types);
304 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
305 TypeVisitorCallbacks &Callbacks,
306 TypeServerHandler *TS) {
307 VisitHelper V(Callbacks, VDS_BytesPresent);
309 V.Visitor.addTypeServerHandler(*TS);
310 return V.Visitor.visitTypeStream(Types);
313 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
314 TypeVisitorCallbacks &Callbacks,
315 TypeServerHandler *TS) {
316 // When the internal visitor calls Types.getType(Index) the interface is
317 // required to return a CVType with the bytes filled out. So we can assume
318 // that the bytes will be present when individual records are visited.
319 VisitHelper V(Callbacks, VDS_BytesPresent);
321 V.Visitor.addTypeServerHandler(*TS);
322 return V.Visitor.visitTypeStream(Types);
325 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
326 TypeVisitorCallbacks &Callbacks,
327 VisitorDataSource Source) {
328 FieldListVisitHelper V(Callbacks, Record.Data, Source);
329 return V.Visitor.visitMemberRecord(Record);
332 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
333 ArrayRef<uint8_t> Record,
334 TypeVisitorCallbacks &Callbacks) {
338 return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
341 Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
342 TypeVisitorCallbacks &Callbacks) {
343 FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
344 return V.Visitor.visitFieldListMemberStream(V.Reader);