Home | History | Annotate | Line # | Download | only in CodeView
      1 //===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
     10 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
     11 
     12 #include "llvm/ADT/APSInt.h"
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/ADT/Optional.h"
     15 #include "llvm/ADT/StringRef.h"
     16 #include "llvm/ADT/iterator.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 = 0;
     77   uint32_t End = 0;
     78   uint32_t Next = 0;
     79   uint32_t Offset = 0;
     80   uint16_t Segment = 0;
     81   uint16_t Length = 0;
     82   ThunkOrdinal Thunk = ThunkOrdinal::Standard;
     83   StringRef Name;
     84   ArrayRef<uint8_t> VariantData;
     85 
     86   uint32_t RecordOffset = 0;
     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 = 0;
     98   uint32_t ThunkOffset = 0;
     99   uint32_t TargetOffset = 0;
    100   uint16_t ThunkSection = 0;
    101   uint16_t TargetSection = 0;
    102 
    103   uint32_t RecordOffset = 0;
    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 = 0;
    114   uint8_t Alignment = 0;
    115   uint32_t Rva = 0;
    116   uint32_t Length = 0;
    117   uint32_t Characteristics = 0;
    118   StringRef Name;
    119 
    120   uint32_t RecordOffset = 0;
    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 = 0;
    131   uint32_t Characteristics = 0;
    132   uint32_t Offset = 0;
    133   uint16_t Segment = 0;
    134   StringRef Name;
    135 
    136   uint32_t RecordOffset = 0;
    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 = 0;
    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 = 0;
    157 };
    158 
    159 struct DecodedAnnotation {
    160   StringRef Name;
    161   ArrayRef<uint8_t> Bytes;
    162   BinaryAnnotationsOpCode OpCode = BinaryAnnotationsOpCode::Invalid;
    163   uint32_t U1 = 0;
    164   uint32_t U2 = 0;
    165   int32_t S1 = 0;
    166 };
    167 
    168 struct BinaryAnnotationIterator
    169     : public iterator_facade_base<BinaryAnnotationIterator,
    170                                   std::forward_iterator_tag,
    171                                   DecodedAnnotation> {
    172   BinaryAnnotationIterator() = default;
    173   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
    174   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
    175       : Data(Other.Data) {}
    176 
    177   bool operator==(BinaryAnnotationIterator Other) const {
    178     return Data == Other.Data;
    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   const DecodedAnnotation &operator*() {
    198     ParseCurrentAnnotation();
    199     return Current.getValue();
    200   }
    201 
    202 private:
    203   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
    204     if (Annotations.empty())
    205       return -1;
    206 
    207     uint8_t FirstByte = Annotations.front();
    208     Annotations = Annotations.drop_front();
    209 
    210     if ((FirstByte & 0x80) == 0x00)
    211       return FirstByte;
    212 
    213     if (Annotations.empty())
    214       return -1;
    215 
    216     uint8_t SecondByte = Annotations.front();
    217     Annotations = Annotations.drop_front();
    218 
    219     if ((FirstByte & 0xC0) == 0x80)
    220       return ((FirstByte & 0x3F) << 8) | SecondByte;
    221 
    222     if (Annotations.empty())
    223       return -1;
    224 
    225     uint8_t ThirdByte = Annotations.front();
    226     Annotations = Annotations.drop_front();
    227 
    228     if (Annotations.empty())
    229       return -1;
    230 
    231     uint8_t FourthByte = Annotations.front();
    232     Annotations = Annotations.drop_front();
    233 
    234     if ((FirstByte & 0xE0) == 0xC0)
    235       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
    236              (ThirdByte << 8) | FourthByte;
    237 
    238     return -1;
    239   }
    240 
    241   static int32_t DecodeSignedOperand(uint32_t Operand) {
    242     if (Operand & 1)
    243       return -(Operand >> 1);
    244     return Operand >> 1;
    245   }
    246 
    247   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
    248     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
    249   }
    250 
    251   bool ParseCurrentAnnotation() {
    252     if (Current.hasValue())
    253       return true;
    254 
    255     Next = Data;
    256     uint32_t Op = GetCompressedAnnotation(Next);
    257     DecodedAnnotation Result;
    258     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
    259     switch (Result.OpCode) {
    260     case BinaryAnnotationsOpCode::Invalid:
    261       Result.Name = "Invalid";
    262       Next = ArrayRef<uint8_t>();
    263       break;
    264     case BinaryAnnotationsOpCode::CodeOffset:
    265       Result.Name = "CodeOffset";
    266       Result.U1 = GetCompressedAnnotation(Next);
    267       break;
    268     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
    269       Result.Name = "ChangeCodeOffsetBase";
    270       Result.U1 = GetCompressedAnnotation(Next);
    271       break;
    272     case BinaryAnnotationsOpCode::ChangeCodeOffset:
    273       Result.Name = "ChangeCodeOffset";
    274       Result.U1 = GetCompressedAnnotation(Next);
    275       break;
    276     case BinaryAnnotationsOpCode::ChangeCodeLength:
    277       Result.Name = "ChangeCodeLength";
    278       Result.U1 = GetCompressedAnnotation(Next);
    279       break;
    280     case BinaryAnnotationsOpCode::ChangeFile:
    281       Result.Name = "ChangeFile";
    282       Result.U1 = GetCompressedAnnotation(Next);
    283       break;
    284     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
    285       Result.Name = "ChangeLineEndDelta";
    286       Result.U1 = GetCompressedAnnotation(Next);
    287       break;
    288     case BinaryAnnotationsOpCode::ChangeRangeKind:
    289       Result.Name = "ChangeRangeKind";
    290       Result.U1 = GetCompressedAnnotation(Next);
    291       break;
    292     case BinaryAnnotationsOpCode::ChangeColumnStart:
    293       Result.Name = "ChangeColumnStart";
    294       Result.U1 = GetCompressedAnnotation(Next);
    295       break;
    296     case BinaryAnnotationsOpCode::ChangeColumnEnd:
    297       Result.Name = "ChangeColumnEnd";
    298       Result.U1 = GetCompressedAnnotation(Next);
    299       break;
    300     case BinaryAnnotationsOpCode::ChangeLineOffset:
    301       Result.Name = "ChangeLineOffset";
    302       Result.S1 = DecodeSignedOperand(Next);
    303       break;
    304     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
    305       Result.Name = "ChangeColumnEndDelta";
    306       Result.S1 = DecodeSignedOperand(Next);
    307       break;
    308     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
    309       Result.Name = "ChangeCodeOffsetAndLineOffset";
    310       uint32_t Annotation = GetCompressedAnnotation(Next);
    311       Result.S1 = DecodeSignedOperand(Annotation >> 4);
    312       Result.U1 = Annotation & 0xf;
    313       break;
    314     }
    315     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
    316       Result.Name = "ChangeCodeLengthAndCodeOffset";
    317       Result.U1 = GetCompressedAnnotation(Next);
    318       Result.U2 = GetCompressedAnnotation(Next);
    319       break;
    320     }
    321     }
    322     Result.Bytes = Data.take_front(Data.size() - Next.size());
    323     Current = Result;
    324     return true;
    325   }
    326 
    327   Optional<DecodedAnnotation> Current;
    328   ArrayRef<uint8_t> Data;
    329   ArrayRef<uint8_t> Next;
    330 };
    331 
    332 // S_INLINESITE
    333 class InlineSiteSym : public SymbolRecord {
    334 public:
    335   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    336   explicit InlineSiteSym(uint32_t RecordOffset)
    337       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
    338         RecordOffset(RecordOffset) {}
    339 
    340   iterator_range<BinaryAnnotationIterator> annotations() const {
    341     return make_range(BinaryAnnotationIterator(AnnotationData),
    342                       BinaryAnnotationIterator());
    343   }
    344 
    345   uint32_t Parent = 0;
    346   uint32_t End = 0;
    347   TypeIndex Inlinee;
    348   std::vector<uint8_t> AnnotationData;
    349 
    350   uint32_t RecordOffset = 0;
    351 };
    352 
    353 struct PublicSym32Header {
    354   ulittle32_t Flags;
    355   ulittle32_t Offset;
    356   ulittle16_t Segment;
    357   // char Name[];
    358 };
    359 
    360 // S_PUB32
    361 class PublicSym32 : public SymbolRecord {
    362 public:
    363   PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
    364   explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    365   explicit PublicSym32(uint32_t RecordOffset)
    366       : SymbolRecord(SymbolRecordKind::PublicSym32),
    367         RecordOffset(RecordOffset) {}
    368 
    369   PublicSymFlags Flags = PublicSymFlags::None;
    370   uint32_t Offset = 0;
    371   uint16_t Segment = 0;
    372   StringRef Name;
    373 
    374   uint32_t RecordOffset = 0;
    375 };
    376 
    377 // S_REGISTER
    378 class RegisterSym : public SymbolRecord {
    379 public:
    380   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    381   explicit RegisterSym(uint32_t RecordOffset)
    382       : SymbolRecord(SymbolRecordKind::RegisterSym),
    383         RecordOffset(RecordOffset) {}
    384 
    385   TypeIndex Index;
    386   RegisterId Register;
    387   StringRef Name;
    388 
    389   uint32_t RecordOffset = 0;
    390 };
    391 
    392 // S_PROCREF, S_LPROCREF
    393 class ProcRefSym : public SymbolRecord {
    394 public:
    395   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    396   explicit ProcRefSym(uint32_t RecordOffset)
    397       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
    398   }
    399 
    400   uint32_t SumName = 0;
    401   uint32_t SymOffset = 0;
    402   uint16_t Module = 0;
    403   StringRef Name;
    404 
    405   uint16_t modi() const { return Module - 1; }
    406   uint32_t RecordOffset = 0;
    407 };
    408 
    409 // S_LOCAL
    410 class LocalSym : public SymbolRecord {
    411 public:
    412   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    413   explicit LocalSym(uint32_t RecordOffset)
    414       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
    415 
    416   TypeIndex Type;
    417   LocalSymFlags Flags = LocalSymFlags::None;
    418   StringRef Name;
    419 
    420   uint32_t RecordOffset = 0;
    421 };
    422 
    423 struct LocalVariableAddrRange {
    424   uint32_t OffsetStart = 0;
    425   uint16_t ISectStart = 0;
    426   uint16_t Range = 0;
    427 };
    428 
    429 struct LocalVariableAddrGap {
    430   uint16_t GapStartOffset = 0;
    431   uint16_t Range = 0;
    432 };
    433 
    434 enum : uint16_t { MaxDefRange = 0xf000 };
    435 
    436 // S_DEFRANGE
    437 class DefRangeSym : public SymbolRecord {
    438   static constexpr uint32_t RelocationOffset = 8;
    439 
    440 public:
    441   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    442   explicit DefRangeSym(uint32_t RecordOffset)
    443       : SymbolRecord(SymbolRecordKind::DefRangeSym),
    444         RecordOffset(RecordOffset) {}
    445 
    446   uint32_t getRelocationOffset() const {
    447     return RecordOffset + RelocationOffset;
    448   }
    449 
    450   uint32_t Program = 0;
    451   LocalVariableAddrRange Range;
    452   std::vector<LocalVariableAddrGap> Gaps;
    453 
    454   uint32_t RecordOffset = 0;
    455 };
    456 
    457 // S_DEFRANGE_SUBFIELD
    458 class DefRangeSubfieldSym : public SymbolRecord {
    459   static constexpr uint32_t RelocationOffset = 12;
    460 
    461 public:
    462   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    463   explicit DefRangeSubfieldSym(uint32_t RecordOffset)
    464       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
    465         RecordOffset(RecordOffset) {}
    466 
    467   uint32_t getRelocationOffset() const {
    468     return RecordOffset + RelocationOffset;
    469   }
    470 
    471   uint32_t Program = 0;
    472   uint16_t OffsetInParent = 0;
    473   LocalVariableAddrRange Range;
    474   std::vector<LocalVariableAddrGap> Gaps;
    475 
    476   uint32_t RecordOffset = 0;
    477 };
    478 
    479 struct DefRangeRegisterHeader {
    480   ulittle16_t Register;
    481   ulittle16_t MayHaveNoName;
    482 };
    483 
    484 // S_DEFRANGE_REGISTER
    485 class DefRangeRegisterSym : public SymbolRecord {
    486 public:
    487   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    488   explicit DefRangeRegisterSym(uint32_t RecordOffset)
    489       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
    490         RecordOffset(RecordOffset) {}
    491 
    492   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
    493 
    494   DefRangeRegisterHeader Hdr;
    495   LocalVariableAddrRange Range;
    496   std::vector<LocalVariableAddrGap> Gaps;
    497 
    498   uint32_t RecordOffset = 0;
    499 };
    500 
    501 struct DefRangeSubfieldRegisterHeader {
    502   ulittle16_t Register;
    503   ulittle16_t MayHaveNoName;
    504   ulittle32_t OffsetInParent;
    505 };
    506 
    507 // S_DEFRANGE_SUBFIELD_REGISTER
    508 class DefRangeSubfieldRegisterSym : public SymbolRecord {
    509 public:
    510   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
    511       : SymbolRecord(Kind) {}
    512   explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
    513       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
    514         RecordOffset(RecordOffset) {}
    515 
    516   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
    517 
    518   DefRangeSubfieldRegisterHeader Hdr;
    519   LocalVariableAddrRange Range;
    520   std::vector<LocalVariableAddrGap> Gaps;
    521 
    522   uint32_t RecordOffset = 0;
    523 };
    524 
    525 struct DefRangeFramePointerRelHeader {
    526   little32_t Offset;
    527 };
    528 
    529 // S_DEFRANGE_FRAMEPOINTER_REL
    530 class DefRangeFramePointerRelSym : public SymbolRecord {
    531   static constexpr uint32_t RelocationOffset = 8;
    532 
    533 public:
    534   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
    535       : SymbolRecord(Kind) {}
    536   explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
    537       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
    538         RecordOffset(RecordOffset) {}
    539 
    540   uint32_t getRelocationOffset() const {
    541     return RecordOffset + RelocationOffset;
    542   }
    543 
    544   DefRangeFramePointerRelHeader Hdr;
    545   LocalVariableAddrRange Range;
    546   std::vector<LocalVariableAddrGap> Gaps;
    547 
    548   uint32_t RecordOffset = 0;
    549 };
    550 
    551 struct DefRangeRegisterRelHeader {
    552   ulittle16_t Register;
    553   ulittle16_t Flags;
    554   little32_t BasePointerOffset;
    555 };
    556 
    557 // S_DEFRANGE_REGISTER_REL
    558 class DefRangeRegisterRelSym : public SymbolRecord {
    559 public:
    560   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    561   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
    562       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
    563         RecordOffset(RecordOffset) {}
    564 
    565   // The flags implement this notional bitfield:
    566   //   uint16_t IsSubfield : 1;
    567   //   uint16_t Padding : 3;
    568   //   uint16_t OffsetInParent : 12;
    569   enum : uint16_t {
    570     IsSubfieldFlag = 1,
    571     OffsetInParentShift = 4,
    572   };
    573 
    574   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
    575   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
    576 
    577   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
    578 
    579   DefRangeRegisterRelHeader Hdr;
    580   LocalVariableAddrRange Range;
    581   std::vector<LocalVariableAddrGap> Gaps;
    582 
    583   uint32_t RecordOffset = 0;
    584 };
    585 
    586 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
    587 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
    588 public:
    589   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
    590       : SymbolRecord(Kind) {}
    591   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
    592       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
    593         RecordOffset(RecordOffset) {}
    594 
    595   int32_t Offset = 0;
    596 
    597   uint32_t RecordOffset = 0;
    598 };
    599 
    600 // S_BLOCK32
    601 class BlockSym : public SymbolRecord {
    602   static constexpr uint32_t RelocationOffset = 16;
    603 
    604 public:
    605   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    606   explicit BlockSym(uint32_t RecordOffset)
    607       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
    608 
    609   uint32_t getRelocationOffset() const {
    610     return RecordOffset + RelocationOffset;
    611   }
    612 
    613   uint32_t Parent = 0;
    614   uint32_t End = 0;
    615   uint32_t CodeSize = 0;
    616   uint32_t CodeOffset = 0;
    617   uint16_t Segment = 0;
    618   StringRef Name;
    619 
    620   uint32_t RecordOffset = 0;
    621 };
    622 
    623 // S_LABEL32
    624 class LabelSym : public SymbolRecord {
    625   static constexpr uint32_t RelocationOffset = 4;
    626 
    627 public:
    628   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    629   explicit LabelSym(uint32_t RecordOffset)
    630       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
    631 
    632   uint32_t getRelocationOffset() const {
    633     return RecordOffset + RelocationOffset;
    634   }
    635 
    636   uint32_t CodeOffset = 0;
    637   uint16_t Segment = 0;
    638   ProcSymFlags Flags = ProcSymFlags::None;
    639   StringRef Name;
    640 
    641   uint32_t RecordOffset = 0;
    642 };
    643 
    644 // S_OBJNAME
    645 class ObjNameSym : public SymbolRecord {
    646 public:
    647   explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
    648   explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    649   explicit ObjNameSym(uint32_t RecordOffset)
    650       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
    651   }
    652 
    653   uint32_t Signature = 0;
    654   StringRef Name;
    655 
    656   uint32_t RecordOffset = 0;
    657 };
    658 
    659 // S_ENVBLOCK
    660 class EnvBlockSym : public SymbolRecord {
    661 public:
    662   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    663   explicit EnvBlockSym(uint32_t RecordOffset)
    664       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
    665         RecordOffset(RecordOffset) {}
    666 
    667   std::vector<StringRef> Fields;
    668 
    669   uint32_t RecordOffset = 0;
    670 };
    671 
    672 // S_EXPORT
    673 class ExportSym : public SymbolRecord {
    674 public:
    675   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    676   explicit ExportSym(uint32_t RecordOffset)
    677       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
    678 
    679   uint16_t Ordinal = 0;
    680   ExportFlags Flags = ExportFlags::None;
    681   StringRef Name;
    682 
    683   uint32_t RecordOffset = 0;
    684 };
    685 
    686 // S_FILESTATIC
    687 class FileStaticSym : public SymbolRecord {
    688 public:
    689   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    690   explicit FileStaticSym(uint32_t RecordOffset)
    691       : SymbolRecord(SymbolRecordKind::FileStaticSym),
    692         RecordOffset(RecordOffset) {}
    693 
    694   TypeIndex Index;
    695   uint32_t ModFilenameOffset = 0;
    696   LocalSymFlags Flags = LocalSymFlags::None;
    697   StringRef Name;
    698 
    699   uint32_t RecordOffset = 0;
    700 };
    701 
    702 // S_COMPILE2
    703 class Compile2Sym : public SymbolRecord {
    704 public:
    705   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    706   explicit Compile2Sym(uint32_t RecordOffset)
    707       : SymbolRecord(SymbolRecordKind::Compile2Sym),
    708         RecordOffset(RecordOffset) {}
    709 
    710   CompileSym2Flags Flags = CompileSym2Flags::None;
    711   CPUType Machine;
    712   uint16_t VersionFrontendMajor = 0;
    713   uint16_t VersionFrontendMinor = 0;
    714   uint16_t VersionFrontendBuild = 0;
    715   uint16_t VersionBackendMajor = 0;
    716   uint16_t VersionBackendMinor = 0;
    717   uint16_t VersionBackendBuild = 0;
    718   StringRef Version;
    719   std::vector<StringRef> ExtraStrings;
    720 
    721   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
    722   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
    723 
    724   uint32_t RecordOffset = 0;
    725 };
    726 
    727 // S_COMPILE3
    728 class Compile3Sym : public SymbolRecord {
    729 public:
    730   Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
    731   explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    732   explicit Compile3Sym(uint32_t RecordOffset)
    733       : SymbolRecord(SymbolRecordKind::Compile3Sym),
    734         RecordOffset(RecordOffset) {}
    735 
    736   CompileSym3Flags Flags = CompileSym3Flags::None;
    737   CPUType Machine;
    738   uint16_t VersionFrontendMajor = 0;
    739   uint16_t VersionFrontendMinor = 0;
    740   uint16_t VersionFrontendBuild = 0;
    741   uint16_t VersionFrontendQFE = 0;
    742   uint16_t VersionBackendMajor = 0;
    743   uint16_t VersionBackendMinor = 0;
    744   uint16_t VersionBackendBuild = 0;
    745   uint16_t VersionBackendQFE = 0;
    746   StringRef Version;
    747 
    748   void setLanguage(SourceLanguage Lang) {
    749     Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
    750   }
    751 
    752   SourceLanguage getLanguage() const {
    753     return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
    754   }
    755   CompileSym3Flags getFlags() const {
    756     return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
    757   }
    758 
    759   bool hasOptimizations() const {
    760     return CompileSym3Flags::None !=
    761            (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
    762   }
    763 
    764   uint32_t RecordOffset = 0;
    765 };
    766 
    767 // S_FRAMEPROC
    768 class FrameProcSym : public SymbolRecord {
    769 public:
    770   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    771   explicit FrameProcSym(uint32_t RecordOffset)
    772       : SymbolRecord(SymbolRecordKind::FrameProcSym),
    773         RecordOffset(RecordOffset) {}
    774 
    775   uint32_t TotalFrameBytes = 0;
    776   uint32_t PaddingFrameBytes = 0;
    777   uint32_t OffsetToPadding = 0;
    778   uint32_t BytesOfCalleeSavedRegisters = 0;
    779   uint32_t OffsetOfExceptionHandler = 0;
    780   uint16_t SectionIdOfExceptionHandler = 0;
    781   FrameProcedureOptions Flags = FrameProcedureOptions::None;
    782 
    783   /// Extract the register this frame uses to refer to local variables.
    784   RegisterId getLocalFramePtrReg(CPUType CPU) const {
    785     return decodeFramePtrReg(
    786         EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
    787   }
    788 
    789   /// Extract the register this frame uses to refer to parameters.
    790   RegisterId getParamFramePtrReg(CPUType CPU) const {
    791     return decodeFramePtrReg(
    792         EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
    793   }
    794 
    795   uint32_t RecordOffset = 0;
    796 
    797 private:
    798 };
    799 
    800 // S_CALLSITEINFO
    801 class CallSiteInfoSym : public SymbolRecord {
    802   static constexpr uint32_t RelocationOffset = 4;
    803 
    804 public:
    805   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    806   explicit CallSiteInfoSym(uint32_t RecordOffset)
    807       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
    808 
    809   uint32_t getRelocationOffset() const {
    810     return RecordOffset + RelocationOffset;
    811   }
    812 
    813   uint32_t CodeOffset = 0;
    814   uint16_t Segment = 0;
    815   TypeIndex Type;
    816 
    817   uint32_t RecordOffset = 0;
    818 };
    819 
    820 // S_HEAPALLOCSITE
    821 class HeapAllocationSiteSym : public SymbolRecord {
    822   static constexpr uint32_t RelocationOffset = 4;
    823 
    824 public:
    825   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    826   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
    827       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
    828         RecordOffset(RecordOffset) {}
    829 
    830   uint32_t getRelocationOffset() const {
    831     return RecordOffset + RelocationOffset;
    832   }
    833 
    834   uint32_t CodeOffset = 0;
    835   uint16_t Segment = 0;
    836   uint16_t CallInstructionSize = 0;
    837   TypeIndex Type;
    838 
    839   uint32_t RecordOffset = 0;
    840 };
    841 
    842 // S_FRAMECOOKIE
    843 class FrameCookieSym : public SymbolRecord {
    844   static constexpr uint32_t RelocationOffset = 4;
    845 
    846 public:
    847   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    848   explicit FrameCookieSym(uint32_t RecordOffset)
    849       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
    850 
    851   uint32_t getRelocationOffset() const {
    852     return RecordOffset + RelocationOffset;
    853   }
    854 
    855   uint32_t CodeOffset = 0;
    856   uint16_t Register = 0;
    857   FrameCookieKind CookieKind;
    858   uint8_t Flags = 0;
    859 
    860   uint32_t RecordOffset = 0;
    861 };
    862 
    863 // S_UDT, S_COBOLUDT
    864 class UDTSym : public SymbolRecord {
    865 public:
    866   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    867   explicit UDTSym(uint32_t RecordOffset)
    868       : SymbolRecord(SymbolRecordKind::UDTSym) {}
    869 
    870   TypeIndex Type;
    871   StringRef Name;
    872 
    873   uint32_t RecordOffset = 0;
    874 };
    875 
    876 // S_BUILDINFO
    877 class BuildInfoSym : public SymbolRecord {
    878 public:
    879   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    880   explicit BuildInfoSym(uint32_t RecordOffset)
    881       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
    882         RecordOffset(RecordOffset) {}
    883 
    884   TypeIndex BuildId;
    885 
    886   uint32_t RecordOffset = 0;
    887 };
    888 
    889 // S_BPREL32
    890 class BPRelativeSym : public SymbolRecord {
    891 public:
    892   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    893   explicit BPRelativeSym(uint32_t RecordOffset)
    894       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
    895         RecordOffset(RecordOffset) {}
    896 
    897   int32_t Offset = 0;
    898   TypeIndex Type;
    899   StringRef Name;
    900 
    901   uint32_t RecordOffset = 0;
    902 };
    903 
    904 // S_REGREL32
    905 class RegRelativeSym : public SymbolRecord {
    906 public:
    907   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    908   explicit RegRelativeSym(uint32_t RecordOffset)
    909       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
    910         RecordOffset(RecordOffset) {}
    911 
    912   uint32_t Offset = 0;
    913   TypeIndex Type;
    914   RegisterId Register;
    915   StringRef Name;
    916 
    917   uint32_t RecordOffset = 0;
    918 };
    919 
    920 // S_CONSTANT, S_MANCONSTANT
    921 class ConstantSym : public SymbolRecord {
    922 public:
    923   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    924   explicit ConstantSym(uint32_t RecordOffset)
    925       : SymbolRecord(SymbolRecordKind::ConstantSym),
    926         RecordOffset(RecordOffset) {}
    927 
    928   TypeIndex Type;
    929   APSInt Value;
    930   StringRef Name;
    931 
    932   uint32_t RecordOffset = 0;
    933 };
    934 
    935 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
    936 class DataSym : public SymbolRecord {
    937   static constexpr uint32_t RelocationOffset = 8;
    938 
    939 public:
    940   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    941   explicit DataSym(uint32_t RecordOffset)
    942       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
    943 
    944   uint32_t getRelocationOffset() const {
    945     return RecordOffset + RelocationOffset;
    946   }
    947 
    948   TypeIndex Type;
    949   uint32_t DataOffset = 0;
    950   uint16_t Segment = 0;
    951   StringRef Name;
    952 
    953   uint32_t RecordOffset = 0;
    954 };
    955 
    956 // S_LTHREAD32, S_GTHREAD32
    957 class ThreadLocalDataSym : public SymbolRecord {
    958   static constexpr uint32_t RelocationOffset = 8;
    959 
    960 public:
    961   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    962   explicit ThreadLocalDataSym(uint32_t RecordOffset)
    963       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
    964         RecordOffset(RecordOffset) {}
    965 
    966   uint32_t getRelocationOffset() const {
    967     return RecordOffset + RelocationOffset;
    968   }
    969 
    970   TypeIndex Type;
    971   uint32_t DataOffset = 0;
    972   uint16_t Segment = 0;
    973   StringRef Name;
    974 
    975   uint32_t RecordOffset = 0;
    976 };
    977 
    978 // S_UNAMESPACE
    979 class UsingNamespaceSym : public SymbolRecord {
    980 public:
    981   explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    982   explicit UsingNamespaceSym(uint32_t RecordOffset)
    983       : SymbolRecord(SymbolRecordKind::UsingNamespaceSym),
    984         RecordOffset(RecordOffset) {}
    985 
    986   StringRef Name;
    987 
    988   uint32_t RecordOffset = 0;
    989 };
    990 
    991 // S_ANNOTATION
    992 class AnnotationSym : public SymbolRecord {
    993 public:
    994   explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
    995   explicit AnnotationSym(uint32_t RecordOffset)
    996       : SymbolRecord(SymbolRecordKind::AnnotationSym),
    997         RecordOffset(RecordOffset) {}
    998 
    999   uint32_t CodeOffset = 0;
   1000   uint16_t Segment = 0;
   1001   std::vector<StringRef> Strings;
   1002 
   1003   uint32_t RecordOffset = 0;
   1004 };
   1005 
   1006 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
   1007                                         uint32_t Offset);
   1008 
   1009 } // end namespace codeview
   1010 } // end namespace llvm
   1011 
   1012 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
   1013