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/ArrayRef.h"
     15 #include "llvm/ADT/Optional.h"
     16 #include "llvm/ADT/StringRef.h"
     17 #include "llvm/ADT/iterator_range.h"
     18 #include "llvm/DebugInfo/CodeView/CVRecord.h"
     19 #include "llvm/DebugInfo/CodeView/CodeView.h"
     20 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
     21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
     22 #include "llvm/Support/BinaryStreamArray.h"
     23 #include "llvm/Support/Endian.h"
     24 #include <cstdint>
     25 #include <vector>
     26 
     27 namespace llvm {
     28 namespace codeview {
     29 
     30 class SymbolRecord {
     31 protected:
     32   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
     33 
     34 public:
     35   SymbolRecordKind getKind() const { return Kind; }
     36 
     37   SymbolRecordKind Kind;
     38 };
     39 
     40 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
     41 // S_LPROC32_DPC_ID
     42 class ProcSym : public SymbolRecord {
     43   static constexpr uint32_t RelocationOffset = 32;
     44 
     45 public:
     46   explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
     47   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
     48       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
     49 
     50   uint32_t getRelocationOffset() const {
     51     return RecordOffset + RelocationOffset;
     52   }
     53 
     54   uint32_t Parent = 0;
     55   uint32_t End = 0;
     56   uint32_t Next = 0;
     57   uint32_t CodeSize = 0;
     58   uint32_t DbgStart = 0;
     59   uint32_t DbgEnd = 0;
     60   TypeIndex FunctionType;
     61   uint32_t CodeOffset = 0;
     62   uint16_t Segment = 0;
     63   ProcSymFlags Flags = ProcSymFlags::None;
     64   StringRef Name;
     65 
     66   uint32_t RecordOffset = 0;
     67 };
     68 
     69 // S_THUNK32
     70 class Thunk32Sym : public SymbolRecord {
     71 public:
     72   explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
     73   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
     74       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
     75 
     76   uint32_t Parent;
     77   uint32_t End;
     78   uint32_t Next;
     79   uint32_t Offset;
     80   uint16_t Segment;
     81   uint16_t Length;
     82   ThunkOrdinal Thunk;
     83   StringRef Name;
     84   ArrayRef<uint8_t> VariantData;
     85 
     86   uint32_t RecordOffset;
     87 };
     88 
     89 // S_TRAMPOLINE
     90 class TrampolineSym : public SymbolRecord {
     91 public:
     92   explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
     93   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
     94       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
     95 
     96   TrampolineType Type;
     97   uint16_t Size;
     98   uint32_t ThunkOffset;
     99   uint32_t TargetOffset;
    100   uint16_t ThunkSection;
    101   uint16_t TargetSection;
    102 
    103   uint32_t RecordOffset;
    104 };
    105 
    106 // S_SECTION
    107 class SectionSym : public SymbolRecord {
    108 public:
    109   explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    110   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
    111       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
    112 
    113   uint16_t SectionNumber;
    114   uint8_t Alignment;
    115   uint32_t Rva;
    116   uint32_t Length;
    117   uint32_t Characteristics;
    118   StringRef Name;
    119 
    120   uint32_t RecordOffset;
    121 };
    122 
    123 // S_COFFGROUP
    124 class CoffGroupSym : public SymbolRecord {
    125 public:
    126   explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    127   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
    128       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
    129 
    130   uint32_t Size;
    131   uint32_t Characteristics;
    132   uint32_t Offset;
    133   uint16_t Segment;
    134   StringRef Name;
    135 
    136   uint32_t RecordOffset;
    137 };
    138 
    139 class ScopeEndSym : public SymbolRecord {
    140 public:
    141   explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    142   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
    143       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
    144 
    145   uint32_t RecordOffset;
    146 };
    147 
    148 class CallerSym : public SymbolRecord {
    149 public:
    150   explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    151   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
    152       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
    153 
    154   std::vector<TypeIndex> Indices;
    155 
    156   uint32_t RecordOffset;
    157 };
    158 
    159 struct BinaryAnnotationIterator {
    160   struct AnnotationData {
    161     BinaryAnnotationsOpCode OpCode;
    162     StringRef Name;
    163     uint32_t U1;
    164     uint32_t U2;
    165     int32_t S1;
    166   };
    167 
    168   BinaryAnnotationIterator() = default;
    169   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
    170   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
    171       : Data(Other.Data) {}
    172 
    173   bool operator==(BinaryAnnotationIterator Other) const {
    174     return Data == Other.Data;
    175   }
    176 
    177   bool operator!=(const BinaryAnnotationIterator &Other) const {
    178     return !(*this == Other);
    179   }
    180 
    181   BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
    182     Data = Other.Data;
    183     return *this;
    184   }
    185 
    186   BinaryAnnotationIterator &operator++() {
    187     if (!ParseCurrentAnnotation()) {
    188       *this = BinaryAnnotationIterator();
    189       return *this;
    190     }
    191     Data = Next;
    192     Next = ArrayRef<uint8_t>();
    193     Current.reset();
    194     return *this;
    195   }
    196 
    197   BinaryAnnotationIterator operator++(int) {
    198     BinaryAnnotationIterator Orig(*this);
    199     ++(*this);
    200     return Orig;
    201   }
    202 
    203   const AnnotationData &operator*() {
    204     ParseCurrentAnnotation();
    205     return Current.getValue();
    206   }
    207 
    208 private:
    209   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
    210     if (Annotations.empty())
    211       return -1;
    212 
    213     uint8_t FirstByte = Annotations.front();
    214     Annotations = Annotations.drop_front();
    215 
    216     if ((FirstByte & 0x80) == 0x00)
    217       return FirstByte;
    218 
    219     if (Annotations.empty())
    220       return -1;
    221 
    222     uint8_t SecondByte = Annotations.front();
    223     Annotations = Annotations.drop_front();
    224 
    225     if ((FirstByte & 0xC0) == 0x80)
    226       return ((FirstByte & 0x3F) << 8) | SecondByte;
    227 
    228     if (Annotations.empty())
    229       return -1;
    230 
    231     uint8_t ThirdByte = Annotations.front();
    232     Annotations = Annotations.drop_front();
    233 
    234     if (Annotations.empty())
    235       return -1;
    236 
    237     uint8_t FourthByte = Annotations.front();
    238     Annotations = Annotations.drop_front();
    239 
    240     if ((FirstByte & 0xE0) == 0xC0)
    241       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
    242              (ThirdByte << 8) | FourthByte;
    243 
    244     return -1;
    245   };
    246 
    247   static int32_t DecodeSignedOperand(uint32_t Operand) {
    248     if (Operand & 1)
    249       return -(Operand >> 1);
    250     return Operand >> 1;
    251   };
    252 
    253   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
    254     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
    255   };
    256 
    257   bool ParseCurrentAnnotation() {
    258     if (Current.hasValue())
    259       return true;
    260 
    261     Next = Data;
    262     uint32_t Op = GetCompressedAnnotation(Next);
    263     AnnotationData Result;
    264     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
    265     switch (Result.OpCode) {
    266     case BinaryAnnotationsOpCode::Invalid:
    267       Result.Name = "Invalid";
    268       Next = ArrayRef<uint8_t>();
    269       break;
    270     case BinaryAnnotationsOpCode::CodeOffset:
    271       Result.Name = "CodeOffset";
    272       Result.U1 = GetCompressedAnnotation(Next);
    273       break;
    274     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
    275       Result.Name = "ChangeCodeOffsetBase";
    276       Result.U1 = GetCompressedAnnotation(Next);
    277       break;
    278     case BinaryAnnotationsOpCode::ChangeCodeOffset:
    279       Result.Name = "ChangeCodeOffset";
    280       Result.U1 = GetCompressedAnnotation(Next);
    281       break;
    282     case BinaryAnnotationsOpCode::ChangeCodeLength:
    283       Result.Name = "ChangeCodeLength";
    284       Result.U1 = GetCompressedAnnotation(Next);
    285       break;
    286     case BinaryAnnotationsOpCode::ChangeFile:
    287       Result.Name = "ChangeFile";
    288       Result.U1 = GetCompressedAnnotation(Next);
    289       break;
    290     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
    291       Result.Name = "ChangeLineEndDelta";
    292       Result.U1 = GetCompressedAnnotation(Next);
    293       break;
    294     case BinaryAnnotationsOpCode::ChangeRangeKind:
    295       Result.Name = "ChangeRangeKind";
    296       Result.U1 = GetCompressedAnnotation(Next);
    297       break;
    298     case BinaryAnnotationsOpCode::ChangeColumnStart:
    299       Result.Name = "ChangeColumnStart";
    300       Result.U1 = GetCompressedAnnotation(Next);
    301       break;
    302     case BinaryAnnotationsOpCode::ChangeColumnEnd:
    303       Result.Name = "ChangeColumnEnd";
    304       Result.U1 = GetCompressedAnnotation(Next);
    305       break;
    306     case BinaryAnnotationsOpCode::ChangeLineOffset:
    307       Result.Name = "ChangeLineOffset";
    308       Result.S1 = DecodeSignedOperand(Next);
    309       break;
    310     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
    311       Result.Name = "ChangeColumnEndDelta";
    312       Result.S1 = DecodeSignedOperand(Next);
    313       break;
    314     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
    315       Result.Name = "ChangeCodeOffsetAndLineOffset";
    316       uint32_t Annotation = GetCompressedAnnotation(Next);
    317       Result.S1 = DecodeSignedOperand(Annotation >> 4);
    318       Result.U1 = Annotation & 0xf;
    319       break;
    320     }
    321     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
    322       Result.Name = "ChangeCodeLengthAndCodeOffset";
    323       Result.U1 = GetCompressedAnnotation(Next);
    324       Result.U2 = GetCompressedAnnotation(Next);
    325       break;
    326     }
    327     }
    328     Current = Result;
    329     return true;
    330   }
    331 
    332   Optional<AnnotationData> Current;
    333   ArrayRef<uint8_t> Data;
    334   ArrayRef<uint8_t> Next;
    335 };
    336 
    337 // S_INLINESITE
    338 class InlineSiteSym : public SymbolRecord {
    339 public:
    340   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    341   InlineSiteSym(uint32_t RecordOffset)
    342       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
    343         RecordOffset(RecordOffset) {}
    344 
    345   iterator_range<BinaryAnnotationIterator> annotations() const {
    346     return make_range(BinaryAnnotationIterator(AnnotationData),
    347                       BinaryAnnotationIterator());
    348   }
    349 
    350   uint32_t Parent;
    351   uint32_t End;
    352   TypeIndex Inlinee;
    353   std::vector<uint8_t> AnnotationData;
    354 
    355   uint32_t RecordOffset;
    356 };
    357 
    358 // S_PUB32
    359 class PublicSym32 : public SymbolRecord {
    360 public:
    361   explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    362   explicit PublicSym32(uint32_t RecordOffset)
    363       : SymbolRecord(SymbolRecordKind::PublicSym32),
    364         RecordOffset(RecordOffset) {}
    365 
    366   PublicSymFlags Flags = PublicSymFlags::None;
    367   uint32_t Offset = 0;
    368   uint16_t Segment = 0;
    369   StringRef Name;
    370 
    371   uint32_t RecordOffset = 0;
    372 };
    373 
    374 // S_REGISTER
    375 class RegisterSym : public SymbolRecord {
    376 public:
    377   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    378   RegisterSym(uint32_t RecordOffset)
    379       : SymbolRecord(SymbolRecordKind::RegisterSym),
    380         RecordOffset(RecordOffset) {}
    381 
    382   TypeIndex Index;
    383   RegisterId Register;
    384   StringRef Name;
    385 
    386   uint32_t RecordOffset;
    387 };
    388 
    389 // S_PROCREF, S_LPROCREF
    390 class ProcRefSym : public SymbolRecord {
    391 public:
    392   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    393   explicit ProcRefSym(uint32_t RecordOffset)
    394       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
    395   }
    396 
    397   uint32_t SumName;
    398   uint32_t SymOffset;
    399   uint16_t Module;
    400   StringRef Name;
    401 
    402   uint32_t RecordOffset;
    403 };
    404 
    405 // S_LOCAL
    406 class LocalSym : public SymbolRecord {
    407 public:
    408   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    409   explicit LocalSym(uint32_t RecordOffset)
    410       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
    411 
    412   TypeIndex Type;
    413   LocalSymFlags Flags;
    414   StringRef Name;
    415 
    416   uint32_t RecordOffset;
    417 };
    418 
    419 struct LocalVariableAddrRange {
    420   uint32_t OffsetStart;
    421   uint16_t ISectStart;
    422   uint16_t Range;
    423 };
    424 
    425 struct LocalVariableAddrGap {
    426   uint16_t GapStartOffset;
    427   uint16_t Range;
    428 };
    429 
    430 enum : uint16_t { MaxDefRange = 0xf000 };
    431 
    432 // S_DEFRANGE
    433 class DefRangeSym : public SymbolRecord {
    434   static constexpr uint32_t RelocationOffset = 8;
    435 
    436 public:
    437   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    438   explicit DefRangeSym(uint32_t RecordOffset)
    439       : SymbolRecord(SymbolRecordKind::DefRangeSym),
    440         RecordOffset(RecordOffset) {}
    441 
    442   uint32_t getRelocationOffset() const {
    443     return RecordOffset + RelocationOffset;
    444   }
    445 
    446   uint32_t Program;
    447   LocalVariableAddrRange Range;
    448   std::vector<LocalVariableAddrGap> Gaps;
    449 
    450   uint32_t RecordOffset;
    451 };
    452 
    453 // S_DEFRANGE_SUBFIELD
    454 class DefRangeSubfieldSym : public SymbolRecord {
    455   static constexpr uint32_t RelocationOffset = 12;
    456 
    457 public:
    458   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    459   DefRangeSubfieldSym(uint32_t RecordOffset)
    460       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
    461         RecordOffset(RecordOffset) {}
    462 
    463   uint32_t getRelocationOffset() const {
    464     return RecordOffset + RelocationOffset;
    465   }
    466 
    467   uint32_t Program;
    468   uint16_t OffsetInParent;
    469   LocalVariableAddrRange Range;
    470   std::vector<LocalVariableAddrGap> Gaps;
    471 
    472   uint32_t RecordOffset;
    473 };
    474 
    475 // S_DEFRANGE_REGISTER
    476 class DefRangeRegisterSym : public SymbolRecord {
    477 public:
    478   struct Header {
    479     ulittle16_t Register;
    480     ulittle16_t MayHaveNoName;
    481   };
    482 
    483   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    484   DefRangeRegisterSym(uint32_t RecordOffset)
    485       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
    486         RecordOffset(RecordOffset) {}
    487 
    488   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
    489 
    490   Header Hdr;
    491   LocalVariableAddrRange Range;
    492   std::vector<LocalVariableAddrGap> Gaps;
    493 
    494   uint32_t RecordOffset;
    495 };
    496 
    497 // S_DEFRANGE_SUBFIELD_REGISTER
    498 class DefRangeSubfieldRegisterSym : public SymbolRecord {
    499 public:
    500   struct Header {
    501     ulittle16_t Register;
    502     ulittle16_t MayHaveNoName;
    503     ulittle32_t OffsetInParent;
    504   };
    505 
    506   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
    507       : SymbolRecord(Kind) {}
    508   DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
    509       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
    510         RecordOffset(RecordOffset) {}
    511 
    512   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
    513 
    514   Header Hdr;
    515   LocalVariableAddrRange Range;
    516   std::vector<LocalVariableAddrGap> Gaps;
    517 
    518   uint32_t RecordOffset;
    519 };
    520 
    521 // S_DEFRANGE_FRAMEPOINTER_REL
    522 class DefRangeFramePointerRelSym : public SymbolRecord {
    523   static constexpr uint32_t RelocationOffset = 8;
    524 
    525 public:
    526   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
    527       : SymbolRecord(Kind) {}
    528   DefRangeFramePointerRelSym(uint32_t RecordOffset)
    529       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
    530         RecordOffset(RecordOffset) {}
    531 
    532   uint32_t getRelocationOffset() const {
    533     return RecordOffset + RelocationOffset;
    534   }
    535 
    536   int32_t Offset;
    537   LocalVariableAddrRange Range;
    538   std::vector<LocalVariableAddrGap> Gaps;
    539 
    540   uint32_t RecordOffset;
    541 };
    542 
    543 // S_DEFRANGE_REGISTER_REL
    544 class DefRangeRegisterRelSym : public SymbolRecord {
    545 public:
    546   struct Header {
    547     ulittle16_t Register;
    548     ulittle16_t Flags;
    549     little32_t BasePointerOffset;
    550   };
    551 
    552   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    553   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
    554       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
    555         RecordOffset(RecordOffset) {}
    556 
    557   // The flags implement this notional bitfield:
    558   //   uint16_t IsSubfield : 1;
    559   //   uint16_t Padding : 3;
    560   //   uint16_t OffsetInParent : 12;
    561   enum : uint16_t {
    562     IsSubfieldFlag = 1,
    563     OffsetInParentShift = 4,
    564   };
    565 
    566   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
    567   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
    568 
    569   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
    570 
    571   Header Hdr;
    572   LocalVariableAddrRange Range;
    573   std::vector<LocalVariableAddrGap> Gaps;
    574 
    575   uint32_t RecordOffset;
    576 };
    577 
    578 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
    579 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
    580 public:
    581   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
    582       : SymbolRecord(Kind) {}
    583   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
    584       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
    585         RecordOffset(RecordOffset) {}
    586 
    587   int32_t Offset;
    588 
    589   uint32_t RecordOffset;
    590 };
    591 
    592 // S_BLOCK32
    593 class BlockSym : public SymbolRecord {
    594   static constexpr uint32_t RelocationOffset = 16;
    595 
    596 public:
    597   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    598   explicit BlockSym(uint32_t RecordOffset)
    599       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
    600 
    601   uint32_t getRelocationOffset() const {
    602     return RecordOffset + RelocationOffset;
    603   }
    604 
    605   uint32_t Parent;
    606   uint32_t End;
    607   uint32_t CodeSize;
    608   uint32_t CodeOffset;
    609   uint16_t Segment;
    610   StringRef Name;
    611 
    612   uint32_t RecordOffset;
    613 };
    614 
    615 // S_LABEL32
    616 class LabelSym : public SymbolRecord {
    617   static constexpr uint32_t RelocationOffset = 4;
    618 
    619 public:
    620   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    621   explicit LabelSym(uint32_t RecordOffset)
    622       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
    623 
    624   uint32_t getRelocationOffset() const {
    625     return RecordOffset + RelocationOffset;
    626   }
    627 
    628   uint32_t CodeOffset;
    629   uint16_t Segment;
    630   ProcSymFlags Flags;
    631   StringRef Name;
    632 
    633   uint32_t RecordOffset;
    634 };
    635 
    636 // S_OBJNAME
    637 class ObjNameSym : public SymbolRecord {
    638 public:
    639   explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    640   ObjNameSym(uint32_t RecordOffset)
    641       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
    642   }
    643 
    644   uint32_t Signature;
    645   StringRef Name;
    646 
    647   uint32_t RecordOffset;
    648 };
    649 
    650 // S_ENVBLOCK
    651 class EnvBlockSym : public SymbolRecord {
    652 public:
    653   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    654   EnvBlockSym(uint32_t RecordOffset)
    655       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
    656         RecordOffset(RecordOffset) {}
    657 
    658   std::vector<StringRef> Fields;
    659 
    660   uint32_t RecordOffset;
    661 };
    662 
    663 // S_EXPORT
    664 class ExportSym : public SymbolRecord {
    665 public:
    666   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    667   ExportSym(uint32_t RecordOffset)
    668       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
    669 
    670   uint16_t Ordinal;
    671   ExportFlags Flags;
    672   StringRef Name;
    673 
    674   uint32_t RecordOffset;
    675 };
    676 
    677 // S_FILESTATIC
    678 class FileStaticSym : public SymbolRecord {
    679 public:
    680   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    681   FileStaticSym(uint32_t RecordOffset)
    682       : SymbolRecord(SymbolRecordKind::FileStaticSym),
    683         RecordOffset(RecordOffset) {}
    684 
    685   TypeIndex Index;
    686   uint32_t ModFilenameOffset;
    687   LocalSymFlags Flags;
    688   StringRef Name;
    689 
    690   uint32_t RecordOffset;
    691 };
    692 
    693 // S_COMPILE2
    694 class Compile2Sym : public SymbolRecord {
    695 public:
    696   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    697   Compile2Sym(uint32_t RecordOffset)
    698       : SymbolRecord(SymbolRecordKind::Compile2Sym),
    699         RecordOffset(RecordOffset) {}
    700 
    701   CompileSym2Flags Flags;
    702   CPUType Machine;
    703   uint16_t VersionFrontendMajor;
    704   uint16_t VersionFrontendMinor;
    705   uint16_t VersionFrontendBuild;
    706   uint16_t VersionBackendMajor;
    707   uint16_t VersionBackendMinor;
    708   uint16_t VersionBackendBuild;
    709   StringRef Version;
    710   std::vector<StringRef> ExtraStrings;
    711 
    712   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
    713   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
    714 
    715   uint32_t RecordOffset;
    716 };
    717 
    718 // S_COMPILE3
    719 class Compile3Sym : public SymbolRecord {
    720 public:
    721   explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    722   Compile3Sym(uint32_t RecordOffset)
    723       : SymbolRecord(SymbolRecordKind::Compile3Sym),
    724         RecordOffset(RecordOffset) {}
    725 
    726   CompileSym3Flags Flags;
    727   CPUType Machine;
    728   uint16_t VersionFrontendMajor;
    729   uint16_t VersionFrontendMinor;
    730   uint16_t VersionFrontendBuild;
    731   uint16_t VersionFrontendQFE;
    732   uint16_t VersionBackendMajor;
    733   uint16_t VersionBackendMinor;
    734   uint16_t VersionBackendBuild;
    735   uint16_t VersionBackendQFE;
    736   StringRef Version;
    737 
    738   void setLanguage(SourceLanguage Lang) {
    739     Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
    740   }
    741 
    742   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
    743   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
    744 
    745   uint32_t RecordOffset;
    746 };
    747 
    748 // S_FRAMEPROC
    749 class FrameProcSym : public SymbolRecord {
    750 public:
    751   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    752   explicit FrameProcSym(uint32_t RecordOffset)
    753       : SymbolRecord(SymbolRecordKind::FrameProcSym),
    754         RecordOffset(RecordOffset) {}
    755 
    756   uint32_t TotalFrameBytes;
    757   uint32_t PaddingFrameBytes;
    758   uint32_t OffsetToPadding;
    759   uint32_t BytesOfCalleeSavedRegisters;
    760   uint32_t OffsetOfExceptionHandler;
    761   uint16_t SectionIdOfExceptionHandler;
    762   FrameProcedureOptions Flags;
    763 
    764   uint32_t RecordOffset;
    765 };
    766 
    767 // S_CALLSITEINFO
    768 class CallSiteInfoSym : public SymbolRecord {
    769   static constexpr uint32_t RelocationOffset = 4;
    770 
    771 public:
    772   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    773   explicit CallSiteInfoSym(uint32_t RecordOffset)
    774       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
    775 
    776   uint32_t getRelocationOffset() const {
    777     return RecordOffset + RelocationOffset;
    778   }
    779 
    780   uint32_t CodeOffset;
    781   uint16_t Segment;
    782   TypeIndex Type;
    783 
    784   uint32_t RecordOffset;
    785 };
    786 
    787 // S_HEAPALLOCSITE
    788 class HeapAllocationSiteSym : public SymbolRecord {
    789   static constexpr uint32_t RelocationOffset = 4;
    790 
    791 public:
    792   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    793   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
    794       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
    795         RecordOffset(RecordOffset) {}
    796 
    797   uint32_t getRelocationOffset() const {
    798     return RecordOffset + RelocationOffset;
    799   }
    800 
    801   uint32_t CodeOffset;
    802   uint16_t Segment;
    803   uint16_t CallInstructionSize;
    804   TypeIndex Type;
    805 
    806   uint32_t RecordOffset;
    807 };
    808 
    809 // S_FRAMECOOKIE
    810 class FrameCookieSym : public SymbolRecord {
    811   static constexpr uint32_t RelocationOffset = 4;
    812 
    813 public:
    814   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    815   explicit FrameCookieSym(uint32_t RecordOffset)
    816       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
    817 
    818   uint32_t getRelocationOffset() const {
    819     return RecordOffset + RelocationOffset;
    820   }
    821 
    822   uint32_t CodeOffset;
    823   uint16_t Register;
    824   FrameCookieKind CookieKind;
    825   uint8_t Flags;
    826 
    827   uint32_t RecordOffset;
    828 };
    829 
    830 // S_UDT, S_COBOLUDT
    831 class UDTSym : public SymbolRecord {
    832 public:
    833   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    834   explicit UDTSym(uint32_t RecordOffset)
    835       : SymbolRecord(SymbolRecordKind::UDTSym) {}
    836 
    837   TypeIndex Type;
    838   StringRef Name;
    839 
    840   uint32_t RecordOffset;
    841 };
    842 
    843 // S_BUILDINFO
    844 class BuildInfoSym : public SymbolRecord {
    845 public:
    846   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    847   BuildInfoSym(uint32_t RecordOffset)
    848       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
    849         RecordOffset(RecordOffset) {}
    850 
    851   TypeIndex BuildId;
    852 
    853   uint32_t RecordOffset;
    854 };
    855 
    856 // S_BPREL32
    857 class BPRelativeSym : public SymbolRecord {
    858 public:
    859   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    860   explicit BPRelativeSym(uint32_t RecordOffset)
    861       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
    862         RecordOffset(RecordOffset) {}
    863 
    864   int32_t Offset;
    865   TypeIndex Type;
    866   StringRef Name;
    867 
    868   uint32_t RecordOffset;
    869 };
    870 
    871 // S_REGREL32
    872 class RegRelativeSym : public SymbolRecord {
    873 public:
    874   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    875   explicit RegRelativeSym(uint32_t RecordOffset)
    876       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
    877         RecordOffset(RecordOffset) {}
    878 
    879   uint32_t Offset;
    880   TypeIndex Type;
    881   RegisterId Register;
    882   StringRef Name;
    883 
    884   uint32_t RecordOffset;
    885 };
    886 
    887 // S_CONSTANT, S_MANCONSTANT
    888 class ConstantSym : public SymbolRecord {
    889 public:
    890   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    891   ConstantSym(uint32_t RecordOffset)
    892       : SymbolRecord(SymbolRecordKind::ConstantSym),
    893         RecordOffset(RecordOffset) {}
    894 
    895   TypeIndex Type;
    896   APSInt Value;
    897   StringRef Name;
    898 
    899   uint32_t RecordOffset;
    900 };
    901 
    902 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
    903 class DataSym : public SymbolRecord {
    904   static constexpr uint32_t RelocationOffset = 8;
    905 
    906 public:
    907   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    908   DataSym(uint32_t RecordOffset)
    909       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
    910 
    911   uint32_t getRelocationOffset() const {
    912     return RecordOffset + RelocationOffset;
    913   }
    914 
    915   TypeIndex Type;
    916   uint32_t DataOffset;
    917   uint16_t Segment;
    918   StringRef Name;
    919 
    920   uint32_t RecordOffset;
    921 };
    922 
    923 // S_LTHREAD32, S_GTHREAD32
    924 class ThreadLocalDataSym : public SymbolRecord {
    925   static constexpr uint32_t RelocationOffset = 8;
    926 
    927 public:
    928   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    929   explicit ThreadLocalDataSym(uint32_t RecordOffset)
    930       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
    931         RecordOffset(RecordOffset) {}
    932 
    933   uint32_t getRelocationOffset() const {
    934     return RecordOffset + RelocationOffset;
    935   }
    936 
    937   TypeIndex Type;
    938   uint32_t DataOffset;
    939   uint16_t Segment;
    940   StringRef Name;
    941 
    942   uint32_t RecordOffset;
    943 };
    944 
    945 // S_ANNOTATION
    946 
    947 using CVSymbol = CVRecord<SymbolKind>;
    948 using CVSymbolArray = VarStreamArray<CVSymbol>;
    949 
    950 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
    951                                         uint32_t Offset);
    952 
    953 } // end namespace codeview
    954 } // end namespace llvm
    955 
    956 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
    957