• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SymbolRecord.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_SYMBOLRECORD_H
11 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
12 
13 #include "llvm/ADT/APSInt.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/DebugInfo/CodeView/CVRecord.h"
16 #include "llvm/DebugInfo/CodeView/CodeView.h"
17 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
18 #include "llvm/DebugInfo/CodeView/StreamArray.h"
19 #include "llvm/DebugInfo/CodeView/StreamInterface.h"
20 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/Error.h"
23 
24 namespace llvm {
25 namespace codeview {
26 
27 using llvm::support::ulittle16_t;
28 using llvm::support::ulittle32_t;
29 using llvm::support::little32_t;
30 
31 class SymbolRecord {
32 protected:
SymbolRecord(SymbolRecordKind Kind)33   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
34 
35 public:
getKind()36   SymbolRecordKind getKind() const { return Kind; }
37 
38 private:
39   SymbolRecordKind Kind;
40 };
41 
42 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
43 // S_LPROC32_DPC_ID
44 class ProcSym : public SymbolRecord {
45 public:
46   struct Hdr {
47     ulittle32_t PtrParent;
48     ulittle32_t PtrEnd;
49     ulittle32_t PtrNext;
50     ulittle32_t CodeSize;
51     ulittle32_t DbgStart;
52     ulittle32_t DbgEnd;
53     TypeIndex FunctionType;
54     ulittle32_t CodeOffset;
55     ulittle16_t Segment;
56     uint8_t Flags; // ProcSymFlags enum
57                    // Name: The null-terminated name follows.
58   };
59 
ProcSym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * H,StringRef Name)60   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
61           StringRef Name)
62       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
63   }
64 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)65   static ErrorOr<ProcSym> deserialize(SymbolRecordKind Kind,
66                                       uint32_t RecordOffset,
67                                       ArrayRef<uint8_t> &Data) {
68     const Hdr *H = nullptr;
69     StringRef Name;
70     CV_DESERIALIZE(Data, H, Name);
71 
72     return ProcSym(Kind, RecordOffset, H, Name);
73   }
74 
getRelocationOffset()75   uint32_t getRelocationOffset() const {
76     return RecordOffset + offsetof(Hdr, CodeOffset);
77   }
78 
79   uint32_t RecordOffset;
80   Hdr Header;
81   StringRef Name;
82 };
83 
84 // S_THUNK32
85 class Thunk32Sym : public SymbolRecord {
86 public:
87   struct Hdr {
88     ulittle32_t Parent;
89     ulittle32_t End;
90     ulittle32_t Next;
91     ulittle32_t Off;
92     ulittle16_t Seg;
93     ulittle16_t Len;
94     uint8_t Ord; // ThunkOrdinal enumeration
95                  // Name: The null-terminated name follows.
96                  // Variant portion of thunk
97   };
98 
Thunk32Sym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * H,StringRef Name,ArrayRef<uint8_t> VariantData)99   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
100              StringRef Name, ArrayRef<uint8_t> VariantData)
101       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
102         VariantData(VariantData) {}
103 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)104   static ErrorOr<Thunk32Sym> deserialize(SymbolRecordKind Kind,
105                                          uint32_t RecordOffset,
106                                          ArrayRef<uint8_t> &Data) {
107     const Hdr *H = nullptr;
108     StringRef Name;
109     ArrayRef<uint8_t> VariantData;
110 
111     CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
112 
113     return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
114   }
115 
116   uint32_t RecordOffset;
117   Hdr Header;
118   StringRef Name;
119   ArrayRef<uint8_t> VariantData;
120 };
121 
122 // S_TRAMPOLINE
123 class TrampolineSym : public SymbolRecord {
124 public:
125   struct Hdr {
126     ulittle16_t Type; // TrampolineType enum
127     ulittle16_t Size;
128     ulittle32_t ThunkOff;
129     ulittle32_t TargetOff;
130     ulittle16_t ThunkSection;
131     ulittle16_t TargetSection;
132   };
133 
TrampolineSym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * H)134   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
135       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
136 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)137   static ErrorOr<TrampolineSym> deserialize(SymbolRecordKind Kind,
138                                             uint32_t RecordOffset,
139                                             ArrayRef<uint8_t> &Data) {
140     const Hdr *H = nullptr;
141 
142     CV_DESERIALIZE(Data, H);
143 
144     return TrampolineSym(Kind, RecordOffset, H);
145   }
146 
147   uint32_t RecordOffset;
148   Hdr Header;
149 };
150 
151 // S_SECTION
152 class SectionSym : public SymbolRecord {
153 public:
154   struct Hdr {
155     ulittle16_t SectionNumber;
156     uint8_t Alignment;
157     uint8_t Reserved; // Must be 0
158     ulittle32_t Rva;
159     ulittle32_t Length;
160     ulittle32_t Characteristics;
161     // Name: The null-terminated name follows.
162   };
163 
SectionSym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * H,StringRef Name)164   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
165              StringRef Name)
166       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
167   }
168 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)169   static ErrorOr<SectionSym> deserialize(SymbolRecordKind Kind,
170                                          uint32_t RecordOffset,
171                                          ArrayRef<uint8_t> &Data) {
172     const Hdr *H = nullptr;
173     StringRef Name;
174 
175     CV_DESERIALIZE(Data, H, Name);
176 
177     return SectionSym(Kind, RecordOffset, H, Name);
178   }
179 
180   uint32_t RecordOffset;
181   Hdr Header;
182   StringRef Name;
183 };
184 
185 // S_COFFGROUP
186 class CoffGroupSym : public SymbolRecord {
187 public:
188   struct Hdr {
189     ulittle32_t Size;
190     ulittle32_t Characteristics;
191     ulittle32_t Offset;
192     ulittle16_t Segment;
193     // Name: The null-terminated name follows.
194   };
195 
CoffGroupSym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * H,StringRef Name)196   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
197                StringRef Name)
198       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
199   }
200 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)201   static ErrorOr<CoffGroupSym> deserialize(SymbolRecordKind Kind,
202                                            uint32_t RecordOffset,
203                                            ArrayRef<uint8_t> &Data) {
204     const Hdr *H = nullptr;
205     StringRef Name;
206 
207     CV_DESERIALIZE(Data, H, Name);
208 
209     return CoffGroupSym(Kind, RecordOffset, H, Name);
210   }
211 
212   uint32_t RecordOffset;
213   Hdr Header;
214   StringRef Name;
215 };
216 
217 class ScopeEndSym : public SymbolRecord {
218 public:
ScopeEndSym(SymbolRecordKind Kind,uint32_t RecordOffset)219   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
220       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
221 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)222   static ErrorOr<ScopeEndSym> deserialize(SymbolRecordKind Kind,
223                                           uint32_t RecordOffset,
224                                           ArrayRef<uint8_t> &Data) {
225     return ScopeEndSym(Kind, RecordOffset);
226   }
227   uint32_t RecordOffset;
228 };
229 
230 class CallerSym : public SymbolRecord {
231 public:
232   struct Hdr {
233     ulittle32_t Count;
234   };
235 
CallerSym(SymbolRecordKind Kind,uint32_t RecordOffset,const Hdr * Header,ArrayRef<TypeIndex> Indices)236   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
237             ArrayRef<TypeIndex> Indices)
238       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
239         Indices(Indices) {}
240 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)241   static ErrorOr<CallerSym> deserialize(SymbolRecordKind Kind,
242                                         uint32_t RecordOffset,
243                                         ArrayRef<uint8_t> &Data) {
244     const Hdr *Header;
245     ArrayRef<TypeIndex> Indices;
246 
247     CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
248 
249     return CallerSym(Kind, RecordOffset, Header, Indices);
250   }
251 
252   uint32_t RecordOffset;
253   Hdr Header;
254   ArrayRef<TypeIndex> Indices;
255 };
256 
257 struct BinaryAnnotationIterator {
258   struct AnnotationData {
259     BinaryAnnotationsOpCode OpCode;
260     StringRef Name;
261     uint32_t U1;
262     uint32_t U2;
263     int32_t S1;
264   };
265 
BinaryAnnotationIteratorBinaryAnnotationIterator266   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
BinaryAnnotationIteratorBinaryAnnotationIterator267   BinaryAnnotationIterator() {}
BinaryAnnotationIteratorBinaryAnnotationIterator268   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
269       : Data(Other.Data) {}
270 
271   bool operator==(BinaryAnnotationIterator Other) const {
272     return Data == Other.Data;
273   }
274 
275   bool operator!=(BinaryAnnotationIterator Other) const {
276     return !(*this == Other);
277   }
278 
279   BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
280     Data = Other.Data;
281     return *this;
282   }
283 
284   BinaryAnnotationIterator &operator++() {
285     if (!ParseCurrentAnnotation()) {
286       *this = BinaryAnnotationIterator();
287       return *this;
288     }
289     Data = Next;
290     Next = ArrayRef<uint8_t>();
291     Current.reset();
292     return *this;
293   }
294 
295   BinaryAnnotationIterator operator++(int) {
296     BinaryAnnotationIterator Orig(*this);
297     ++(*this);
298     return Orig;
299   }
300 
301   const AnnotationData &operator*() {
302     ParseCurrentAnnotation();
303     return Current.getValue();
304   }
305 
306 private:
GetCompressedAnnotationBinaryAnnotationIterator307   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
308     if (Annotations.empty())
309       return -1;
310 
311     uint8_t FirstByte = Annotations.front();
312     Annotations = Annotations.drop_front();
313 
314     if ((FirstByte & 0x80) == 0x00)
315       return FirstByte;
316 
317     if (Annotations.empty())
318       return -1;
319 
320     uint8_t SecondByte = Annotations.front();
321     Annotations = Annotations.drop_front();
322 
323     if ((FirstByte & 0xC0) == 0x80)
324       return ((FirstByte & 0x3F) << 8) | SecondByte;
325 
326     if (Annotations.empty())
327       return -1;
328 
329     uint8_t ThirdByte = Annotations.front();
330     Annotations = Annotations.drop_front();
331 
332     if (Annotations.empty())
333       return -1;
334 
335     uint8_t FourthByte = Annotations.front();
336     Annotations = Annotations.drop_front();
337 
338     if ((FirstByte & 0xE0) == 0xC0)
339       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
340              (ThirdByte << 8) | FourthByte;
341 
342     return -1;
343   };
344 
DecodeSignedOperandBinaryAnnotationIterator345   static int32_t DecodeSignedOperand(uint32_t Operand) {
346     if (Operand & 1)
347       return -(Operand >> 1);
348     return Operand >> 1;
349   };
350 
DecodeSignedOperandBinaryAnnotationIterator351   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
352     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
353   };
354 
ParseCurrentAnnotationBinaryAnnotationIterator355   bool ParseCurrentAnnotation() {
356     if (Current.hasValue())
357       return true;
358 
359     Next = Data;
360     uint32_t Op = GetCompressedAnnotation(Next);
361     AnnotationData Result;
362     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
363     switch (Result.OpCode) {
364     case BinaryAnnotationsOpCode::Invalid:
365       Result.Name = "Invalid";
366       Next = ArrayRef<uint8_t>();
367       break;
368     case BinaryAnnotationsOpCode::CodeOffset:
369       Result.Name = "CodeOffset";
370       Result.U1 = GetCompressedAnnotation(Next);
371       break;
372     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
373       Result.Name = "ChangeCodeOffsetBase";
374       Result.U1 = GetCompressedAnnotation(Next);
375       break;
376     case BinaryAnnotationsOpCode::ChangeCodeOffset:
377       Result.Name = "ChangeCodeOffset";
378       Result.U1 = GetCompressedAnnotation(Next);
379       break;
380     case BinaryAnnotationsOpCode::ChangeCodeLength:
381       Result.Name = "ChangeCodeLength";
382       Result.U1 = GetCompressedAnnotation(Next);
383       break;
384     case BinaryAnnotationsOpCode::ChangeFile:
385       Result.Name = "ChangeFile";
386       Result.U1 = GetCompressedAnnotation(Next);
387       break;
388     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
389       Result.Name = "ChangeLineEndDelta";
390       Result.U1 = GetCompressedAnnotation(Next);
391       break;
392     case BinaryAnnotationsOpCode::ChangeRangeKind:
393       Result.Name = "ChangeRangeKind";
394       Result.U1 = GetCompressedAnnotation(Next);
395       break;
396     case BinaryAnnotationsOpCode::ChangeColumnStart:
397       Result.Name = "ChangeColumnStart";
398       Result.U1 = GetCompressedAnnotation(Next);
399       break;
400     case BinaryAnnotationsOpCode::ChangeColumnEnd:
401       Result.Name = "ChangeColumnEnd";
402       Result.U1 = GetCompressedAnnotation(Next);
403       break;
404     case BinaryAnnotationsOpCode::ChangeLineOffset:
405       Result.Name = "ChangeLineOffset";
406       Result.S1 = DecodeSignedOperand(Next);
407       break;
408     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
409       Result.Name = "ChangeColumnEndDelta";
410       Result.S1 = DecodeSignedOperand(Next);
411       break;
412     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
413       Result.Name = "ChangeCodeOffsetAndLineOffset";
414       uint32_t Annotation = GetCompressedAnnotation(Next);
415       Result.S1 = DecodeSignedOperand(Annotation >> 4);
416       Result.U1 = Annotation & 0xf;
417       break;
418     }
419     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
420       Result.Name = "ChangeCodeLengthAndCodeOffset";
421       Result.U1 = GetCompressedAnnotation(Next);
422       Result.U2 = GetCompressedAnnotation(Next);
423       break;
424     }
425     }
426     Current = Result;
427     return true;
428   }
429 
430   Optional<AnnotationData> Current;
431   ArrayRef<uint8_t> Data;
432   ArrayRef<uint8_t> Next;
433 };
434 
435 // S_INLINESITE
436 class InlineSiteSym : public SymbolRecord {
437 public:
438   struct Hdr {
439     ulittle32_t PtrParent;
440     ulittle32_t PtrEnd;
441     TypeIndex Inlinee;
442     // BinaryAnnotations
443   };
444 
InlineSiteSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<uint8_t> Annotations)445   InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
446                 ArrayRef<uint8_t> Annotations)
447       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
448         RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {}
449 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)450   static ErrorOr<InlineSiteSym> deserialize(SymbolRecordKind Kind,
451                                             uint32_t RecordOffset,
452                                             ArrayRef<uint8_t> &Data) {
453     const Hdr *H = nullptr;
454     ArrayRef<uint8_t> Annotations;
455     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
456 
457     return InlineSiteSym(RecordOffset, H, Annotations);
458   }
459 
annotations()460   llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
461     return llvm::make_range(BinaryAnnotationIterator(Annotations),
462                             BinaryAnnotationIterator());
463   }
464 
465   uint32_t RecordOffset;
466   Hdr Header;
467 
468 private:
469   ArrayRef<uint8_t> Annotations;
470 };
471 
472 // S_PUB32
473 class PublicSym32 : public SymbolRecord {
474 public:
475   struct Hdr {
476     ulittle32_t Index; // Type index, or Metadata token if a managed symbol
477     ulittle32_t Off;
478     ulittle16_t Seg;
479     // Name: The null-terminated name follows.
480   };
481 
PublicSym32(uint32_t RecordOffset,const Hdr * H,StringRef Name)482   PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
483       : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
484         Header(*H), Name(Name) {}
485 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)486   static ErrorOr<PublicSym32> deserialize(SymbolRecordKind Kind,
487                                           uint32_t RecordOffset,
488                                           ArrayRef<uint8_t> &Data) {
489     const Hdr *H = nullptr;
490     StringRef Name;
491     CV_DESERIALIZE(Data, H, Name);
492 
493     return PublicSym32(RecordOffset, H, Name);
494   }
495 
496   uint32_t RecordOffset;
497   Hdr Header;
498   StringRef Name;
499 };
500 
501 // S_REGISTER
502 class RegisterSym : public SymbolRecord {
503 public:
504   struct Hdr {
505     ulittle32_t Index;    // Type index or Metadata token
506     ulittle16_t Register; // RegisterId enumeration
507     // Name: The null-terminated name follows.
508   };
509 
RegisterSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)510   RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
511       : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
512         Header(*H), Name(Name) {}
513 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)514   static ErrorOr<RegisterSym> deserialize(SymbolRecordKind Kind,
515                                           uint32_t RecordOffset,
516                                           ArrayRef<uint8_t> &Data) {
517     const Hdr *H = nullptr;
518     StringRef Name;
519     CV_DESERIALIZE(Data, H, Name);
520 
521     return RegisterSym(RecordOffset, H, Name);
522   }
523 
524   uint32_t RecordOffset;
525   Hdr Header;
526   StringRef Name;
527 };
528 
529 // S_PROCREF, S_LPROCREF
530 class ProcRefSym : public SymbolRecord {
531 public:
532   struct Hdr {
533     ulittle32_t SumName;   // SUC of the name (?)
534     ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols
535     ulittle16_t Mod;       // Module containing the actual symbol
536                            // Name:  The null-terminated name follows.
537   };
538 
ProcRefSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)539   ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
540       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
541         Header(*H), Name(Name) {}
542 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)543   static ErrorOr<ProcRefSym> deserialize(SymbolRecordKind Kind,
544                                          uint32_t RecordOffset,
545                                          ArrayRef<uint8_t> &Data) {
546     const Hdr *H = nullptr;
547     StringRef Name;
548     CV_DESERIALIZE(Data, H, Name);
549 
550     return ProcRefSym(RecordOffset, H, Name);
551   }
552 
553   uint32_t RecordOffset;
554   Hdr Header;
555   StringRef Name;
556 };
557 
558 // S_LOCAL
559 class LocalSym : public SymbolRecord {
560 public:
561   struct Hdr {
562     TypeIndex Type;
563     ulittle16_t Flags; // LocalSymFlags enum
564                        // Name: The null-terminated name follows.
565   };
566 
LocalSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)567   LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
568       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
569         Header(*H), Name(Name) {}
570 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)571   static ErrorOr<LocalSym> deserialize(SymbolRecordKind Kind,
572                                        uint32_t RecordOffset,
573                                        ArrayRef<uint8_t> &Data) {
574     const Hdr *H = nullptr;
575     StringRef Name;
576     CV_DESERIALIZE(Data, H, Name);
577 
578     return LocalSym(RecordOffset, H, Name);
579   }
580 
581   uint32_t RecordOffset;
582   Hdr Header;
583   StringRef Name;
584 };
585 
586 struct LocalVariableAddrRange {
587   ulittle32_t OffsetStart;
588   ulittle16_t ISectStart;
589   ulittle16_t Range;
590 };
591 
592 struct LocalVariableAddrGap {
593   ulittle16_t GapStartOffset;
594   ulittle16_t Range;
595 };
596 
597 enum : uint16_t { MaxDefRange = 0xf000 };
598 
599 // S_DEFRANGE
600 class DefRangeSym : public SymbolRecord {
601 public:
602   struct Hdr {
603     ulittle32_t Program;
604     LocalVariableAddrRange Range;
605     // LocalVariableAddrGap Gaps[];
606   };
607 
DefRangeSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)608   DefRangeSym(uint32_t RecordOffset, const Hdr *H,
609               ArrayRef<LocalVariableAddrGap> Gaps)
610       : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
611         Header(*H), Gaps(Gaps) {}
612 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)613   static ErrorOr<DefRangeSym> deserialize(SymbolRecordKind Kind,
614                                           uint32_t RecordOffset,
615                                           ArrayRef<uint8_t> &Data) {
616     const Hdr *H = nullptr;
617     ArrayRef<LocalVariableAddrGap> Gaps;
618     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
619 
620     return DefRangeSym(RecordOffset, H, Gaps);
621   }
622 
getRelocationOffset()623   uint32_t getRelocationOffset() const {
624     return RecordOffset + offsetof(Hdr, Range);
625   }
626 
627   uint32_t RecordOffset;
628   Hdr Header;
629   ArrayRef<LocalVariableAddrGap> Gaps;
630 };
631 
632 // S_DEFRANGE_SUBFIELD
633 class DefRangeSubfieldSym : public SymbolRecord {
634 public:
635   struct Hdr {
636     ulittle32_t Program;
637     ulittle16_t OffsetInParent;
638     LocalVariableAddrRange Range;
639     // LocalVariableAddrGap Gaps[];
640   };
DefRangeSubfieldSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)641   DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
642                       ArrayRef<LocalVariableAddrGap> Gaps)
643       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
644         RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
645 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)646   static ErrorOr<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
647                                                   uint32_t RecordOffset,
648                                                   ArrayRef<uint8_t> &Data) {
649     const Hdr *H = nullptr;
650     ArrayRef<LocalVariableAddrGap> Gaps;
651     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
652 
653     return DefRangeSubfieldSym(RecordOffset, H, Gaps);
654   }
655 
getRelocationOffset()656   uint32_t getRelocationOffset() const {
657     return RecordOffset + offsetof(Hdr, Range);
658   }
659 
660   uint32_t RecordOffset;
661   Hdr Header;
662   ArrayRef<LocalVariableAddrGap> Gaps;
663 };
664 
665 // S_DEFRANGE_REGISTER
666 class DefRangeRegisterSym : public SymbolRecord {
667 public:
668   struct Hdr {
669     ulittle16_t Register;
670     ulittle16_t MayHaveNoName;
671     LocalVariableAddrRange Range;
672     // LocalVariableAddrGap Gaps[];
673   };
674 
DefRangeRegisterSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)675   DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
676                       ArrayRef<LocalVariableAddrGap> Gaps)
677       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
678         RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
679 
DefRangeRegisterSym(uint16_t Register,uint16_t MayHaveNoName,uint32_t OffsetStart,uint16_t ISectStart,uint16_t Range,ArrayRef<LocalVariableAddrGap> Gaps)680   DefRangeRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
681                       uint32_t OffsetStart, uint16_t ISectStart, uint16_t Range,
682                       ArrayRef<LocalVariableAddrGap> Gaps)
683       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(0),
684         Gaps(Gaps) {
685     Header.Register = Register;
686     Header.MayHaveNoName = MayHaveNoName;
687     Header.Range.OffsetStart = OffsetStart;
688     Header.Range.ISectStart = ISectStart;
689     Header.Range.Range = Range;
690   }
691 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)692   static ErrorOr<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
693                                                   uint32_t RecordOffset,
694                                                   ArrayRef<uint8_t> &Data) {
695     const Hdr *H = nullptr;
696     ArrayRef<LocalVariableAddrGap> Gaps;
697     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
698 
699     return DefRangeRegisterSym(RecordOffset, H, Gaps);
700   }
701 
getRelocationOffset()702   uint32_t getRelocationOffset() const {
703     return RecordOffset + offsetof(Hdr, Range);
704   }
705 
706   uint32_t RecordOffset;
707   Hdr Header;
708   ArrayRef<LocalVariableAddrGap> Gaps;
709 };
710 
711 // S_DEFRANGE_SUBFIELD_REGISTER
712 class DefRangeSubfieldRegisterSym : public SymbolRecord {
713 public:
714   struct Hdr {
715     ulittle16_t Register; // Register to which the variable is relative
716     ulittle16_t MayHaveNoName;
717     ulittle32_t OffsetInParent;
718     LocalVariableAddrRange Range;
719     // LocalVariableAddrGap Gaps[];
720   };
721 
DefRangeSubfieldRegisterSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)722   DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
723                               ArrayRef<LocalVariableAddrGap> Gaps)
724       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
725         RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
726 
DefRangeSubfieldRegisterSym(uint16_t Register,uint16_t MayHaveNoName,uint32_t OffsetInParent,ArrayRef<LocalVariableAddrGap> Gaps)727   DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
728                               uint32_t OffsetInParent,
729                               ArrayRef<LocalVariableAddrGap> Gaps)
730       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
731         RecordOffset(0), Gaps(Gaps) {
732     Header.Register = Register;
733     Header.MayHaveNoName = MayHaveNoName;
734     Header.OffsetInParent = OffsetInParent;
735   }
736 
737   static ErrorOr<DefRangeSubfieldRegisterSym>
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)738   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
739               ArrayRef<uint8_t> &Data) {
740     const Hdr *H = nullptr;
741     ArrayRef<LocalVariableAddrGap> Gaps;
742     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
743 
744     return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
745   }
746 
getRelocationOffset()747   uint32_t getRelocationOffset() const {
748     return RecordOffset + offsetof(Hdr, Range);
749   }
750 
751   uint32_t RecordOffset;
752   Hdr Header;
753   ArrayRef<LocalVariableAddrGap> Gaps;
754 };
755 
756 // S_DEFRANGE_FRAMEPOINTER_REL
757 class DefRangeFramePointerRelSym : public SymbolRecord {
758 public:
759   struct Hdr {
760     little32_t Offset; // Offset from the frame pointer register
761     LocalVariableAddrRange Range;
762     // LocalVariableAddrGap Gaps[];
763   };
764 
DefRangeFramePointerRelSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)765   DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
766                              ArrayRef<LocalVariableAddrGap> Gaps)
767       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
768         RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
769 
770   static ErrorOr<DefRangeFramePointerRelSym>
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)771   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
772               ArrayRef<uint8_t> &Data) {
773     const Hdr *H = nullptr;
774     ArrayRef<LocalVariableAddrGap> Gaps;
775     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
776 
777     return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
778   }
779 
getRelocationOffset()780   uint32_t getRelocationOffset() const {
781     return RecordOffset + offsetof(Hdr, Range);
782   }
783 
784   uint32_t RecordOffset;
785   Hdr Header;
786   ArrayRef<LocalVariableAddrGap> Gaps;
787 };
788 
789 // S_DEFRANGE_REGISTER_REL
790 class DefRangeRegisterRelSym : public SymbolRecord {
791 public:
792   struct Hdr {
793     ulittle16_t BaseRegister;
794     ulittle16_t Flags;
795     little32_t BasePointerOffset;
796     LocalVariableAddrRange Range;
797     // LocalVariableAddrGap Gaps[];
798   };
799 
DefRangeRegisterRelSym(uint32_t RecordOffset,const Hdr * H,ArrayRef<LocalVariableAddrGap> Gaps)800   DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
801                          ArrayRef<LocalVariableAddrGap> Gaps)
802       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
803         RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
804 
DefRangeRegisterRelSym(uint16_t BaseRegister,uint16_t Flags,int32_t BasePointerOffset,uint32_t OffsetStart,uint16_t ISectStart,uint16_t Range,ArrayRef<LocalVariableAddrGap> Gaps)805   DefRangeRegisterRelSym(uint16_t BaseRegister, uint16_t Flags,
806                          int32_t BasePointerOffset, uint32_t OffsetStart,
807                          uint16_t ISectStart, uint16_t Range,
808                          ArrayRef<LocalVariableAddrGap> Gaps)
809       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), RecordOffset(0),
810         Gaps(Gaps) {
811     Header.BaseRegister = BaseRegister;
812     Header.Flags = Flags;
813     Header.BasePointerOffset = BasePointerOffset;
814     Header.Range.OffsetStart = OffsetStart;
815     Header.Range.ISectStart = ISectStart;
816     Header.Range.Range = Range;
817   }
818 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)819   static ErrorOr<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
820                                                      uint32_t RecordOffset,
821                                                      ArrayRef<uint8_t> &Data) {
822     const Hdr *H = nullptr;
823     ArrayRef<LocalVariableAddrGap> Gaps;
824     CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
825 
826     return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
827   }
828 
hasSpilledUDTMember()829   bool hasSpilledUDTMember() const { return Header.Flags & 1; }
offsetInParent()830   uint16_t offsetInParent() const { return Header.Flags >> 4; }
831 
getRelocationOffset()832   uint32_t getRelocationOffset() const {
833     return RecordOffset + offsetof(Hdr, Range);
834   }
835 
836   uint32_t RecordOffset;
837   Hdr Header;
838   ArrayRef<LocalVariableAddrGap> Gaps;
839 };
840 
841 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
842 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
843 public:
844   struct Hdr {
845     little32_t Offset; // Offset from the frame pointer register
846   };
847 
DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset,const Hdr * H)848   DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
849       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
850         RecordOffset(RecordOffset), Header(*H) {}
851 
852   static ErrorOr<DefRangeFramePointerRelFullScopeSym>
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)853   deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
854               ArrayRef<uint8_t> &Data) {
855     const Hdr *H = nullptr;
856     CV_DESERIALIZE(Data, H);
857 
858     return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
859   }
860 
861   uint32_t RecordOffset;
862   Hdr Header;
863 };
864 
865 // S_BLOCK32
866 class BlockSym : public SymbolRecord {
867 public:
868   struct Hdr {
869     ulittle32_t PtrParent;
870     ulittle32_t PtrEnd;
871     ulittle32_t CodeSize;
872     ulittle32_t CodeOffset;
873     ulittle16_t Segment;
874     // Name: The null-terminated name follows.
875   };
876 
BlockSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)877   BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
878       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
879         Header(*H), Name(Name) {}
880 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)881   static ErrorOr<BlockSym> deserialize(SymbolRecordKind Kind,
882                                        uint32_t RecordOffset,
883                                        ArrayRef<uint8_t> &Data) {
884     const Hdr *H = nullptr;
885     StringRef Name;
886     CV_DESERIALIZE(Data, H, Name);
887 
888     return BlockSym(RecordOffset, H, Name);
889   }
890 
getRelocationOffset()891   uint32_t getRelocationOffset() const {
892     return RecordOffset + offsetof(Hdr, CodeOffset);
893   }
894 
895   uint32_t RecordOffset;
896   Hdr Header;
897   StringRef Name;
898 };
899 
900 // S_LABEL32
901 class LabelSym : public SymbolRecord {
902 public:
903   struct Hdr {
904     ulittle32_t CodeOffset;
905     ulittle16_t Segment;
906     uint8_t Flags; // CV_PROCFLAGS
907                    // Name: The null-terminated name follows.
908   };
909 
LabelSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)910   LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
911       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
912         Header(*H), Name(Name) {}
913 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)914   static ErrorOr<LabelSym> deserialize(SymbolRecordKind Kind,
915                                        uint32_t RecordOffset,
916                                        ArrayRef<uint8_t> &Data) {
917     const Hdr *H = nullptr;
918     StringRef Name;
919     CV_DESERIALIZE(Data, H, Name);
920 
921     return LabelSym(RecordOffset, H, Name);
922   }
923 
getRelocationOffset()924   uint32_t getRelocationOffset() const {
925     return RecordOffset + offsetof(Hdr, CodeOffset);
926   }
927 
928   uint32_t RecordOffset;
929   Hdr Header;
930   StringRef Name;
931 };
932 
933 // S_OBJNAME
934 class ObjNameSym : public SymbolRecord {
935 public:
936   struct Hdr {
937     ulittle32_t Signature;
938     // Name: The null-terminated name follows.
939   };
940 
ObjNameSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)941   ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
942       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
943         Header(*H), Name(Name) {}
944 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)945   static ErrorOr<ObjNameSym> deserialize(SymbolRecordKind Kind,
946                                          uint32_t RecordOffset,
947                                          ArrayRef<uint8_t> &Data) {
948     const Hdr *H = nullptr;
949     StringRef Name;
950     CV_DESERIALIZE(Data, H, Name);
951 
952     return ObjNameSym(RecordOffset, H, Name);
953   }
954 
955   uint32_t RecordOffset;
956   Hdr Header;
957   StringRef Name;
958 };
959 
960 // S_ENVBLOCK
961 class EnvBlockSym : public SymbolRecord {
962 public:
963   struct Hdr {
964     uint8_t Reserved;
965     // Sequence of zero terminated strings.
966   };
967 
EnvBlockSym(uint32_t RecordOffset,const Hdr * H,const std::vector<StringRef> & Fields)968   EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
969               const std::vector<StringRef> &Fields)
970       : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
971         Header(*H), Fields(Fields) {}
972 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)973   static ErrorOr<EnvBlockSym> deserialize(SymbolRecordKind Kind,
974                                           uint32_t RecordOffset,
975                                           ArrayRef<uint8_t> &Data) {
976     const Hdr *H = nullptr;
977     std::vector<StringRef> Fields;
978     CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
979 
980     return EnvBlockSym(RecordOffset, H, Fields);
981   }
982 
983   uint32_t RecordOffset;
984   Hdr Header;
985   std::vector<StringRef> Fields;
986 };
987 
988 // S_EXPORT
989 class ExportSym : public SymbolRecord {
990 public:
991   struct Hdr {
992     ulittle16_t Ordinal;
993     ulittle16_t Flags; // ExportFlags
994                        // Name: The null-terminated name follows.
995   };
996 
ExportSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)997   ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
998       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
999         Header(*H), Name(Name) {}
1000 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1001   static ErrorOr<ExportSym> deserialize(SymbolRecordKind Kind,
1002                                         uint32_t RecordOffset,
1003                                         ArrayRef<uint8_t> &Data) {
1004     const Hdr *H = nullptr;
1005     StringRef Name;
1006     CV_DESERIALIZE(Data, H, Name);
1007 
1008     return ExportSym(RecordOffset, H, Name);
1009   }
1010 
1011   uint32_t RecordOffset;
1012   Hdr Header;
1013   StringRef Name;
1014 };
1015 
1016 // S_FILESTATIC
1017 class FileStaticSym : public SymbolRecord {
1018 public:
1019   struct Hdr {
1020     ulittle32_t Index;             // Type Index
1021     ulittle32_t ModFilenameOffset; // Index of mod filename in string table
1022     ulittle16_t Flags;             // LocalSymFlags enum
1023                                    // Name: The null-terminated name follows.
1024   };
1025 
FileStaticSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1026   FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1027       : SymbolRecord(SymbolRecordKind::FileStaticSym),
1028         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1029 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1030   static ErrorOr<FileStaticSym> deserialize(SymbolRecordKind Kind,
1031                                             uint32_t RecordOffset,
1032                                             ArrayRef<uint8_t> &Data) {
1033     const Hdr *H = nullptr;
1034     StringRef Name;
1035     CV_DESERIALIZE(Data, H, Name);
1036 
1037     return FileStaticSym(RecordOffset, H, Name);
1038   }
1039 
1040   uint32_t RecordOffset;
1041   Hdr Header;
1042   StringRef Name;
1043 };
1044 
1045 // S_COMPILE2
1046 class Compile2Sym : public SymbolRecord {
1047 public:
1048   struct Hdr {
1049     ulittle32_t flags; // CompileSym2Flags enum
getLanguageHdr1050     uint8_t getLanguage() const { return flags & 0xFF; }
1051     unsigned short Machine; // CPUType enum
1052     unsigned short VersionFrontendMajor;
1053     unsigned short VersionFrontendMinor;
1054     unsigned short VersionFrontendBuild;
1055     unsigned short VersionBackendMajor;
1056     unsigned short VersionBackendMinor;
1057     unsigned short VersionBackendBuild;
1058     // Version: The null-terminated version string follows.
1059     // Optional block of zero terminated strings terminated with a double zero.
1060   };
1061 
Compile2Sym(uint32_t RecordOffset,const Hdr * H,StringRef Version)1062   Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
1063       : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
1064         Header(*H), Version(Version) {}
1065 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1066   static ErrorOr<Compile2Sym> deserialize(SymbolRecordKind Kind,
1067                                           uint32_t RecordOffset,
1068                                           ArrayRef<uint8_t> &Data) {
1069     const Hdr *H = nullptr;
1070     StringRef Version;
1071     CV_DESERIALIZE(Data, H, Version);
1072 
1073     return Compile2Sym(RecordOffset, H, Version);
1074   }
1075 
1076   uint32_t RecordOffset;
1077   Hdr Header;
1078   StringRef Version;
1079 };
1080 
1081 // S_COMPILE3
1082 class Compile3Sym : public SymbolRecord {
1083 public:
1084   struct Hdr {
1085     ulittle32_t flags; // CompileSym3Flags enum
getLanguageHdr1086     uint8_t getLanguage() const { return flags & 0xff; }
1087     ulittle16_t Machine; // CPUType enum
1088     ulittle16_t VersionFrontendMajor;
1089     ulittle16_t VersionFrontendMinor;
1090     ulittle16_t VersionFrontendBuild;
1091     ulittle16_t VersionFrontendQFE;
1092     ulittle16_t VersionBackendMajor;
1093     ulittle16_t VersionBackendMinor;
1094     ulittle16_t VersionBackendBuild;
1095     ulittle16_t VersionBackendQFE;
1096     // VersionString: The null-terminated version string follows.
1097   };
1098 
Compile3Sym(uint32_t RecordOffset,const Hdr * H,StringRef Version)1099   Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
1100       : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
1101         Header(*H), Version(Version) {}
1102 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1103   static ErrorOr<Compile3Sym> deserialize(SymbolRecordKind Kind,
1104                                           uint32_t RecordOffset,
1105                                           ArrayRef<uint8_t> &Data) {
1106     const Hdr *H = nullptr;
1107     StringRef Version;
1108     CV_DESERIALIZE(Data, H, Version);
1109 
1110     return Compile3Sym(RecordOffset, H, Version);
1111   }
1112 
1113   uint32_t RecordOffset;
1114   Hdr Header;
1115   StringRef Version;
1116 };
1117 
1118 // S_FRAMEPROC
1119 class FrameProcSym : public SymbolRecord {
1120 public:
1121   struct Hdr {
1122     ulittle32_t TotalFrameBytes;
1123     ulittle32_t PaddingFrameBytes;
1124     ulittle32_t OffsetToPadding;
1125     ulittle32_t BytesOfCalleeSavedRegisters;
1126     ulittle32_t OffsetOfExceptionHandler;
1127     ulittle16_t SectionIdOfExceptionHandler;
1128     ulittle32_t Flags;
1129   };
1130 
FrameProcSym(uint32_t RecordOffset,const Hdr * H)1131   FrameProcSym(uint32_t RecordOffset, const Hdr *H)
1132       : SymbolRecord(SymbolRecordKind::FrameProcSym),
1133         RecordOffset(RecordOffset), Header(*H) {}
1134 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1135   static ErrorOr<FrameProcSym> deserialize(SymbolRecordKind Kind,
1136                                            uint32_t RecordOffset,
1137                                            ArrayRef<uint8_t> &Data) {
1138     const Hdr *H = nullptr;
1139     CV_DESERIALIZE(Data, H);
1140 
1141     return FrameProcSym(RecordOffset, H);
1142   }
1143 
1144   uint32_t RecordOffset;
1145   Hdr Header;
1146 };
1147 
1148 // S_CALLSITEINFO
1149 class CallSiteInfoSym : public SymbolRecord {
1150 public:
1151   struct Hdr {
1152     ulittle32_t CodeOffset;
1153     ulittle16_t Segment;
1154     ulittle16_t Reserved;
1155     TypeIndex Type;
1156   };
1157 
CallSiteInfoSym(uint32_t RecordOffset,const Hdr * H)1158   CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
1159       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
1160         RecordOffset(RecordOffset), Header(*H) {}
1161 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1162   static ErrorOr<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
1163                                               uint32_t RecordOffset,
1164                                               ArrayRef<uint8_t> &Data) {
1165     const Hdr *H = nullptr;
1166     CV_DESERIALIZE(Data, H);
1167 
1168     return CallSiteInfoSym(RecordOffset, H);
1169   }
1170 
getRelocationOffset()1171   uint32_t getRelocationOffset() const {
1172     return RecordOffset + offsetof(Hdr, CodeOffset);
1173   }
1174 
1175   uint32_t RecordOffset;
1176   Hdr Header;
1177 };
1178 
1179 // S_HEAPALLOCSITE
1180 class HeapAllocationSiteSym : public SymbolRecord {
1181 public:
1182   struct Hdr {
1183     ulittle32_t CodeOffset;
1184     ulittle16_t Segment;
1185     ulittle16_t CallInstructionSize;
1186     TypeIndex Type;
1187   };
1188 
HeapAllocationSiteSym(uint32_t RecordOffset,const Hdr * H)1189   HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
1190       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
1191         RecordOffset(RecordOffset), Header(*H) {}
1192 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1193   static ErrorOr<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
1194                                                     uint32_t RecordOffset,
1195                                                     ArrayRef<uint8_t> &Data) {
1196     const Hdr *H = nullptr;
1197     CV_DESERIALIZE(Data, H);
1198 
1199     return HeapAllocationSiteSym(RecordOffset, H);
1200   }
1201 
getRelocationOffset()1202   uint32_t getRelocationOffset() const {
1203     return RecordOffset + offsetof(Hdr, CodeOffset);
1204   }
1205 
1206   uint32_t RecordOffset;
1207   Hdr Header;
1208 };
1209 
1210 // S_FRAMECOOKIE
1211 class FrameCookieSym : public SymbolRecord {
1212 public:
1213   struct Hdr {
1214     ulittle32_t CodeOffset;
1215     ulittle16_t Register;
1216     uint8_t CookieKind;
1217     uint8_t Flags;
1218   };
1219 
FrameCookieSym(uint32_t RecordOffset,const Hdr * H)1220   FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
1221       : SymbolRecord(SymbolRecordKind::FrameCookieSym),
1222         RecordOffset(RecordOffset), Header(*H) {}
1223 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1224   static ErrorOr<FrameCookieSym> deserialize(SymbolRecordKind Kind,
1225                                              uint32_t RecordOffset,
1226                                              ArrayRef<uint8_t> &Data) {
1227     const Hdr *H = nullptr;
1228     CV_DESERIALIZE(Data, H);
1229 
1230     return FrameCookieSym(RecordOffset, H);
1231   }
1232 
getRelocationOffset()1233   uint32_t getRelocationOffset() const {
1234     return RecordOffset + offsetof(Hdr, CodeOffset);
1235   }
1236 
1237   uint32_t RecordOffset;
1238   Hdr Header;
1239 };
1240 
1241 // S_UDT, S_COBOLUDT
1242 class UDTSym : public SymbolRecord {
1243 public:
1244   struct Hdr {
1245     TypeIndex Type; // Type of the UDT
1246                     // Name: The null-terminated name follows.
1247   };
1248 
UDTSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1249   UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1250       : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
1251         Header(*H), Name(Name) {}
1252 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1253   static ErrorOr<UDTSym> deserialize(SymbolRecordKind Kind,
1254                                      uint32_t RecordOffset,
1255                                      ArrayRef<uint8_t> &Data) {
1256     const Hdr *H = nullptr;
1257     StringRef Name;
1258     CV_DESERIALIZE(Data, H, Name);
1259 
1260     return UDTSym(RecordOffset, H, Name);
1261   }
1262 
1263   uint32_t RecordOffset;
1264   Hdr Header;
1265   StringRef Name;
1266 };
1267 
1268 // S_BUILDINFO
1269 class BuildInfoSym : public SymbolRecord {
1270 public:
1271   struct Hdr {
1272     ulittle32_t BuildId;
1273   };
1274 
BuildInfoSym(uint32_t RecordOffset,const Hdr * H)1275   BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
1276       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
1277         RecordOffset(RecordOffset), Header(*H) {}
1278 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1279   static ErrorOr<BuildInfoSym> deserialize(SymbolRecordKind Kind,
1280                                            uint32_t RecordOffset,
1281                                            ArrayRef<uint8_t> &Data) {
1282     const Hdr *H = nullptr;
1283     CV_DESERIALIZE(Data, H);
1284 
1285     return BuildInfoSym(RecordOffset, H);
1286   }
1287 
1288   uint32_t RecordOffset;
1289   Hdr Header;
1290 };
1291 
1292 // S_BPREL32
1293 class BPRelativeSym : public SymbolRecord {
1294 public:
1295   struct Hdr {
1296     little32_t Offset; // Offset from the base pointer register
1297     TypeIndex Type;    // Type of the variable
1298                        // Name: The null-terminated name follows.
1299   };
1300 
BPRelativeSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1301   BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1302       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
1303         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1304 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1305   static ErrorOr<BPRelativeSym> deserialize(SymbolRecordKind Kind,
1306                                             uint32_t RecordOffset,
1307                                             ArrayRef<uint8_t> &Data) {
1308     const Hdr *H = nullptr;
1309     StringRef Name;
1310     CV_DESERIALIZE(Data, H, Name);
1311 
1312     return BPRelativeSym(RecordOffset, H, Name);
1313   }
1314 
1315   uint32_t RecordOffset;
1316   Hdr Header;
1317   StringRef Name;
1318 };
1319 
1320 // S_REGREL32
1321 class RegRelativeSym : public SymbolRecord {
1322 public:
1323   struct Hdr {
1324     ulittle32_t Offset;   // Offset from the register
1325     TypeIndex Type;       // Type of the variable
1326     ulittle16_t Register; // Register to which the variable is relative
1327                           // Name: The null-terminated name follows.
1328   };
1329 
RegRelativeSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1330   RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1331       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
1332         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1333 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1334   static ErrorOr<RegRelativeSym> deserialize(SymbolRecordKind Kind,
1335                                              uint32_t RecordOffset,
1336                                              ArrayRef<uint8_t> &Data) {
1337     const Hdr *H = nullptr;
1338     StringRef Name;
1339     CV_DESERIALIZE(Data, H, Name);
1340 
1341     return RegRelativeSym(RecordOffset, H, Name);
1342   }
1343 
1344   uint32_t RecordOffset;
1345   Hdr Header;
1346   StringRef Name;
1347 };
1348 
1349 // S_CONSTANT, S_MANCONSTANT
1350 class ConstantSym : public SymbolRecord {
1351 public:
1352   struct Hdr {
1353     TypeIndex Type;
1354     // Value: The value of the constant.
1355     // Name: The null-terminated name follows.
1356   };
1357 
ConstantSym(uint32_t RecordOffset,const Hdr * H,const APSInt & Value,StringRef Name)1358   ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
1359               StringRef Name)
1360       : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
1361         Header(*H), Value(Value), Name(Name) {}
1362 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1363   static ErrorOr<ConstantSym> deserialize(SymbolRecordKind Kind,
1364                                           uint32_t RecordOffset,
1365                                           ArrayRef<uint8_t> &Data) {
1366     const Hdr *H = nullptr;
1367     APSInt Value;
1368     StringRef Name;
1369     CV_DESERIALIZE(Data, H, Value, Name);
1370 
1371     return ConstantSym(RecordOffset, H, Value, Name);
1372   }
1373 
1374   uint32_t RecordOffset;
1375   Hdr Header;
1376   APSInt Value;
1377   StringRef Name;
1378 };
1379 
1380 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
1381 class DataSym : public SymbolRecord {
1382 public:
1383   struct Hdr {
1384     TypeIndex Type;
1385     ulittle32_t DataOffset;
1386     ulittle16_t Segment;
1387     // Name: The null-terminated name follows.
1388   };
1389 
DataSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1390   DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1391       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
1392         Header(*H), Name(Name) {}
1393 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1394   static ErrorOr<DataSym> deserialize(SymbolRecordKind Kind,
1395                                       uint32_t RecordOffset,
1396                                       ArrayRef<uint8_t> &Data) {
1397     const Hdr *H = nullptr;
1398     StringRef Name;
1399     CV_DESERIALIZE(Data, H, Name);
1400 
1401     return DataSym(RecordOffset, H, Name);
1402   }
1403 
getRelocationOffset()1404   uint32_t getRelocationOffset() const {
1405     return RecordOffset + offsetof(Hdr, DataOffset);
1406   }
1407 
1408   uint32_t RecordOffset;
1409   Hdr Header;
1410   StringRef Name;
1411 };
1412 
1413 // S_LTHREAD32, S_GTHREAD32
1414 class ThreadLocalDataSym : public SymbolRecord {
1415 public:
1416   struct Hdr {
1417     TypeIndex Type;
1418     ulittle32_t DataOffset;
1419     ulittle16_t Segment;
1420     // Name: The null-terminated name follows.
1421   };
1422 
ThreadLocalDataSym(uint32_t RecordOffset,const Hdr * H,StringRef Name)1423   ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1424       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
1425         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1426 
deserialize(SymbolRecordKind Kind,uint32_t RecordOffset,ArrayRef<uint8_t> & Data)1427   static ErrorOr<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
1428                                                  uint32_t RecordOffset,
1429                                                  ArrayRef<uint8_t> &Data) {
1430     const Hdr *H = nullptr;
1431     StringRef Name;
1432     CV_DESERIALIZE(Data, H, Name);
1433 
1434     return ThreadLocalDataSym(RecordOffset, H, Name);
1435   }
1436 
getRelocationOffset()1437   uint32_t getRelocationOffset() const {
1438     return RecordOffset + offsetof(Hdr, DataOffset);
1439   }
1440 
1441   uint32_t RecordOffset;
1442   Hdr Header;
1443   StringRef Name;
1444 };
1445 
1446 typedef CVRecord<SymbolKind> CVSymbol;
1447 typedef VarStreamArray<CVSymbol> CVSymbolArray;
1448 
1449 } // namespace codeview
1450 } // namespace llvm
1451 
1452 #endif
1453