summaryrefslogtreecommitdiff
path: root/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h')
-rw-r--r--clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h995
1 files changed, 995 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h
new file mode 100644
index 00000000..ac7b106e
--- /dev/null
+++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -0,0 +1,995 @@
+//===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/Endian.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class SymbolRecord {
+protected:
+ explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
+
+public:
+ SymbolRecordKind getKind() const { return Kind; }
+
+ SymbolRecordKind Kind;
+};
+
+// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
+// S_LPROC32_DPC_ID
+class ProcSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 32;
+
+public:
+ explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t Parent = 0;
+ uint32_t End = 0;
+ uint32_t Next = 0;
+ uint32_t CodeSize = 0;
+ uint32_t DbgStart = 0;
+ uint32_t DbgEnd = 0;
+ TypeIndex FunctionType;
+ uint32_t CodeOffset = 0;
+ uint16_t Segment = 0;
+ ProcSymFlags Flags = ProcSymFlags::None;
+ StringRef Name;
+
+ uint32_t RecordOffset = 0;
+};
+
+// S_THUNK32
+class Thunk32Sym : public SymbolRecord {
+public:
+ explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ uint32_t Parent;
+ uint32_t End;
+ uint32_t Next;
+ uint32_t Offset;
+ uint16_t Segment;
+ uint16_t Length;
+ ThunkOrdinal Thunk;
+ StringRef Name;
+ ArrayRef<uint8_t> VariantData;
+
+ uint32_t RecordOffset;
+};
+
+// S_TRAMPOLINE
+class TrampolineSym : public SymbolRecord {
+public:
+ explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ TrampolineType Type;
+ uint16_t Size;
+ uint32_t ThunkOffset;
+ uint32_t TargetOffset;
+ uint16_t ThunkSection;
+ uint16_t TargetSection;
+
+ uint32_t RecordOffset;
+};
+
+// S_SECTION
+class SectionSym : public SymbolRecord {
+public:
+ explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ uint16_t SectionNumber;
+ uint8_t Alignment;
+ uint32_t Rva;
+ uint32_t Length;
+ uint32_t Characteristics;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_COFFGROUP
+class CoffGroupSym : public SymbolRecord {
+public:
+ explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ uint32_t Size;
+ uint32_t Characteristics;
+ uint32_t Offset;
+ uint16_t Segment;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+class ScopeEndSym : public SymbolRecord {
+public:
+ explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ uint32_t RecordOffset;
+};
+
+class CallerSym : public SymbolRecord {
+public:
+ explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
+ : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
+
+ std::vector<TypeIndex> Indices;
+
+ uint32_t RecordOffset;
+};
+
+struct BinaryAnnotationIterator {
+ struct AnnotationData {
+ BinaryAnnotationsOpCode OpCode;
+ StringRef Name;
+ uint32_t U1;
+ uint32_t U2;
+ int32_t S1;
+ };
+
+ BinaryAnnotationIterator() = default;
+ BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
+ BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
+ : Data(Other.Data) {}
+
+ bool operator==(BinaryAnnotationIterator Other) const {
+ return Data == Other.Data;
+ }
+
+ bool operator!=(const BinaryAnnotationIterator &Other) const {
+ return !(*this == Other);
+ }
+
+ BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
+ Data = Other.Data;
+ return *this;
+ }
+
+ BinaryAnnotationIterator &operator++() {
+ if (!ParseCurrentAnnotation()) {
+ *this = BinaryAnnotationIterator();
+ return *this;
+ }
+ Data = Next;
+ Next = ArrayRef<uint8_t>();
+ Current.reset();
+ return *this;
+ }
+
+ BinaryAnnotationIterator operator++(int) {
+ BinaryAnnotationIterator Orig(*this);
+ ++(*this);
+ return Orig;
+ }
+
+ const AnnotationData &operator*() {
+ ParseCurrentAnnotation();
+ return Current.getValue();
+ }
+
+private:
+ static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t FirstByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0x80) == 0x00)
+ return FirstByte;
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t SecondByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0xC0) == 0x80)
+ return ((FirstByte & 0x3F) << 8) | SecondByte;
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t ThirdByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if (Annotations.empty())
+ return -1;
+
+ uint8_t FourthByte = Annotations.front();
+ Annotations = Annotations.drop_front();
+
+ if ((FirstByte & 0xE0) == 0xC0)
+ return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
+ (ThirdByte << 8) | FourthByte;
+
+ return -1;
+ };
+
+ static int32_t DecodeSignedOperand(uint32_t Operand) {
+ if (Operand & 1)
+ return -(Operand >> 1);
+ return Operand >> 1;
+ };
+
+ static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
+ return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
+ };
+
+ bool ParseCurrentAnnotation() {
+ if (Current.hasValue())
+ return true;
+
+ Next = Data;
+ uint32_t Op = GetCompressedAnnotation(Next);
+ AnnotationData Result;
+ Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
+ switch (Result.OpCode) {
+ case BinaryAnnotationsOpCode::Invalid:
+ Result.Name = "Invalid";
+ Next = ArrayRef<uint8_t>();
+ break;
+ case BinaryAnnotationsOpCode::CodeOffset:
+ Result.Name = "CodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+ Result.Name = "ChangeCodeOffsetBase";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ Result.Name = "ChangeCodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ Result.Name = "ChangeCodeLength";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeFile:
+ Result.Name = "ChangeFile";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+ Result.Name = "ChangeLineEndDelta";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeRangeKind:
+ Result.Name = "ChangeRangeKind";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnStart:
+ Result.Name = "ChangeColumnStart";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnEnd:
+ Result.Name = "ChangeColumnEnd";
+ Result.U1 = GetCompressedAnnotation(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineOffset:
+ Result.Name = "ChangeLineOffset";
+ Result.S1 = DecodeSignedOperand(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+ Result.Name = "ChangeColumnEndDelta";
+ Result.S1 = DecodeSignedOperand(Next);
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
+ Result.Name = "ChangeCodeOffsetAndLineOffset";
+ uint32_t Annotation = GetCompressedAnnotation(Next);
+ Result.S1 = DecodeSignedOperand(Annotation >> 4);
+ Result.U1 = Annotation & 0xf;
+ break;
+ }
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
+ Result.Name = "ChangeCodeLengthAndCodeOffset";
+ Result.U1 = GetCompressedAnnotation(Next);
+ Result.U2 = GetCompressedAnnotation(Next);
+ break;
+ }
+ }
+ Current = Result;
+ return true;
+ }
+
+ Optional<AnnotationData> Current;
+ ArrayRef<uint8_t> Data;
+ ArrayRef<uint8_t> Next;
+};
+
+// S_INLINESITE
+class InlineSiteSym : public SymbolRecord {
+public:
+ explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ InlineSiteSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::InlineSiteSym),
+ RecordOffset(RecordOffset) {}
+
+ iterator_range<BinaryAnnotationIterator> annotations() const {
+ return make_range(BinaryAnnotationIterator(AnnotationData),
+ BinaryAnnotationIterator());
+ }
+
+ uint32_t Parent;
+ uint32_t End;
+ TypeIndex Inlinee;
+ std::vector<uint8_t> AnnotationData;
+
+ uint32_t RecordOffset;
+};
+
+// S_PUB32
+class PublicSym32 : public SymbolRecord {
+public:
+ PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
+ explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit PublicSym32(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::PublicSym32),
+ RecordOffset(RecordOffset) {}
+
+ PublicSymFlags Flags = PublicSymFlags::None;
+ uint32_t Offset = 0;
+ uint16_t Segment = 0;
+ StringRef Name;
+
+ uint32_t RecordOffset = 0;
+};
+
+// S_REGISTER
+class RegisterSym : public SymbolRecord {
+public:
+ explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ RegisterSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::RegisterSym),
+ RecordOffset(RecordOffset) {}
+
+ TypeIndex Index;
+ RegisterId Register;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_PROCREF, S_LPROCREF
+class ProcRefSym : public SymbolRecord {
+public:
+ explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit ProcRefSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
+ }
+
+ uint32_t SumName;
+ uint32_t SymOffset;
+ uint16_t Module;
+ StringRef Name;
+
+ uint16_t modi() const { return Module - 1; }
+ uint32_t RecordOffset;
+};
+
+// S_LOCAL
+class LocalSym : public SymbolRecord {
+public:
+ explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit LocalSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
+
+ TypeIndex Type;
+ LocalSymFlags Flags;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+struct LocalVariableAddrRange {
+ uint32_t OffsetStart;
+ uint16_t ISectStart;
+ uint16_t Range;
+};
+
+struct LocalVariableAddrGap {
+ uint16_t GapStartOffset;
+ uint16_t Range;
+};
+
+enum : uint16_t { MaxDefRange = 0xf000 };
+
+// S_DEFRANGE
+class DefRangeSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 8;
+
+public:
+ explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit DefRangeSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t Program;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_SUBFIELD
+class DefRangeSubfieldSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 12;
+
+public:
+ explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ DefRangeSubfieldSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t Program;
+ uint16_t OffsetInParent;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_REGISTER
+class DefRangeRegisterSym : public SymbolRecord {
+public:
+ struct Header {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+ };
+
+ explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ DefRangeRegisterSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+
+ Header Hdr;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_SUBFIELD_REGISTER
+class DefRangeSubfieldRegisterSym : public SymbolRecord {
+public:
+ struct Header {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+ ulittle32_t OffsetInParent;
+ };
+
+ explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
+ : SymbolRecord(Kind) {}
+ DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+
+ Header Hdr;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_FRAMEPOINTER_REL
+class DefRangeFramePointerRelSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 8;
+
+public:
+ explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
+ : SymbolRecord(Kind) {}
+ DefRangeFramePointerRelSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ int32_t Offset;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_REGISTER_REL
+class DefRangeRegisterRelSym : public SymbolRecord {
+public:
+ struct Header {
+ ulittle16_t Register;
+ ulittle16_t Flags;
+ little32_t BasePointerOffset;
+ };
+
+ explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
+ RecordOffset(RecordOffset) {}
+
+ // The flags implement this notional bitfield:
+ // uint16_t IsSubfield : 1;
+ // uint16_t Padding : 3;
+ // uint16_t OffsetInParent : 12;
+ enum : uint16_t {
+ IsSubfieldFlag = 1,
+ OffsetInParentShift = 4,
+ };
+
+ bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
+ uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
+
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+
+ Header Hdr;
+ LocalVariableAddrRange Range;
+ std::vector<LocalVariableAddrGap> Gaps;
+
+ uint32_t RecordOffset;
+};
+
+// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
+class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
+public:
+ explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
+ : SymbolRecord(Kind) {}
+ explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
+ RecordOffset(RecordOffset) {}
+
+ int32_t Offset;
+
+ uint32_t RecordOffset;
+};
+
+// S_BLOCK32
+class BlockSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 16;
+
+public:
+ explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit BlockSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t Parent;
+ uint32_t End;
+ uint32_t CodeSize;
+ uint32_t CodeOffset;
+ uint16_t Segment;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_LABEL32
+class LabelSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 4;
+
+public:
+ explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit LabelSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t CodeOffset;
+ uint16_t Segment;
+ ProcSymFlags Flags;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_OBJNAME
+class ObjNameSym : public SymbolRecord {
+public:
+ explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
+ explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ ObjNameSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
+ }
+
+ uint32_t Signature;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_ENVBLOCK
+class EnvBlockSym : public SymbolRecord {
+public:
+ explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ EnvBlockSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::EnvBlockSym),
+ RecordOffset(RecordOffset) {}
+
+ std::vector<StringRef> Fields;
+
+ uint32_t RecordOffset;
+};
+
+// S_EXPORT
+class ExportSym : public SymbolRecord {
+public:
+ explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ ExportSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
+
+ uint16_t Ordinal;
+ ExportFlags Flags;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_FILESTATIC
+class FileStaticSym : public SymbolRecord {
+public:
+ explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ FileStaticSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::FileStaticSym),
+ RecordOffset(RecordOffset) {}
+
+ TypeIndex Index;
+ uint32_t ModFilenameOffset;
+ LocalSymFlags Flags;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_COMPILE2
+class Compile2Sym : public SymbolRecord {
+public:
+ explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ Compile2Sym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::Compile2Sym),
+ RecordOffset(RecordOffset) {}
+
+ CompileSym2Flags Flags;
+ CPUType Machine;
+ uint16_t VersionFrontendMajor;
+ uint16_t VersionFrontendMinor;
+ uint16_t VersionFrontendBuild;
+ uint16_t VersionBackendMajor;
+ uint16_t VersionBackendMinor;
+ uint16_t VersionBackendBuild;
+ StringRef Version;
+ std::vector<StringRef> ExtraStrings;
+
+ uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
+ uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
+
+ uint32_t RecordOffset;
+};
+
+// S_COMPILE3
+class Compile3Sym : public SymbolRecord {
+public:
+ Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
+ explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ Compile3Sym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::Compile3Sym),
+ RecordOffset(RecordOffset) {}
+
+ CompileSym3Flags Flags;
+ CPUType Machine;
+ uint16_t VersionFrontendMajor;
+ uint16_t VersionFrontendMinor;
+ uint16_t VersionFrontendBuild;
+ uint16_t VersionFrontendQFE;
+ uint16_t VersionBackendMajor;
+ uint16_t VersionBackendMinor;
+ uint16_t VersionBackendBuild;
+ uint16_t VersionBackendQFE;
+ StringRef Version;
+
+ void setLanguage(SourceLanguage Lang) {
+ Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
+ }
+
+ SourceLanguage getLanguage() const {
+ return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
+ }
+ CompileSym3Flags getFlags() const {
+ return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
+ }
+
+ bool hasOptimizations() const {
+ return CompileSym3Flags::None !=
+ (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
+ }
+
+ uint32_t RecordOffset;
+};
+
+// S_FRAMEPROC
+class FrameProcSym : public SymbolRecord {
+public:
+ explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit FrameProcSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::FrameProcSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t TotalFrameBytes;
+ uint32_t PaddingFrameBytes;
+ uint32_t OffsetToPadding;
+ uint32_t BytesOfCalleeSavedRegisters;
+ uint32_t OffsetOfExceptionHandler;
+ uint16_t SectionIdOfExceptionHandler;
+ FrameProcedureOptions Flags;
+
+ /// Extract the register this frame uses to refer to local variables.
+ RegisterId getLocalFramePtrReg(CPUType CPU) const {
+ return decodeFramePtrReg(
+ EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
+ }
+
+ /// Extract the register this frame uses to refer to parameters.
+ RegisterId getParamFramePtrReg(CPUType CPU) const {
+ return decodeFramePtrReg(
+ EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
+ }
+
+ uint32_t RecordOffset;
+
+private:
+};
+
+// S_CALLSITEINFO
+class CallSiteInfoSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 4;
+
+public:
+ explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit CallSiteInfoSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t CodeOffset;
+ uint16_t Segment;
+ TypeIndex Type;
+
+ uint32_t RecordOffset;
+};
+
+// S_HEAPALLOCSITE
+class HeapAllocationSiteSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 4;
+
+public:
+ explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit HeapAllocationSiteSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t CodeOffset;
+ uint16_t Segment;
+ uint16_t CallInstructionSize;
+ TypeIndex Type;
+
+ uint32_t RecordOffset;
+};
+
+// S_FRAMECOOKIE
+class FrameCookieSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 4;
+
+public:
+ explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit FrameCookieSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ uint32_t CodeOffset;
+ uint16_t Register;
+ FrameCookieKind CookieKind;
+ uint8_t Flags;
+
+ uint32_t RecordOffset;
+};
+
+// S_UDT, S_COBOLUDT
+class UDTSym : public SymbolRecord {
+public:
+ explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit UDTSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::UDTSym) {}
+
+ TypeIndex Type;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_BUILDINFO
+class BuildInfoSym : public SymbolRecord {
+public:
+ explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ BuildInfoSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::BuildInfoSym),
+ RecordOffset(RecordOffset) {}
+
+ TypeIndex BuildId;
+
+ uint32_t RecordOffset;
+};
+
+// S_BPREL32
+class BPRelativeSym : public SymbolRecord {
+public:
+ explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit BPRelativeSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::BPRelativeSym),
+ RecordOffset(RecordOffset) {}
+
+ int32_t Offset;
+ TypeIndex Type;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_REGREL32
+class RegRelativeSym : public SymbolRecord {
+public:
+ explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit RegRelativeSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::RegRelativeSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t Offset;
+ TypeIndex Type;
+ RegisterId Register;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_CONSTANT, S_MANCONSTANT
+class ConstantSym : public SymbolRecord {
+public:
+ explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ ConstantSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::ConstantSym),
+ RecordOffset(RecordOffset) {}
+
+ TypeIndex Type;
+ APSInt Value;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
+class DataSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 8;
+
+public:
+ explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ DataSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ TypeIndex Type;
+ uint32_t DataOffset;
+ uint16_t Segment;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_LTHREAD32, S_GTHREAD32
+class ThreadLocalDataSym : public SymbolRecord {
+ static constexpr uint32_t RelocationOffset = 8;
+
+public:
+ explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit ThreadLocalDataSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
+ RecordOffset(RecordOffset) {}
+
+ uint32_t getRelocationOffset() const {
+ return RecordOffset + RelocationOffset;
+ }
+
+ TypeIndex Type;
+ uint32_t DataOffset;
+ uint16_t Segment;
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_UNAMESPACE
+class UsingNamespaceSym : public SymbolRecord {
+public:
+ explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
+ explicit UsingNamespaceSym(uint32_t RecordOffset)
+ : SymbolRecord(SymbolRecordKind::RegRelativeSym),
+ RecordOffset(RecordOffset) {}
+
+ StringRef Name;
+
+ uint32_t RecordOffset;
+};
+
+// S_ANNOTATION
+
+using CVSymbol = CVRecord<SymbolKind>;
+using CVSymbolArray = VarStreamArray<CVSymbol>;
+
+Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
+ uint32_t Offset);
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H