Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:40

0001 //===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
0010 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
0011 
0012 #include "llvm/ADT/APSInt.h"
0013 #include "llvm/ADT/ArrayRef.h"
0014 #include "llvm/ADT/StringRef.h"
0015 #include "llvm/ADT/iterator.h"
0016 #include "llvm/ADT/iterator_range.h"
0017 #include "llvm/DebugInfo/CodeView/CVRecord.h"
0018 #include "llvm/DebugInfo/CodeView/CodeView.h"
0019 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
0020 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
0021 #include "llvm/Support/BinaryStreamArray.h"
0022 #include "llvm/Support/Endian.h"
0023 #include <cstdint>
0024 #include <vector>
0025 
0026 namespace llvm {
0027 namespace codeview {
0028 
0029 class SymbolRecord {
0030 protected:
0031   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
0032 
0033 public:
0034   SymbolRecordKind getKind() const { return Kind; }
0035 
0036   SymbolRecordKind Kind;
0037 };
0038 
0039 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
0040 // S_LPROC32_DPC_ID
0041 class ProcSym : public SymbolRecord {
0042   static constexpr uint32_t RelocationOffset = 32;
0043 
0044 public:
0045   explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0046   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0047       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0048 
0049   uint32_t getRelocationOffset() const {
0050     return RecordOffset + RelocationOffset;
0051   }
0052 
0053   uint32_t Parent = 0;
0054   uint32_t End = 0;
0055   uint32_t Next = 0;
0056   uint32_t CodeSize = 0;
0057   uint32_t DbgStart = 0;
0058   uint32_t DbgEnd = 0;
0059   TypeIndex FunctionType;
0060   uint32_t CodeOffset = 0;
0061   uint16_t Segment = 0;
0062   ProcSymFlags Flags = ProcSymFlags::None;
0063   StringRef Name;
0064 
0065   uint32_t RecordOffset = 0;
0066 };
0067 
0068 // S_THUNK32
0069 class Thunk32Sym : public SymbolRecord {
0070 public:
0071   explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0072   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
0073       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0074 
0075   uint32_t Parent = 0;
0076   uint32_t End = 0;
0077   uint32_t Next = 0;
0078   uint32_t Offset = 0;
0079   uint16_t Segment = 0;
0080   uint16_t Length = 0;
0081   ThunkOrdinal Thunk = ThunkOrdinal::Standard;
0082   StringRef Name;
0083   ArrayRef<uint8_t> VariantData;
0084 
0085   uint32_t RecordOffset = 0;
0086 };
0087 
0088 // S_TRAMPOLINE
0089 class TrampolineSym : public SymbolRecord {
0090 public:
0091   explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0092   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0093       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0094 
0095   TrampolineType Type;
0096   uint16_t Size = 0;
0097   uint32_t ThunkOffset = 0;
0098   uint32_t TargetOffset = 0;
0099   uint16_t ThunkSection = 0;
0100   uint16_t TargetSection = 0;
0101 
0102   uint32_t RecordOffset = 0;
0103 };
0104 
0105 // S_SECTION
0106 class SectionSym : public SymbolRecord {
0107 public:
0108   explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0109   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0110       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0111 
0112   uint16_t SectionNumber = 0;
0113   uint8_t Alignment = 0;
0114   uint32_t Rva = 0;
0115   uint32_t Length = 0;
0116   uint32_t Characteristics = 0;
0117   StringRef Name;
0118 
0119   uint32_t RecordOffset = 0;
0120 };
0121 
0122 // S_COFFGROUP
0123 class CoffGroupSym : public SymbolRecord {
0124 public:
0125   explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0126   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0127       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0128 
0129   uint32_t Size = 0;
0130   uint32_t Characteristics = 0;
0131   uint32_t Offset = 0;
0132   uint16_t Segment = 0;
0133   StringRef Name;
0134 
0135   uint32_t RecordOffset = 0;
0136 };
0137 
0138 class ScopeEndSym : public SymbolRecord {
0139 public:
0140   explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0141   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0142       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0143 
0144   uint32_t RecordOffset = 0;
0145 };
0146 
0147 class JumpTableSym : public SymbolRecord {
0148 public:
0149   explicit JumpTableSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0150   JumpTableSym(uint32_t RecordOffset)
0151       : SymbolRecord(SymbolRecordKind::JumpTableSym),
0152         RecordOffset(RecordOffset) {}
0153 
0154   uint32_t BaseOffset = 0;
0155   uint16_t BaseSegment = 0;
0156 
0157   JumpTableEntrySize SwitchType;
0158   uint32_t BranchOffset = 0;
0159   uint32_t TableOffset = 0;
0160   uint16_t BranchSegment = 0;
0161   uint16_t TableSegment = 0;
0162 
0163   uint32_t EntriesCount = 0;
0164 
0165   uint32_t RecordOffset = 0;
0166 };
0167 
0168 class CallerSym : public SymbolRecord {
0169 public:
0170   explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0171   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
0172       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
0173 
0174   std::vector<TypeIndex> Indices;
0175 
0176   uint32_t RecordOffset = 0;
0177 };
0178 
0179 struct DecodedAnnotation {
0180   StringRef Name;
0181   ArrayRef<uint8_t> Bytes;
0182   BinaryAnnotationsOpCode OpCode = BinaryAnnotationsOpCode::Invalid;
0183   uint32_t U1 = 0;
0184   uint32_t U2 = 0;
0185   int32_t S1 = 0;
0186 };
0187 
0188 struct BinaryAnnotationIterator
0189     : public iterator_facade_base<BinaryAnnotationIterator,
0190                                   std::forward_iterator_tag,
0191                                   DecodedAnnotation> {
0192   BinaryAnnotationIterator() = default;
0193   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
0194   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
0195       : Data(Other.Data) {}
0196 
0197   bool operator==(BinaryAnnotationIterator Other) const {
0198     return Data == Other.Data;
0199   }
0200 
0201   BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
0202     Data = Other.Data;
0203     return *this;
0204   }
0205 
0206   BinaryAnnotationIterator &operator++() {
0207     if (!ParseCurrentAnnotation()) {
0208       *this = BinaryAnnotationIterator();
0209       return *this;
0210     }
0211     Data = Next;
0212     Next = ArrayRef<uint8_t>();
0213     Current.reset();
0214     return *this;
0215   }
0216 
0217   const DecodedAnnotation &operator*() {
0218     ParseCurrentAnnotation();
0219     return *Current;
0220   }
0221 
0222 private:
0223   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
0224     if (Annotations.empty())
0225       return -1;
0226 
0227     uint8_t FirstByte = Annotations.front();
0228     Annotations = Annotations.drop_front();
0229 
0230     if ((FirstByte & 0x80) == 0x00)
0231       return FirstByte;
0232 
0233     if (Annotations.empty())
0234       return -1;
0235 
0236     uint8_t SecondByte = Annotations.front();
0237     Annotations = Annotations.drop_front();
0238 
0239     if ((FirstByte & 0xC0) == 0x80)
0240       return ((FirstByte & 0x3F) << 8) | SecondByte;
0241 
0242     if (Annotations.empty())
0243       return -1;
0244 
0245     uint8_t ThirdByte = Annotations.front();
0246     Annotations = Annotations.drop_front();
0247 
0248     if (Annotations.empty())
0249       return -1;
0250 
0251     uint8_t FourthByte = Annotations.front();
0252     Annotations = Annotations.drop_front();
0253 
0254     if ((FirstByte & 0xE0) == 0xC0)
0255       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
0256              (ThirdByte << 8) | FourthByte;
0257 
0258     return -1;
0259   }
0260 
0261   static int32_t DecodeSignedOperand(uint32_t Operand) {
0262     if (Operand & 1)
0263       return -(Operand >> 1);
0264     return Operand >> 1;
0265   }
0266 
0267   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
0268     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
0269   }
0270 
0271   bool ParseCurrentAnnotation() {
0272     if (Current)
0273       return true;
0274 
0275     Next = Data;
0276     uint32_t Op = GetCompressedAnnotation(Next);
0277     DecodedAnnotation Result;
0278     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
0279     switch (Result.OpCode) {
0280     case BinaryAnnotationsOpCode::Invalid:
0281       Result.Name = "Invalid";
0282       Next = ArrayRef<uint8_t>();
0283       break;
0284     case BinaryAnnotationsOpCode::CodeOffset:
0285       Result.Name = "CodeOffset";
0286       Result.U1 = GetCompressedAnnotation(Next);
0287       break;
0288     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
0289       Result.Name = "ChangeCodeOffsetBase";
0290       Result.U1 = GetCompressedAnnotation(Next);
0291       break;
0292     case BinaryAnnotationsOpCode::ChangeCodeOffset:
0293       Result.Name = "ChangeCodeOffset";
0294       Result.U1 = GetCompressedAnnotation(Next);
0295       break;
0296     case BinaryAnnotationsOpCode::ChangeCodeLength:
0297       Result.Name = "ChangeCodeLength";
0298       Result.U1 = GetCompressedAnnotation(Next);
0299       break;
0300     case BinaryAnnotationsOpCode::ChangeFile:
0301       Result.Name = "ChangeFile";
0302       Result.U1 = GetCompressedAnnotation(Next);
0303       break;
0304     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
0305       Result.Name = "ChangeLineEndDelta";
0306       Result.U1 = GetCompressedAnnotation(Next);
0307       break;
0308     case BinaryAnnotationsOpCode::ChangeRangeKind:
0309       Result.Name = "ChangeRangeKind";
0310       Result.U1 = GetCompressedAnnotation(Next);
0311       break;
0312     case BinaryAnnotationsOpCode::ChangeColumnStart:
0313       Result.Name = "ChangeColumnStart";
0314       Result.U1 = GetCompressedAnnotation(Next);
0315       break;
0316     case BinaryAnnotationsOpCode::ChangeColumnEnd:
0317       Result.Name = "ChangeColumnEnd";
0318       Result.U1 = GetCompressedAnnotation(Next);
0319       break;
0320     case BinaryAnnotationsOpCode::ChangeLineOffset:
0321       Result.Name = "ChangeLineOffset";
0322       Result.S1 = DecodeSignedOperand(Next);
0323       break;
0324     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
0325       Result.Name = "ChangeColumnEndDelta";
0326       Result.S1 = DecodeSignedOperand(Next);
0327       break;
0328     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
0329       Result.Name = "ChangeCodeOffsetAndLineOffset";
0330       uint32_t Annotation = GetCompressedAnnotation(Next);
0331       Result.S1 = DecodeSignedOperand(Annotation >> 4);
0332       Result.U1 = Annotation & 0xf;
0333       break;
0334     }
0335     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
0336       Result.Name = "ChangeCodeLengthAndCodeOffset";
0337       Result.U1 = GetCompressedAnnotation(Next);
0338       Result.U2 = GetCompressedAnnotation(Next);
0339       break;
0340     }
0341     }
0342     Result.Bytes = Data.take_front(Data.size() - Next.size());
0343     Current = Result;
0344     return true;
0345   }
0346 
0347   std::optional<DecodedAnnotation> Current;
0348   ArrayRef<uint8_t> Data;
0349   ArrayRef<uint8_t> Next;
0350 };
0351 
0352 // S_INLINESITE
0353 class InlineSiteSym : public SymbolRecord {
0354 public:
0355   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0356   explicit InlineSiteSym(uint32_t RecordOffset)
0357       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
0358         RecordOffset(RecordOffset) {}
0359 
0360   iterator_range<BinaryAnnotationIterator> annotations() const {
0361     return make_range(BinaryAnnotationIterator(AnnotationData),
0362                       BinaryAnnotationIterator());
0363   }
0364 
0365   uint32_t Parent = 0;
0366   uint32_t End = 0;
0367   TypeIndex Inlinee;
0368   std::vector<uint8_t> AnnotationData;
0369 
0370   uint32_t RecordOffset = 0;
0371 };
0372 
0373 struct PublicSym32Header {
0374   ulittle32_t Flags;
0375   ulittle32_t Offset;
0376   ulittle16_t Segment;
0377   // char Name[];
0378 };
0379 
0380 // S_PUB32
0381 class PublicSym32 : public SymbolRecord {
0382 public:
0383   PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
0384   explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0385   explicit PublicSym32(uint32_t RecordOffset)
0386       : SymbolRecord(SymbolRecordKind::PublicSym32),
0387         RecordOffset(RecordOffset) {}
0388 
0389   PublicSymFlags Flags = PublicSymFlags::None;
0390   uint32_t Offset = 0;
0391   uint16_t Segment = 0;
0392   StringRef Name;
0393 
0394   uint32_t RecordOffset = 0;
0395 };
0396 
0397 // S_REGISTER
0398 class RegisterSym : public SymbolRecord {
0399 public:
0400   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0401   explicit RegisterSym(uint32_t RecordOffset)
0402       : SymbolRecord(SymbolRecordKind::RegisterSym),
0403         RecordOffset(RecordOffset) {}
0404 
0405   TypeIndex Index;
0406   RegisterId Register;
0407   StringRef Name;
0408 
0409   uint32_t RecordOffset = 0;
0410 };
0411 
0412 // S_PROCREF, S_LPROCREF
0413 class ProcRefSym : public SymbolRecord {
0414 public:
0415   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0416   explicit ProcRefSym(uint32_t RecordOffset)
0417       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
0418   }
0419 
0420   uint32_t SumName = 0;
0421   uint32_t SymOffset = 0;
0422   uint16_t Module = 0;
0423   StringRef Name;
0424 
0425   uint16_t modi() const { return Module - 1; }
0426   uint32_t RecordOffset = 0;
0427 };
0428 
0429 // S_LOCAL
0430 class LocalSym : public SymbolRecord {
0431 public:
0432   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0433   explicit LocalSym(uint32_t RecordOffset)
0434       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
0435 
0436   TypeIndex Type;
0437   LocalSymFlags Flags = LocalSymFlags::None;
0438   StringRef Name;
0439 
0440   uint32_t RecordOffset = 0;
0441 };
0442 
0443 struct LocalVariableAddrRange {
0444   uint32_t OffsetStart = 0;
0445   uint16_t ISectStart = 0;
0446   uint16_t Range = 0;
0447 };
0448 
0449 struct LocalVariableAddrGap {
0450   uint16_t GapStartOffset = 0;
0451   uint16_t Range = 0;
0452 };
0453 
0454 enum : uint16_t { MaxDefRange = 0xf000 };
0455 
0456 // S_DEFRANGE
0457 class DefRangeSym : public SymbolRecord {
0458   static constexpr uint32_t RelocationOffset = 8;
0459 
0460 public:
0461   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0462   explicit DefRangeSym(uint32_t RecordOffset)
0463       : SymbolRecord(SymbolRecordKind::DefRangeSym),
0464         RecordOffset(RecordOffset) {}
0465 
0466   uint32_t getRelocationOffset() const {
0467     return RecordOffset + RelocationOffset;
0468   }
0469 
0470   uint32_t Program = 0;
0471   LocalVariableAddrRange Range;
0472   std::vector<LocalVariableAddrGap> Gaps;
0473 
0474   uint32_t RecordOffset = 0;
0475 };
0476 
0477 // S_DEFRANGE_SUBFIELD
0478 class DefRangeSubfieldSym : public SymbolRecord {
0479   static constexpr uint32_t RelocationOffset = 12;
0480 
0481 public:
0482   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0483   explicit DefRangeSubfieldSym(uint32_t RecordOffset)
0484       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
0485         RecordOffset(RecordOffset) {}
0486 
0487   uint32_t getRelocationOffset() const {
0488     return RecordOffset + RelocationOffset;
0489   }
0490 
0491   uint32_t Program = 0;
0492   uint16_t OffsetInParent = 0;
0493   LocalVariableAddrRange Range;
0494   std::vector<LocalVariableAddrGap> Gaps;
0495 
0496   uint32_t RecordOffset = 0;
0497 };
0498 
0499 struct DefRangeRegisterHeader {
0500   ulittle16_t Register;
0501   ulittle16_t MayHaveNoName;
0502 };
0503 
0504 // S_DEFRANGE_REGISTER
0505 class DefRangeRegisterSym : public SymbolRecord {
0506 public:
0507   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0508   explicit DefRangeRegisterSym(uint32_t RecordOffset)
0509       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
0510         RecordOffset(RecordOffset) {}
0511 
0512   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
0513 
0514   DefRangeRegisterHeader Hdr;
0515   LocalVariableAddrRange Range;
0516   std::vector<LocalVariableAddrGap> Gaps;
0517 
0518   uint32_t RecordOffset = 0;
0519 };
0520 
0521 struct DefRangeSubfieldRegisterHeader {
0522   ulittle16_t Register;
0523   ulittle16_t MayHaveNoName;
0524   ulittle32_t OffsetInParent;
0525 };
0526 
0527 // S_DEFRANGE_SUBFIELD_REGISTER
0528 class DefRangeSubfieldRegisterSym : public SymbolRecord {
0529 public:
0530   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
0531       : SymbolRecord(Kind) {}
0532   explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
0533       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
0534         RecordOffset(RecordOffset) {}
0535 
0536   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
0537 
0538   DefRangeSubfieldRegisterHeader Hdr;
0539   LocalVariableAddrRange Range;
0540   std::vector<LocalVariableAddrGap> Gaps;
0541 
0542   uint32_t RecordOffset = 0;
0543 };
0544 
0545 struct DefRangeFramePointerRelHeader {
0546   little32_t Offset;
0547 };
0548 
0549 // S_DEFRANGE_FRAMEPOINTER_REL
0550 class DefRangeFramePointerRelSym : public SymbolRecord {
0551   static constexpr uint32_t RelocationOffset = 8;
0552 
0553 public:
0554   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
0555       : SymbolRecord(Kind) {}
0556   explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
0557       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
0558         RecordOffset(RecordOffset) {}
0559 
0560   uint32_t getRelocationOffset() const {
0561     return RecordOffset + RelocationOffset;
0562   }
0563 
0564   DefRangeFramePointerRelHeader Hdr;
0565   LocalVariableAddrRange Range;
0566   std::vector<LocalVariableAddrGap> Gaps;
0567 
0568   uint32_t RecordOffset = 0;
0569 };
0570 
0571 struct DefRangeRegisterRelHeader {
0572   ulittle16_t Register;
0573   ulittle16_t Flags;
0574   little32_t BasePointerOffset;
0575 };
0576 
0577 // S_DEFRANGE_REGISTER_REL
0578 class DefRangeRegisterRelSym : public SymbolRecord {
0579 public:
0580   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0581   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
0582       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
0583         RecordOffset(RecordOffset) {}
0584 
0585   // The flags implement this notional bitfield:
0586   //   uint16_t IsSubfield : 1;
0587   //   uint16_t Padding : 3;
0588   //   uint16_t OffsetInParent : 12;
0589   enum : uint16_t {
0590     IsSubfieldFlag = 1,
0591     OffsetInParentShift = 4,
0592   };
0593 
0594   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
0595   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
0596 
0597   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
0598 
0599   DefRangeRegisterRelHeader Hdr;
0600   LocalVariableAddrRange Range;
0601   std::vector<LocalVariableAddrGap> Gaps;
0602 
0603   uint32_t RecordOffset = 0;
0604 };
0605 
0606 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
0607 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
0608 public:
0609   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
0610       : SymbolRecord(Kind) {}
0611   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
0612       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
0613         RecordOffset(RecordOffset) {}
0614 
0615   int32_t Offset = 0;
0616 
0617   uint32_t RecordOffset = 0;
0618 };
0619 
0620 // S_BLOCK32
0621 class BlockSym : public SymbolRecord {
0622   static constexpr uint32_t RelocationOffset = 16;
0623 
0624 public:
0625   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0626   explicit BlockSym(uint32_t RecordOffset)
0627       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
0628 
0629   uint32_t getRelocationOffset() const {
0630     return RecordOffset + RelocationOffset;
0631   }
0632 
0633   uint32_t Parent = 0;
0634   uint32_t End = 0;
0635   uint32_t CodeSize = 0;
0636   uint32_t CodeOffset = 0;
0637   uint16_t Segment = 0;
0638   StringRef Name;
0639 
0640   uint32_t RecordOffset = 0;
0641 };
0642 
0643 // S_LABEL32
0644 class LabelSym : public SymbolRecord {
0645   static constexpr uint32_t RelocationOffset = 4;
0646 
0647 public:
0648   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0649   explicit LabelSym(uint32_t RecordOffset)
0650       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
0651 
0652   uint32_t getRelocationOffset() const {
0653     return RecordOffset + RelocationOffset;
0654   }
0655 
0656   uint32_t CodeOffset = 0;
0657   uint16_t Segment = 0;
0658   ProcSymFlags Flags = ProcSymFlags::None;
0659   StringRef Name;
0660 
0661   uint32_t RecordOffset = 0;
0662 };
0663 
0664 // S_OBJNAME
0665 class ObjNameSym : public SymbolRecord {
0666 public:
0667   explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
0668   explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0669   explicit ObjNameSym(uint32_t RecordOffset)
0670       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
0671   }
0672 
0673   uint32_t Signature = 0;
0674   StringRef Name;
0675 
0676   uint32_t RecordOffset = 0;
0677 };
0678 
0679 // S_ENVBLOCK
0680 class EnvBlockSym : public SymbolRecord {
0681 public:
0682   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0683   explicit EnvBlockSym(uint32_t RecordOffset)
0684       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
0685         RecordOffset(RecordOffset) {}
0686 
0687   std::vector<StringRef> Fields;
0688 
0689   uint32_t RecordOffset = 0;
0690 };
0691 
0692 // S_EXPORT
0693 class ExportSym : public SymbolRecord {
0694 public:
0695   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0696   explicit ExportSym(uint32_t RecordOffset)
0697       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
0698 
0699   uint16_t Ordinal = 0;
0700   ExportFlags Flags = ExportFlags::None;
0701   StringRef Name;
0702 
0703   uint32_t RecordOffset = 0;
0704 };
0705 
0706 // S_FILESTATIC
0707 class FileStaticSym : public SymbolRecord {
0708 public:
0709   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0710   explicit FileStaticSym(uint32_t RecordOffset)
0711       : SymbolRecord(SymbolRecordKind::FileStaticSym),
0712         RecordOffset(RecordOffset) {}
0713 
0714   TypeIndex Index;
0715   uint32_t ModFilenameOffset = 0;
0716   LocalSymFlags Flags = LocalSymFlags::None;
0717   StringRef Name;
0718 
0719   uint32_t RecordOffset = 0;
0720 };
0721 
0722 // S_COMPILE2
0723 class Compile2Sym : public SymbolRecord {
0724 public:
0725   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0726   explicit Compile2Sym(uint32_t RecordOffset)
0727       : SymbolRecord(SymbolRecordKind::Compile2Sym),
0728         RecordOffset(RecordOffset) {}
0729 
0730   CompileSym2Flags Flags = CompileSym2Flags::None;
0731   CPUType Machine;
0732   uint16_t VersionFrontendMajor = 0;
0733   uint16_t VersionFrontendMinor = 0;
0734   uint16_t VersionFrontendBuild = 0;
0735   uint16_t VersionBackendMajor = 0;
0736   uint16_t VersionBackendMinor = 0;
0737   uint16_t VersionBackendBuild = 0;
0738   StringRef Version;
0739   std::vector<StringRef> ExtraStrings;
0740 
0741   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
0742   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
0743 
0744   uint32_t RecordOffset = 0;
0745 };
0746 
0747 // S_COMPILE3
0748 class Compile3Sym : public SymbolRecord {
0749 public:
0750   Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
0751   explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0752   explicit Compile3Sym(uint32_t RecordOffset)
0753       : SymbolRecord(SymbolRecordKind::Compile3Sym),
0754         RecordOffset(RecordOffset) {}
0755 
0756   CompileSym3Flags Flags = CompileSym3Flags::None;
0757   CPUType Machine;
0758   uint16_t VersionFrontendMajor = 0;
0759   uint16_t VersionFrontendMinor = 0;
0760   uint16_t VersionFrontendBuild = 0;
0761   uint16_t VersionFrontendQFE = 0;
0762   uint16_t VersionBackendMajor = 0;
0763   uint16_t VersionBackendMinor = 0;
0764   uint16_t VersionBackendBuild = 0;
0765   uint16_t VersionBackendQFE = 0;
0766   StringRef Version;
0767 
0768   void setLanguage(SourceLanguage Lang) {
0769     Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
0770   }
0771 
0772   SourceLanguage getLanguage() const {
0773     return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
0774   }
0775   CompileSym3Flags getFlags() const {
0776     return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
0777   }
0778 
0779   bool hasOptimizations() const {
0780     return CompileSym3Flags::None !=
0781            (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
0782   }
0783 
0784   uint32_t RecordOffset = 0;
0785 };
0786 
0787 // S_FRAMEPROC
0788 class FrameProcSym : public SymbolRecord {
0789 public:
0790   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0791   explicit FrameProcSym(uint32_t RecordOffset)
0792       : SymbolRecord(SymbolRecordKind::FrameProcSym),
0793         RecordOffset(RecordOffset) {}
0794 
0795   uint32_t TotalFrameBytes = 0;
0796   uint32_t PaddingFrameBytes = 0;
0797   uint32_t OffsetToPadding = 0;
0798   uint32_t BytesOfCalleeSavedRegisters = 0;
0799   uint32_t OffsetOfExceptionHandler = 0;
0800   uint16_t SectionIdOfExceptionHandler = 0;
0801   FrameProcedureOptions Flags = FrameProcedureOptions::None;
0802 
0803   /// Extract the register this frame uses to refer to local variables.
0804   RegisterId getLocalFramePtrReg(CPUType CPU) const {
0805     return decodeFramePtrReg(
0806         EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
0807   }
0808 
0809   /// Extract the register this frame uses to refer to parameters.
0810   RegisterId getParamFramePtrReg(CPUType CPU) const {
0811     return decodeFramePtrReg(
0812         EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
0813   }
0814 
0815   uint32_t RecordOffset = 0;
0816 
0817 private:
0818 };
0819 
0820 // S_CALLSITEINFO
0821 class CallSiteInfoSym : public SymbolRecord {
0822   static constexpr uint32_t RelocationOffset = 4;
0823 
0824 public:
0825   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0826   explicit CallSiteInfoSym(uint32_t RecordOffset)
0827       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
0828 
0829   uint32_t getRelocationOffset() const {
0830     return RecordOffset + RelocationOffset;
0831   }
0832 
0833   uint32_t CodeOffset = 0;
0834   uint16_t Segment = 0;
0835   TypeIndex Type;
0836 
0837   uint32_t RecordOffset = 0;
0838 };
0839 
0840 // S_HEAPALLOCSITE
0841 class HeapAllocationSiteSym : public SymbolRecord {
0842   static constexpr uint32_t RelocationOffset = 4;
0843 
0844 public:
0845   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0846   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
0847       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
0848         RecordOffset(RecordOffset) {}
0849 
0850   uint32_t getRelocationOffset() const {
0851     return RecordOffset + RelocationOffset;
0852   }
0853 
0854   uint32_t CodeOffset = 0;
0855   uint16_t Segment = 0;
0856   uint16_t CallInstructionSize = 0;
0857   TypeIndex Type;
0858 
0859   uint32_t RecordOffset = 0;
0860 };
0861 
0862 // S_FRAMECOOKIE
0863 class FrameCookieSym : public SymbolRecord {
0864   static constexpr uint32_t RelocationOffset = 4;
0865 
0866 public:
0867   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0868   explicit FrameCookieSym(uint32_t RecordOffset)
0869       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
0870 
0871   uint32_t getRelocationOffset() const {
0872     return RecordOffset + RelocationOffset;
0873   }
0874 
0875   uint32_t CodeOffset = 0;
0876   uint16_t Register = 0;
0877   FrameCookieKind CookieKind;
0878   uint8_t Flags = 0;
0879 
0880   uint32_t RecordOffset = 0;
0881 };
0882 
0883 // S_UDT, S_COBOLUDT
0884 class UDTSym : public SymbolRecord {
0885 public:
0886   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0887   explicit UDTSym(uint32_t RecordOffset)
0888       : SymbolRecord(SymbolRecordKind::UDTSym) {}
0889 
0890   TypeIndex Type;
0891   StringRef Name;
0892 
0893   uint32_t RecordOffset = 0;
0894 };
0895 
0896 // S_BUILDINFO
0897 class BuildInfoSym : public SymbolRecord {
0898 public:
0899   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0900   explicit BuildInfoSym(uint32_t RecordOffset)
0901       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
0902         RecordOffset(RecordOffset) {}
0903 
0904   TypeIndex BuildId;
0905 
0906   uint32_t RecordOffset = 0;
0907 };
0908 
0909 // S_BPREL32
0910 class BPRelativeSym : public SymbolRecord {
0911 public:
0912   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0913   explicit BPRelativeSym(uint32_t RecordOffset)
0914       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
0915         RecordOffset(RecordOffset) {}
0916 
0917   int32_t Offset = 0;
0918   TypeIndex Type;
0919   StringRef Name;
0920 
0921   uint32_t RecordOffset = 0;
0922 };
0923 
0924 // S_REGREL32
0925 class RegRelativeSym : public SymbolRecord {
0926 public:
0927   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0928   explicit RegRelativeSym(uint32_t RecordOffset)
0929       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
0930         RecordOffset(RecordOffset) {}
0931 
0932   uint32_t Offset = 0;
0933   TypeIndex Type;
0934   RegisterId Register;
0935   StringRef Name;
0936 
0937   uint32_t RecordOffset = 0;
0938 };
0939 
0940 // S_CONSTANT, S_MANCONSTANT
0941 class ConstantSym : public SymbolRecord {
0942 public:
0943   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0944   explicit ConstantSym(uint32_t RecordOffset)
0945       : SymbolRecord(SymbolRecordKind::ConstantSym),
0946         RecordOffset(RecordOffset) {}
0947 
0948   TypeIndex Type;
0949   APSInt Value;
0950   StringRef Name;
0951 
0952   uint32_t RecordOffset = 0;
0953 };
0954 
0955 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
0956 class DataSym : public SymbolRecord {
0957   static constexpr uint32_t RelocationOffset = 8;
0958 
0959 public:
0960   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0961   explicit DataSym(uint32_t RecordOffset)
0962       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
0963 
0964   uint32_t getRelocationOffset() const {
0965     return RecordOffset + RelocationOffset;
0966   }
0967 
0968   TypeIndex Type;
0969   uint32_t DataOffset = 0;
0970   uint16_t Segment = 0;
0971   StringRef Name;
0972 
0973   uint32_t RecordOffset = 0;
0974 };
0975 
0976 // S_LTHREAD32, S_GTHREAD32
0977 class ThreadLocalDataSym : public SymbolRecord {
0978   static constexpr uint32_t RelocationOffset = 8;
0979 
0980 public:
0981   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
0982   explicit ThreadLocalDataSym(uint32_t RecordOffset)
0983       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
0984         RecordOffset(RecordOffset) {}
0985 
0986   uint32_t getRelocationOffset() const {
0987     return RecordOffset + RelocationOffset;
0988   }
0989 
0990   TypeIndex Type;
0991   uint32_t DataOffset = 0;
0992   uint16_t Segment = 0;
0993   StringRef Name;
0994 
0995   uint32_t RecordOffset = 0;
0996 };
0997 
0998 // S_UNAMESPACE
0999 class UsingNamespaceSym : public SymbolRecord {
1000 public:
1001   explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
1002   explicit UsingNamespaceSym(uint32_t RecordOffset)
1003       : SymbolRecord(SymbolRecordKind::UsingNamespaceSym),
1004         RecordOffset(RecordOffset) {}
1005 
1006   StringRef Name;
1007 
1008   uint32_t RecordOffset = 0;
1009 };
1010 
1011 // S_ANNOTATION
1012 class AnnotationSym : public SymbolRecord {
1013 public:
1014   explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
1015   explicit AnnotationSym(uint32_t RecordOffset)
1016       : SymbolRecord(SymbolRecordKind::AnnotationSym),
1017         RecordOffset(RecordOffset) {}
1018 
1019   uint32_t CodeOffset = 0;
1020   uint16_t Segment = 0;
1021   std::vector<StringRef> Strings;
1022 
1023   uint32_t RecordOffset = 0;
1024 };
1025 
1026 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
1027                                         uint32_t Offset);
1028 
1029 } // end namespace codeview
1030 } // end namespace llvm
1031 
1032 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H