LLVM  4.0.0
TypeRecordMapping.cpp
Go to the documentation of this file.
1 //===- TypeRecordMapping.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 
12 using namespace llvm;
13 using namespace llvm::codeview;
14 
15 #define error(X) \
16  if (auto EC = X) \
17  return EC;
18 
19 namespace {
20 struct MapOneMethodRecord {
21  explicit MapOneMethodRecord(bool IsFromOverloadList)
22  : IsFromOverloadList(IsFromOverloadList) {}
23 
24  Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
25  error(IO.mapInteger(Method.Attrs.Attrs));
26  if (IsFromOverloadList) {
27  uint16_t Padding = 0;
28  error(IO.mapInteger(Padding));
29  }
30  error(IO.mapInteger(Method.Type));
31  if (Method.isIntroducingVirtual()) {
32  error(IO.mapInteger(Method.VFTableOffset));
33  } else if (!IO.isWriting())
34  Method.VFTableOffset = -1;
35 
36  if (!IsFromOverloadList)
37  error(IO.mapStringZ(Method.Name));
38 
39  return Error::success();
40  }
41 
42 private:
43  bool IsFromOverloadList;
44 };
45 }
46 
48  StringRef &UniqueName, bool HasUniqueName) {
49  if (IO.isWriting()) {
50  // Try to be smart about what we write here. We can't write anything too
51  // large, so if we're going to go over the limit, truncate both the name
52  // and unique name by the same amount.
53  size_t BytesLeft = IO.maxFieldLength();
54  if (HasUniqueName) {
55  size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
56  StringRef N = Name;
57  StringRef U = UniqueName;
58  if (BytesNeeded > BytesLeft) {
59  size_t BytesToDrop = (BytesNeeded - BytesLeft);
60  size_t DropN = std::min(N.size(), BytesToDrop / 2);
61  size_t DropU = std::min(U.size(), BytesToDrop - DropN);
62 
63  N = N.drop_back(DropN);
64  U = U.drop_back(DropU);
65  }
66 
67  error(IO.mapStringZ(N));
68  error(IO.mapStringZ(U));
69  } else {
70  size_t BytesNeeded = Name.size() + 1;
71  StringRef N = Name;
72  if (BytesNeeded > BytesLeft) {
73  size_t BytesToDrop = std::min(N.size(), BytesToDrop);
74  N = N.drop_back(BytesToDrop);
75  }
76  error(IO.mapStringZ(N));
77  }
78  } else {
79  error(IO.mapStringZ(Name));
80  if (HasUniqueName)
81  error(IO.mapStringZ(UniqueName));
82  }
83 
84  return Error::success();
85 }
86 
88  assert(!TypeKind.hasValue() && "Already in a type mapping!");
89  assert(!MemberKind.hasValue() && "Already in a member mapping!");
90 
91  // FieldList and MethodList records can be any length because they can be
92  // split with continuation records. All other record types cannot be
93  // longer than the maximum record length.
94  Optional<uint32_t> MaxLen;
95  if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
96  CVR.Type != TypeLeafKind::LF_METHODLIST)
97  MaxLen = MaxRecordLength - sizeof(RecordPrefix);
98  error(IO.beginRecord(MaxLen));
99  TypeKind = CVR.Type;
100  return Error::success();
101 }
102 
104  assert(TypeKind.hasValue() && "Not in a type mapping!");
105  assert(!MemberKind.hasValue() && "Still in a member mapping!");
106 
107  error(IO.endRecord());
108 
109  TypeKind.reset();
110  return Error::success();
111 }
112 
114  assert(TypeKind.hasValue() && "Not in a type mapping!");
115  assert(!MemberKind.hasValue() && "Already in a member mapping!");
116 
117  // The largest possible subrecord is one in which there is a record prefix,
118  // followed by the subrecord, followed by a continuation, and that entire
119  // sequence spaws `MaxRecordLength` bytes. So the record's length is
120  // calculated as follows.
121  constexpr uint32_t ContinuationLength = 8;
123  ContinuationLength));
124 
125  MemberKind = Record.Kind;
126  return Error::success();
127 }
128 
130  assert(TypeKind.hasValue() && "Not in a type mapping!");
131  assert(MemberKind.hasValue() && "Not in a member mapping!");
132 
133  if (!IO.isWriting()) {
134  if (auto EC = IO.skipPadding())
135  return EC;
136  }
137 
138  MemberKind.reset();
139  error(IO.endRecord());
140  return Error::success();
141 }
142 
144  error(IO.mapInteger(Record.ModifiedType));
145  error(IO.mapEnum(Record.Modifiers));
146 
147  return Error::success();
148 }
149 
151  ProcedureRecord &Record) {
152  error(IO.mapInteger(Record.ReturnType));
153  error(IO.mapEnum(Record.CallConv));
154  error(IO.mapEnum(Record.Options));
155  error(IO.mapInteger(Record.ParameterCount));
156  error(IO.mapInteger(Record.ArgumentList));
157 
158  return Error::success();
159 }
160 
162  MemberFunctionRecord &Record) {
163  error(IO.mapInteger(Record.ReturnType));
164  error(IO.mapInteger(Record.ClassType));
165  error(IO.mapInteger(Record.ThisType));
166  error(IO.mapEnum(Record.CallConv));
167  error(IO.mapEnum(Record.Options));
168  error(IO.mapInteger(Record.ParameterCount));
169  error(IO.mapInteger(Record.ArgumentList));
171 
172  return Error::success();
173 }
174 
177  Record.StringIndices,
178  [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
179 
180  return Error::success();
181 }
182 
184  error(IO.mapInteger(Record.ReferentType));
185  error(IO.mapInteger(Record.Attrs));
186 
187  if (Record.isPointerToMember()) {
188  if (!IO.isWriting())
189  Record.MemberInfo.emplace();
190 
191  MemberPointerInfo &M = *Record.MemberInfo;
192  error(IO.mapInteger(M.ContainingType));
193  error(IO.mapEnum(M.Representation));
194  }
195 
196  return Error::success();
197 }
198 
200  error(IO.mapInteger(Record.ElementType));
201  error(IO.mapInteger(Record.IndexType));
202  error(IO.mapEncodedInteger(Record.Size));
203  error(IO.mapStringZ(Record.Name));
204 
205  return Error::success();
206 }
207 
209  assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
210  (CVR.Type == TypeLeafKind::LF_CLASS) ||
211  (CVR.Type == TypeLeafKind::LF_INTERFACE));
212 
213  error(IO.mapInteger(Record.MemberCount));
214  error(IO.mapEnum(Record.Options));
215  error(IO.mapInteger(Record.FieldList));
216  error(IO.mapInteger(Record.DerivationList));
217  error(IO.mapInteger(Record.VTableShape));
218  error(IO.mapEncodedInteger(Record.Size));
219  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
220  Record.hasUniqueName()));
221 
222  return Error::success();
223 }
224 
226  error(IO.mapInteger(Record.MemberCount));
227  error(IO.mapEnum(Record.Options));
228  error(IO.mapInteger(Record.FieldList));
229  error(IO.mapEncodedInteger(Record.Size));
230  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
231  Record.hasUniqueName()));
232 
233  return Error::success();
234 }
235 
237  error(IO.mapInteger(Record.MemberCount));
238  error(IO.mapEnum(Record.Options));
239  error(IO.mapInteger(Record.UnderlyingType));
240  error(IO.mapInteger(Record.FieldList));
241  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
242  Record.hasUniqueName()));
243 
244  return Error::success();
245 }
246 
248  error(IO.mapInteger(Record.Type));
249  error(IO.mapInteger(Record.BitSize));
250  error(IO.mapInteger(Record.BitOffset));
251 
252  return Error::success();
253 }
254 
256  VFTableShapeRecord &Record) {
257  uint16_t Size;
258  if (IO.isWriting()) {
259  ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
260  Size = Slots.size();
261  error(IO.mapInteger(Size));
262 
263  for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
264  uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
265  if ((SlotIndex + 1) < Slots.size()) {
266  Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
267  }
268  error(IO.mapInteger(Byte));
269  }
270  } else {
271  error(IO.mapInteger(Size));
272  for (uint16_t I = 0; I < Size; I += 2) {
273  uint8_t Byte;
274  error(IO.mapInteger(Byte));
275  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
276  if ((I + 1) < Size)
277  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
278  }
279  }
280 
281  return Error::success();
282 }
283 
285  error(IO.mapInteger(Record.CompleteClass));
286  error(IO.mapInteger(Record.OverriddenVFTable));
287  error(IO.mapInteger(Record.VFPtrOffset));
288  uint32_t NamesLen = 0;
289  if (IO.isWriting()) {
290  for (auto Name : Record.MethodNames)
291  NamesLen += Name.size() + 1;
292  }
293  error(IO.mapInteger(NamesLen));
294  error(IO.mapVectorTail(
295  Record.MethodNames,
296  [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
297 
298  return Error::success();
299 }
300 
302  error(IO.mapInteger(Record.Id));
303  error(IO.mapStringZ(Record.String));
304 
305  return Error::success();
306 }
307 
309  UdtSourceLineRecord &Record) {
310  error(IO.mapInteger(Record.UDT));
311  error(IO.mapInteger(Record.SourceFile));
312  error(IO.mapInteger(Record.LineNumber));
313 
314  return Error::success();
315 }
316 
318  UdtModSourceLineRecord &Record) {
319  error(IO.mapInteger(Record.UDT));
320  error(IO.mapInteger(Record.SourceFile));
321  error(IO.mapInteger(Record.LineNumber));
322  error(IO.mapInteger(Record.Module));
323 
324  return Error::success();
325 }
326 
328  error(IO.mapInteger(Record.ParentScope));
329  error(IO.mapInteger(Record.FunctionType));
330  error(IO.mapStringZ(Record.Name));
331 
332  return Error::success();
333 }
334 
336  MemberFuncIdRecord &Record) {
337  error(IO.mapInteger(Record.ClassType));
338  error(IO.mapInteger(Record.FunctionType));
339  error(IO.mapStringZ(Record.Name));
340 
341  return Error::success();
342 }
343 
345  BuildInfoRecord &Record) {
346  error(IO.mapVectorN<uint16_t>(
347  Record.ArgIndices,
348  [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
349 
350  return Error::success();
351 }
352 
354  MethodOverloadListRecord &Record) {
355  // TODO: Split the list into multiple records if it's longer than 64KB, using
356  // a subrecord of TypeRecordKind::Index to chain the records together.
357  error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
358 
359  return Error::success();
360 }
361 
363  FieldListRecord &Record) {
364  error(IO.mapByteVectorTail(Record.Data));
365 
366  return Error::success();
367 }
368 
370  TypeServer2Record &Record) {
371  return Error::success();
372 }
373 
375  BaseClassRecord &Record) {
376  error(IO.mapInteger(Record.Attrs.Attrs));
377  error(IO.mapInteger(Record.Type));
378  error(IO.mapEncodedInteger(Record.Offset));
379 
380  return Error::success();
381 }
382 
384  EnumeratorRecord &Record) {
385  error(IO.mapInteger(Record.Attrs.Attrs));
386 
387  // FIXME: Handle full APInt such as __int128.
388  error(IO.mapEncodedInteger(Record.Value));
389  error(IO.mapStringZ(Record.Name));
390 
391  return Error::success();
392 }
393 
395  DataMemberRecord &Record) {
396  error(IO.mapInteger(Record.Attrs.Attrs));
397  error(IO.mapInteger(Record.Type));
398  error(IO.mapEncodedInteger(Record.FieldOffset));
399  error(IO.mapStringZ(Record.Name));
400 
401  return Error::success();
402 }
403 
405  OverloadedMethodRecord &Record) {
406  error(IO.mapInteger(Record.NumOverloads));
407  error(IO.mapInteger(Record.MethodList));
408  error(IO.mapStringZ(Record.Name));
409 
410  return Error::success();
411 }
412 
414  OneMethodRecord &Record) {
415  MapOneMethodRecord Mapper(false);
416  return Mapper(IO, Record);
417 }
418 
420  NestedTypeRecord &Record) {
421  uint16_t Padding = 0;
422  error(IO.mapInteger(Padding));
423  error(IO.mapInteger(Record.Type));
424  error(IO.mapStringZ(Record.Name));
425 
426  return Error::success();
427 }
428 
430  StaticDataMemberRecord &Record) {
431 
432  error(IO.mapInteger(Record.Attrs.Attrs));
433  error(IO.mapInteger(Record.Type));
434  error(IO.mapStringZ(Record.Name));
435 
436  return Error::success();
437 }
438 
440  VirtualBaseClassRecord &Record) {
441 
442  error(IO.mapInteger(Record.Attrs.Attrs));
443  error(IO.mapInteger(Record.BaseType));
444  error(IO.mapInteger(Record.VBPtrType));
445  error(IO.mapEncodedInteger(Record.VBPtrOffset));
446  error(IO.mapEncodedInteger(Record.VTableIndex));
447 
448  return Error::success();
449 }
450 
452  VFPtrRecord &Record) {
453  uint16_t Padding = 0;
454  error(IO.mapInteger(Padding));
455  error(IO.mapInteger(Record.Type));
456 
457  return Error::success();
458 }
459 
461  ListContinuationRecord &Record) {
462  uint16_t Padding = 0;
463  error(IO.mapInteger(Padding));
464  error(IO.mapInteger(Record.ContinuationIndex));
465 
466  return Error::success();
467 }
Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes)
Error mapVectorN(T &Items, const ElementMapper &Mapper)
bool hasValue() const
Definition: Optional.h:125
Error mapInteger(TypeIndex &TypeInd)
#define error(X)
ArrayRef< uint8_t > Data
Definition: TypeRecord.h:381
std::vector< TypeIndex > StringIndices
Definition: TypeRecord.h:254
Error visitMemberEnd(CVMemberRecord &Record) override
Error beginRecord(Optional< uint32_t > MaxLength)
bool isPointerToMember() const
Definition: TypeRecord.h:319
Error visitTypeEnd(CVType &Record) override
bool isIntroducingVirtual() const
Definition: TypeRecord.h:739
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
A 32-bit type reference.
Definition: TypeIndex.h:89
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:141
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
bool hasUniqueName() const
Definition: TypeRecord.h:426
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Optional< MemberPointerInfo > MemberInfo
Definition: TypeRecord.h:338
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:936
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:766
std::vector< StringRef > MethodNames
Definition: TypeRecord.h:711
static ErrorSuccess success()
Create a success value.
Error mapEncodedInteger(int64_t &Value)
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
CallingConvention CallConv
Definition: TypeRecord.h:175
std::vector< OneMethodRecord > Methods
Definition: TypeRecord.h:762
SmallVector< TypeIndex, 4 > ArgIndices
Definition: TypeRecord.h:680
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
Error mapStringZ(StringRef &Value)
void reset()
Definition: Optional.h:108
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< VFTableSlotKind > Slots
Definition: TypeRecord.h:557
Lightweight error class with error context and mandatory checking.
Error mapVectorTail(T &Items, const ElementMapper &Mapper)
ArrayRef< VFTableSlotKind > getSlots() const
Definition: TypeRecord.h:549
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:643
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:76
Error visitMemberBegin(CVMemberRecord &Record) override
PointerToMemberRepresentation Representation
Definition: TypeRecord.h:119