Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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