LLVM  8.0.1
CVTypeVisitor.cpp
Go to the documentation of this file.
1 //===- CVTypeVisitor.cpp ----------------------------------------*- 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 
11 
19 
20 using namespace llvm;
21 using namespace llvm::codeview;
22 
23 
24 template <typename T>
26  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
27  T KnownRecord(RK);
28  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
29  return EC;
30  return Error::success();
31 }
32 
33 template <typename T>
35  TypeVisitorCallbacks &Callbacks) {
36  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
37  T KnownRecord(RK);
38  if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
39  return EC;
40  return Error::success();
41 }
42 
44  TypeVisitorCallbacks &Callbacks) {
45  if (auto EC = Callbacks.visitMemberBegin(Record))
46  return EC;
47 
48  switch (Record.Kind) {
49  default:
50  if (auto EC = Callbacks.visitUnknownMember(Record))
51  return EC;
52  break;
53 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
54  case EnumName: { \
55  if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
56  return EC; \
57  break; \
58  }
59 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
60  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
61 #define TYPE_RECORD(EnumName, EnumVal, Name)
62 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
63 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
64  }
65 
66  if (auto EC = Callbacks.visitMemberEnd(Record))
67  return EC;
68 
69  return Error::success();
70 }
71 
72 namespace {
73 
74 class CVTypeVisitor {
75 public:
76  explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
77 
79  Error visitTypeRecord(CVType &Record);
80 
81  /// Visits the type records in Data. Sets the error flag on parse failures.
82  Error visitTypeStream(const CVTypeArray &Types);
85 
87  Error visitFieldListMemberStream(BinaryStreamReader &Stream);
88 
89 private:
90  Error finishVisitation(CVType &Record);
91 
92  /// The interface to the class that gets notified of each visitation.
93  TypeVisitorCallbacks &Callbacks;
94 };
95 
96 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
97  : Callbacks(Callbacks) {}
98 
100  switch (Record.Type) {
101  default:
102  if (auto EC = Callbacks.visitUnknownType(Record))
103  return EC;
104  break;
105 #define TYPE_RECORD(EnumName, EnumVal, Name) \
106  case EnumName: { \
107  if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
108  return EC; \
109  break; \
110  }
111 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
112  TYPE_RECORD(EnumVal, EnumVal, AliasName)
113 #define MEMBER_RECORD(EnumName, EnumVal, Name)
114 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
115 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
116  }
117 
118  if (auto EC = Callbacks.visitTypeEnd(Record))
119  return EC;
120 
121  return Error::success();
122 }
123 
125  if (auto EC = Callbacks.visitTypeBegin(Record, Index))
126  return EC;
127 
128  return finishVisitation(Record);
129 }
130 
132  if (auto EC = Callbacks.visitTypeBegin(Record))
133  return EC;
134 
135  return finishVisitation(Record);
136 }
137 
139  return ::visitMemberRecord(Record, Callbacks);
140 }
141 
142 /// Visits the type records in Data. Sets the error flag on parse failures.
144  for (auto I : Types) {
145  if (auto EC = visitTypeRecord(I))
146  return EC;
147  }
148  return Error::success();
149 }
150 
152  for (auto I : Types) {
153  if (auto EC = visitTypeRecord(I))
154  return EC;
155  }
156  return Error::success();
157 }
158 
160  Optional<TypeIndex> I = Types.getFirst();
161  while (I) {
162  CVType Type = Types.getType(*I);
163  if (auto EC = visitTypeRecord(Type, *I))
164  return EC;
165  I = Types.getNext(*I);
166  }
167  return Error::success();
168 }
169 
170 Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
171  TypeLeafKind Leaf;
172  while (!Reader.empty()) {
173  if (auto EC = Reader.readEnum(Leaf))
174  return EC;
175 
176  CVMemberRecord Record;
177  Record.Kind = Leaf;
178  if (auto EC = ::visitMemberRecord(Record, Callbacks))
179  return EC;
180  }
181 
182  return Error::success();
183 }
184 
185 struct FieldListVisitHelper {
186  FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
188  : Stream(Data, llvm::support::little), Reader(Stream),
189  Deserializer(Reader),
190  Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
191  if (Source == VDS_BytesPresent) {
192  Pipeline.addCallbackToPipeline(Deserializer);
193  Pipeline.addCallbackToPipeline(Callbacks);
194  }
195  }
196 
197  BinaryByteStream Stream;
198  BinaryStreamReader Reader;
199  FieldListDeserializer Deserializer;
201  CVTypeVisitor Visitor;
202 };
203 
204 struct VisitHelper {
205  VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
206  : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
207  if (Source == VDS_BytesPresent) {
208  Pipeline.addCallbackToPipeline(Deserializer);
209  Pipeline.addCallbackToPipeline(Callbacks);
210  }
211  }
212 
213  TypeDeserializer Deserializer;
215  CVTypeVisitor Visitor;
216 };
217 }
218 
220  TypeVisitorCallbacks &Callbacks,
222  VisitHelper V(Callbacks, Source);
223  return V.Visitor.visitTypeRecord(Record, Index);
224 }
225 
227  TypeVisitorCallbacks &Callbacks,
229  VisitHelper V(Callbacks, Source);
230  return V.Visitor.visitTypeRecord(Record);
231 }
232 
234  TypeVisitorCallbacks &Callbacks,
236  VisitHelper V(Callbacks, Source);
237  return V.Visitor.visitTypeStream(Types);
238 }
239 
241  TypeVisitorCallbacks &Callbacks) {
242  VisitHelper V(Callbacks, VDS_BytesPresent);
243  return V.Visitor.visitTypeStream(Types);
244 }
245 
247  TypeVisitorCallbacks &Callbacks) {
248  // When the internal visitor calls Types.getType(Index) the interface is
249  // required to return a CVType with the bytes filled out. So we can assume
250  // that the bytes will be present when individual records are visited.
251  VisitHelper V(Callbacks, VDS_BytesPresent);
252  return V.Visitor.visitTypeStream(Types);
253 }
254 
256  TypeVisitorCallbacks &Callbacks,
258  FieldListVisitHelper V(Callbacks, Record.Data, Source);
259  return V.Visitor.visitMemberRecord(Record);
260 }
261 
264  TypeVisitorCallbacks &Callbacks) {
265  CVMemberRecord R;
266  R.Data = Record;
267  R.Kind = Kind;
268  return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
269 }
270 
272  TypeVisitorCallbacks &Callbacks) {
273  FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
274  return V.Visitor.visitFieldListMemberStream(V.Reader);
275 }
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
virtual Optional< TypeIndex > getNext(TypeIndex Prev)=0
This class represents lattice values for constants.
Definition: AllocatorList.h:24
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
ArrayRef< uint8_t > Data
Definition: TypeRecord.h:41
virtual CVType getType(TypeIndex Index)=0
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
virtual Optional< TypeIndex > getFirst()=0
virtual Error visitUnknownMember(CVMemberRecord &Record)
virtual Error visitUnknownType(CVType &Record)
Action to take on unknown types. By default, they are ignored.
A 32-bit type reference.
Definition: TypeIndex.h:96
virtual Error visitTypeEnd(CVType &Record)
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition: CodeView.h:27
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
static Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
virtual Error visitMemberBegin(CVMemberRecord &Record)
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
virtual Error visitTypeBegin(CVType &Record)
Paired begin/end actions for all types.
A range adaptor for a pair of iterators.
#define I(x, y, z)
Definition: MD5.cpp:58
static Error finishVisitation(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks)
const unsigned Kind
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
Provides read only access to a subclass of BinaryStream.
Error readEnum(T &Dest)
Similar to readInteger.
virtual Error visitMemberEnd(CVMemberRecord &Record)