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 class StealTypeServerVisitor : public TypeVisitorCallbacks {
50 explicit StealTypeServerVisitor(TypeServer2Record &TR) : TR(TR) {}
52 Error visitKnownRecord(CVType &CVR, TypeServer2Record &Record) override {
54 return Error::success();
58 TypeServer2Record &TR;
61 TypeServer2Record R(TypeRecordKind::TypeServer2);
62 StealTypeServerVisitor Thief(R);
63 if (auto EC = visitTypeRecord(Record, Thief))
69 static Error visitMemberRecord(CVMemberRecord &Record,
70 TypeVisitorCallbacks &Callbacks) {
71 if (auto EC = Callbacks.visitMemberBegin(Record))
74 switch (Record.Kind) {
76 if (auto EC = Callbacks.visitUnknownMember(Record))
79 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
81 if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
85 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
86 MEMBER_RECORD(EnumVal, EnumVal, AliasName)
87 #define TYPE_RECORD(EnumName, EnumVal, Name)
88 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
89 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
92 if (auto EC = Callbacks.visitMemberEnd(Record))
95 return Error::success();
100 class CVTypeVisitor {
102 explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
104 void addTypeServerHandler(TypeServerHandler &Handler);
106 Error visitTypeRecord(CVType &Record, TypeIndex Index);
107 Error visitTypeRecord(CVType &Record);
109 /// Visits the type records in Data. Sets the error flag on parse failures.
110 Error visitTypeStream(const CVTypeArray &Types);
111 Error visitTypeStream(CVTypeRange Types);
112 Error visitTypeStream(TypeCollection &Types);
114 Error visitMemberRecord(CVMemberRecord Record);
115 Error visitFieldListMemberStream(BinaryStreamReader &Stream);
118 Expected<bool> handleTypeServer(CVType &Record);
119 Error finishVisitation(CVType &Record);
121 /// The interface to the class that gets notified of each visitation.
122 TypeVisitorCallbacks &Callbacks;
124 TinyPtrVector<TypeServerHandler *> Handlers;
127 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
128 : Callbacks(Callbacks) {}
130 void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
131 Handlers.push_back(&Handler);
134 Expected<bool> CVTypeVisitor::handleTypeServer(CVType &Record) {
135 if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
136 auto TS = deserializeTypeServerRecord(Record);
138 return TS.takeError();
140 for (auto Handler : Handlers) {
141 auto ExpectedResult = Handler->handle(*TS, Callbacks);
142 // If there was an error, return the error.
144 return ExpectedResult.takeError();
146 // If the handler processed the record, return success.
150 // Otherwise keep searching for a handler, eventually falling out and
151 // using the default record handler.
157 Error CVTypeVisitor::finishVisitation(CVType &Record) {
158 switch (Record.Type) {
160 if (auto EC = Callbacks.visitUnknownType(Record))
163 #define TYPE_RECORD(EnumName, EnumVal, Name) \
165 if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
169 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
170 TYPE_RECORD(EnumVal, EnumVal, AliasName)
171 #define MEMBER_RECORD(EnumName, EnumVal, Name)
172 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
173 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
176 if (auto EC = Callbacks.visitTypeEnd(Record))
179 return Error::success();
182 Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
183 auto ExpectedResult = handleTypeServer(Record);
185 return ExpectedResult.takeError();
187 return Error::success();
189 if (auto EC = Callbacks.visitTypeBegin(Record, Index))
192 return finishVisitation(Record);
195 Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
196 auto ExpectedResult = handleTypeServer(Record);
198 return ExpectedResult.takeError();
200 return Error::success();
202 if (auto EC = Callbacks.visitTypeBegin(Record))
205 return finishVisitation(Record);
208 Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
209 return ::visitMemberRecord(Record, Callbacks);
212 /// Visits the type records in Data. Sets the error flag on parse failures.
213 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
214 for (auto I : Types) {
215 if (auto EC = visitTypeRecord(I))
218 return Error::success();
221 Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
222 for (auto I : Types) {
223 if (auto EC = visitTypeRecord(I))
226 return Error::success();
229 Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
230 Optional<TypeIndex> I = Types.getFirst();
232 CVType Type = Types.getType(*I);
233 if (auto EC = visitTypeRecord(Type, *I))
235 I = Types.getNext(*I);
237 return Error::success();
240 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
242 while (!Reader.empty()) {
243 if (auto EC = Reader.readEnum(Leaf))
246 CVMemberRecord Record;
248 if (auto EC = ::visitMemberRecord(Record, Callbacks))
252 return Error::success();
255 struct FieldListVisitHelper {
256 FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
257 VisitorDataSource Source)
258 : Stream(Data, llvm::support::little), Reader(Stream),
259 Deserializer(Reader),
260 Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
261 if (Source == VDS_BytesPresent) {
262 Pipeline.addCallbackToPipeline(Deserializer);
263 Pipeline.addCallbackToPipeline(Callbacks);
267 BinaryByteStream Stream;
268 BinaryStreamReader Reader;
269 FieldListDeserializer Deserializer;
270 TypeVisitorCallbackPipeline Pipeline;
271 CVTypeVisitor Visitor;
275 VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
276 : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
277 if (Source == VDS_BytesPresent) {
278 Pipeline.addCallbackToPipeline(Deserializer);
279 Pipeline.addCallbackToPipeline(Callbacks);
283 TypeDeserializer Deserializer;
284 TypeVisitorCallbackPipeline Pipeline;
285 CVTypeVisitor Visitor;
289 Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
290 TypeVisitorCallbacks &Callbacks,
291 VisitorDataSource Source,
292 TypeServerHandler *TS) {
293 VisitHelper V(Callbacks, Source);
295 V.Visitor.addTypeServerHandler(*TS);
296 return V.Visitor.visitTypeRecord(Record, Index);
299 Error llvm::codeview::visitTypeRecord(CVType &Record,
300 TypeVisitorCallbacks &Callbacks,
301 VisitorDataSource Source,
302 TypeServerHandler *TS) {
303 VisitHelper V(Callbacks, Source);
305 V.Visitor.addTypeServerHandler(*TS);
306 return V.Visitor.visitTypeRecord(Record);
309 Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
310 TypeVisitorCallbacks &Callbacks,
311 TypeServerHandler *TS) {
312 VisitHelper V(Callbacks, VDS_BytesPresent);
314 V.Visitor.addTypeServerHandler(*TS);
315 return V.Visitor.visitTypeStream(Types);
318 Error llvm::codeview::visitTypeStream(CVTypeRange Types,
319 TypeVisitorCallbacks &Callbacks,
320 TypeServerHandler *TS) {
321 VisitHelper V(Callbacks, VDS_BytesPresent);
323 V.Visitor.addTypeServerHandler(*TS);
324 return V.Visitor.visitTypeStream(Types);
327 Error llvm::codeview::visitTypeStream(TypeCollection &Types,
328 TypeVisitorCallbacks &Callbacks,
329 TypeServerHandler *TS) {
330 // When the internal visitor calls Types.getType(Index) the interface is
331 // required to return a CVType with the bytes filled out. So we can assume
332 // that the bytes will be present when individual records are visited.
333 VisitHelper V(Callbacks, VDS_BytesPresent);
335 V.Visitor.addTypeServerHandler(*TS);
336 return V.Visitor.visitTypeStream(Types);
339 Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
340 TypeVisitorCallbacks &Callbacks,
341 VisitorDataSource Source) {
342 FieldListVisitHelper V(Callbacks, Record.Data, Source);
343 return V.Visitor.visitMemberRecord(Record);
346 Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
347 ArrayRef<uint8_t> Record,
348 TypeVisitorCallbacks &Callbacks) {
352 return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
355 Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
356 TypeVisitorCallbacks &Callbacks) {
357 FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
358 return V.Visitor.visitFieldListMemberStream(V.Reader);