Home | History | Annotate | Download | only in CodeView
      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:
     33   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
     34 
     35 public:
     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 
     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
     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 
     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
    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 
    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
    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 
    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
    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 
    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 
    217 class ScopeEndSym : public SymbolRecord {
    218 public:
    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 
    230 class CallerSym : public SymbolRecord {
    231 public:
    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 
    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 
    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 
    306 private:
    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
    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 
    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 
    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 
    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
    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 
    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
    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 
    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
    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 
    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 
    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 
    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
    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   };
    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
    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 
    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
    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 
    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
    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 
    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
    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 
    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
    842 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
    843 public:
    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
    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 
    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
    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 
    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
    934 class ObjNameSym : public SymbolRecord {
    935 public:
    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
    961 class EnvBlockSym : public SymbolRecord {
    962 public:
    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
    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 
    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
   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 
   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
   1046 class Compile2Sym : public SymbolRecord {
   1047 public:
   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
   1082 class Compile3Sym : public SymbolRecord {
   1083 public:
   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
   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 
   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
   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 
   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
   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 
   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
   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 
   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
   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 
   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
   1269 class BuildInfoSym : public SymbolRecord {
   1270 public:
   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
   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 
   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
   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 
   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
   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 
   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
   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 
   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
   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 
   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 
   1446 typedef CVRecord<SymbolKind> CVSymbol;
   1447 typedef VarStreamArray<CVSymbol> CVSymbolArray;
   1448 
   1449 } // namespace codeview
   1450 } // namespace llvm
   1451 
   1452 #endif
   1453