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
24namespace llvm {
25namespace codeview {
26
27using llvm::support::ulittle16_t;
28using llvm::support::ulittle32_t;
29using llvm::support::little32_t;
30
31class SymbolRecord {
32protected:
33  explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
34
35public:
36  SymbolRecordKind getKind() const { return Kind; }
37
38private:
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
44class ProcSym : public SymbolRecord {
45public:
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
60  ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
61          StringRef Name)
62      : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
63  }
64
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
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
85class Thunk32Sym : public SymbolRecord {
86public:
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
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
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
123class TrampolineSym : public SymbolRecord {
124public:
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
134  TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
135      : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
136
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
152class SectionSym : public SymbolRecord {
153public:
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
164  SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
165             StringRef Name)
166      : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
167  }
168
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
186class CoffGroupSym : public SymbolRecord {
187public:
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
196  CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
197               StringRef Name)
198      : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
199  }
200
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
217class ScopeEndSym : public SymbolRecord {
218public:
219  ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
220      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
221
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
230class CallerSym : public SymbolRecord {
231public:
232  struct Hdr {
233    ulittle32_t Count;
234  };
235
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
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
257struct BinaryAnnotationIterator {
258  struct AnnotationData {
259    BinaryAnnotationsOpCode OpCode;
260    StringRef Name;
261    uint32_t U1;
262    uint32_t U2;
263    int32_t S1;
264  };
265
266  BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
267  BinaryAnnotationIterator() {}
268  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
306private:
307  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
345  static int32_t DecodeSignedOperand(uint32_t Operand) {
346    if (Operand & 1)
347      return -(Operand >> 1);
348    return Operand >> 1;
349  };
350
351  static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
352    return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
353  };
354
355  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
436class InlineSiteSym : public SymbolRecord {
437public:
438  struct Hdr {
439    ulittle32_t PtrParent;
440    ulittle32_t PtrEnd;
441    TypeIndex Inlinee;
442    // BinaryAnnotations
443  };
444
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
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
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
468private:
469  ArrayRef<uint8_t> Annotations;
470};
471
472// S_PUB32
473class PublicSym32 : public SymbolRecord {
474public:
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
482  PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
483      : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
484        Header(*H), Name(Name) {}
485
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
502class RegisterSym : public SymbolRecord {
503public:
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
510  RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
511      : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
512        Header(*H), Name(Name) {}
513
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
530class ProcRefSym : public SymbolRecord {
531public:
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
539  ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
540      : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
541        Header(*H), Name(Name) {}
542
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
559class LocalSym : public SymbolRecord {
560public:
561  struct Hdr {
562    TypeIndex Type;
563    ulittle16_t Flags; // LocalSymFlags enum
564                       // Name: The null-terminated name follows.
565  };
566
567  LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
568      : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
569        Header(*H), Name(Name) {}
570
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
586struct LocalVariableAddrRange {
587  ulittle32_t OffsetStart;
588  ulittle16_t ISectStart;
589  ulittle16_t Range;
590};
591
592struct LocalVariableAddrGap {
593  ulittle16_t GapStartOffset;
594  ulittle16_t Range;
595};
596
597enum : uint16_t { MaxDefRange = 0xf000 };
598
599// S_DEFRANGE
600class DefRangeSym : public SymbolRecord {
601public:
602  struct Hdr {
603    ulittle32_t Program;
604    LocalVariableAddrRange Range;
605    // LocalVariableAddrGap Gaps[];
606  };
607
608  DefRangeSym(uint32_t RecordOffset, const Hdr *H,
609              ArrayRef<LocalVariableAddrGap> Gaps)
610      : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
611        Header(*H), Gaps(Gaps) {}
612
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
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
633class DefRangeSubfieldSym : public SymbolRecord {
634public:
635  struct Hdr {
636    ulittle32_t Program;
637    ulittle16_t OffsetInParent;
638    LocalVariableAddrRange Range;
639    // LocalVariableAddrGap Gaps[];
640  };
641  DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
642                      ArrayRef<LocalVariableAddrGap> Gaps)
643      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
644        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
645
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
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
666class DefRangeRegisterSym : public SymbolRecord {
667public:
668  struct Hdr {
669    ulittle16_t Register;
670    ulittle16_t MayHaveNoName;
671    LocalVariableAddrRange Range;
672    // LocalVariableAddrGap Gaps[];
673  };
674
675  DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
676                      ArrayRef<LocalVariableAddrGap> Gaps)
677      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
678        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
679
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
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
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
712class DefRangeSubfieldRegisterSym : public SymbolRecord {
713public:
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
722  DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
723                              ArrayRef<LocalVariableAddrGap> Gaps)
724      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
725        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
726
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>
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
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
757class DefRangeFramePointerRelSym : public SymbolRecord {
758public:
759  struct Hdr {
760    little32_t Offset; // Offset from the frame pointer register
761    LocalVariableAddrRange Range;
762    // LocalVariableAddrGap Gaps[];
763  };
764
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>
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
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
790class DefRangeRegisterRelSym : public SymbolRecord {
791public:
792  struct Hdr {
793    ulittle16_t BaseRegister;
794    ulittle16_t Flags;
795    little32_t BasePointerOffset;
796    LocalVariableAddrRange Range;
797    // LocalVariableAddrGap Gaps[];
798  };
799
800  DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
801                         ArrayRef<LocalVariableAddrGap> Gaps)
802      : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
803        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
804
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
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
829  bool hasSpilledUDTMember() const { return Header.Flags & 1; }
830  uint16_t offsetInParent() const { return Header.Flags >> 4; }
831
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
842class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
843public:
844  struct Hdr {
845    little32_t Offset; // Offset from the frame pointer register
846  };
847
848  DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
849      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
850        RecordOffset(RecordOffset), Header(*H) {}
851
852  static ErrorOr<DefRangeFramePointerRelFullScopeSym>
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
866class BlockSym : public SymbolRecord {
867public:
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
877  BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
878      : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
879        Header(*H), Name(Name) {}
880
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
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
901class LabelSym : public SymbolRecord {
902public:
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
910  LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
911      : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
912        Header(*H), Name(Name) {}
913
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
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
934class ObjNameSym : public SymbolRecord {
935public:
936  struct Hdr {
937    ulittle32_t Signature;
938    // Name: The null-terminated name follows.
939  };
940
941  ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
942      : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
943        Header(*H), Name(Name) {}
944
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
961class EnvBlockSym : public SymbolRecord {
962public:
963  struct Hdr {
964    uint8_t Reserved;
965    // Sequence of zero terminated strings.
966  };
967
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
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
989class ExportSym : public SymbolRecord {
990public:
991  struct Hdr {
992    ulittle16_t Ordinal;
993    ulittle16_t Flags; // ExportFlags
994                       // Name: The null-terminated name follows.
995  };
996
997  ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
998      : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
999        Header(*H), Name(Name) {}
1000
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
1017class FileStaticSym : public SymbolRecord {
1018public:
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
1026  FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1027      : SymbolRecord(SymbolRecordKind::FileStaticSym),
1028        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1029
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
1046class Compile2Sym : public SymbolRecord {
1047public:
1048  struct Hdr {
1049    ulittle32_t flags; // CompileSym2Flags enum
1050    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
1062  Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
1063      : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
1064        Header(*H), Version(Version) {}
1065
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
1082class Compile3Sym : public SymbolRecord {
1083public:
1084  struct Hdr {
1085    ulittle32_t flags; // CompileSym3Flags enum
1086    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
1099  Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
1100      : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
1101        Header(*H), Version(Version) {}
1102
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
1119class FrameProcSym : public SymbolRecord {
1120public:
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
1131  FrameProcSym(uint32_t RecordOffset, const Hdr *H)
1132      : SymbolRecord(SymbolRecordKind::FrameProcSym),
1133        RecordOffset(RecordOffset), Header(*H) {}
1134
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
1149class CallSiteInfoSym : public SymbolRecord {
1150public:
1151  struct Hdr {
1152    ulittle32_t CodeOffset;
1153    ulittle16_t Segment;
1154    ulittle16_t Reserved;
1155    TypeIndex Type;
1156  };
1157
1158  CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
1159      : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
1160        RecordOffset(RecordOffset), Header(*H) {}
1161
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
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
1180class HeapAllocationSiteSym : public SymbolRecord {
1181public:
1182  struct Hdr {
1183    ulittle32_t CodeOffset;
1184    ulittle16_t Segment;
1185    ulittle16_t CallInstructionSize;
1186    TypeIndex Type;
1187  };
1188
1189  HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
1190      : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
1191        RecordOffset(RecordOffset), Header(*H) {}
1192
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
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
1211class FrameCookieSym : public SymbolRecord {
1212public:
1213  struct Hdr {
1214    ulittle32_t CodeOffset;
1215    ulittle16_t Register;
1216    uint8_t CookieKind;
1217    uint8_t Flags;
1218  };
1219
1220  FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
1221      : SymbolRecord(SymbolRecordKind::FrameCookieSym),
1222        RecordOffset(RecordOffset), Header(*H) {}
1223
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
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
1242class UDTSym : public SymbolRecord {
1243public:
1244  struct Hdr {
1245    TypeIndex Type; // Type of the UDT
1246                    // Name: The null-terminated name follows.
1247  };
1248
1249  UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1250      : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
1251        Header(*H), Name(Name) {}
1252
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
1269class BuildInfoSym : public SymbolRecord {
1270public:
1271  struct Hdr {
1272    ulittle32_t BuildId;
1273  };
1274
1275  BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
1276      : SymbolRecord(SymbolRecordKind::BuildInfoSym),
1277        RecordOffset(RecordOffset), Header(*H) {}
1278
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
1293class BPRelativeSym : public SymbolRecord {
1294public:
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
1301  BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1302      : SymbolRecord(SymbolRecordKind::BPRelativeSym),
1303        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1304
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
1321class RegRelativeSym : public SymbolRecord {
1322public:
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
1330  RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1331      : SymbolRecord(SymbolRecordKind::RegRelativeSym),
1332        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1333
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
1350class ConstantSym : public SymbolRecord {
1351public:
1352  struct Hdr {
1353    TypeIndex Type;
1354    // Value: The value of the constant.
1355    // Name: The null-terminated name follows.
1356  };
1357
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
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
1381class DataSym : public SymbolRecord {
1382public:
1383  struct Hdr {
1384    TypeIndex Type;
1385    ulittle32_t DataOffset;
1386    ulittle16_t Segment;
1387    // Name: The null-terminated name follows.
1388  };
1389
1390  DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1391      : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
1392        Header(*H), Name(Name) {}
1393
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
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
1414class ThreadLocalDataSym : public SymbolRecord {
1415public:
1416  struct Hdr {
1417    TypeIndex Type;
1418    ulittle32_t DataOffset;
1419    ulittle16_t Segment;
1420    // Name: The null-terminated name follows.
1421  };
1422
1423  ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
1424      : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
1425        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
1426
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
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
1446typedef CVRecord<SymbolKind> CVSymbol;
1447typedef VarStreamArray<CVSymbol> CVSymbolArray;
1448
1449} // namespace codeview
1450} // namespace llvm
1451
1452#endif
1453