1 //===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
10 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/iterator.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/CodeView/CVRecord.h"
19 #include "llvm/DebugInfo/CodeView/CodeView.h"
20 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 #include "llvm/Support/BinaryStreamArray.h"
23 #include "llvm/Support/Endian.h"
32 explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
35 SymbolRecordKind getKind() const { return Kind; }
37 SymbolRecordKind Kind;
40 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
42 class ProcSym : public SymbolRecord {
43 static constexpr uint32_t RelocationOffset = 32;
46 explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
47 ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
48 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
50 uint32_t getRelocationOffset() const {
51 return RecordOffset + RelocationOffset;
57 uint32_t CodeSize = 0;
58 uint32_t DbgStart = 0;
60 TypeIndex FunctionType;
61 uint32_t CodeOffset = 0;
63 ProcSymFlags Flags = ProcSymFlags::None;
66 uint32_t RecordOffset = 0;
70 class Thunk32Sym : public SymbolRecord {
72 explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
73 Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
74 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
82 ThunkOrdinal Thunk = ThunkOrdinal::Standard;
84 ArrayRef<uint8_t> VariantData;
86 uint32_t RecordOffset = 0;
90 class TrampolineSym : public SymbolRecord {
92 explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
93 TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
94 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
98 uint32_t ThunkOffset = 0;
99 uint32_t TargetOffset = 0;
100 uint16_t ThunkSection = 0;
101 uint16_t TargetSection = 0;
103 uint32_t RecordOffset = 0;
107 class SectionSym : public SymbolRecord {
109 explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
110 SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
111 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
113 uint16_t SectionNumber = 0;
114 uint8_t Alignment = 0;
117 uint32_t Characteristics = 0;
120 uint32_t RecordOffset = 0;
124 class CoffGroupSym : public SymbolRecord {
126 explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
127 CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
128 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
131 uint32_t Characteristics = 0;
133 uint16_t Segment = 0;
136 uint32_t RecordOffset = 0;
139 class ScopeEndSym : public SymbolRecord {
141 explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
142 ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
143 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
145 uint32_t RecordOffset = 0;
148 class CallerSym : public SymbolRecord {
150 explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
151 CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
152 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
154 std::vector<TypeIndex> Indices;
156 uint32_t RecordOffset = 0;
159 struct DecodedAnnotation {
161 ArrayRef<uint8_t> Bytes;
162 BinaryAnnotationsOpCode OpCode = BinaryAnnotationsOpCode::Invalid;
168 struct BinaryAnnotationIterator
169 : public iterator_facade_base<BinaryAnnotationIterator,
170 std::forward_iterator_tag,
172 BinaryAnnotationIterator() = default;
173 BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
174 BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
175 : Data(Other.Data) {}
177 bool operator==(BinaryAnnotationIterator Other) const {
178 return Data == Other.Data;
181 BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
186 BinaryAnnotationIterator &operator++() {
187 if (!ParseCurrentAnnotation()) {
188 *this = BinaryAnnotationIterator();
192 Next = ArrayRef<uint8_t>();
197 const DecodedAnnotation &operator*() {
198 ParseCurrentAnnotation();
199 return Current.getValue();
203 static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
204 if (Annotations.empty())
207 uint8_t FirstByte = Annotations.front();
208 Annotations = Annotations.drop_front();
210 if ((FirstByte & 0x80) == 0x00)
213 if (Annotations.empty())
216 uint8_t SecondByte = Annotations.front();
217 Annotations = Annotations.drop_front();
219 if ((FirstByte & 0xC0) == 0x80)
220 return ((FirstByte & 0x3F) << 8) | SecondByte;
222 if (Annotations.empty())
225 uint8_t ThirdByte = Annotations.front();
226 Annotations = Annotations.drop_front();
228 if (Annotations.empty())
231 uint8_t FourthByte = Annotations.front();
232 Annotations = Annotations.drop_front();
234 if ((FirstByte & 0xE0) == 0xC0)
235 return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
236 (ThirdByte << 8) | FourthByte;
241 static int32_t DecodeSignedOperand(uint32_t Operand) {
243 return -(Operand >> 1);
247 static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
248 return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
251 bool ParseCurrentAnnotation() {
252 if (Current.hasValue())
256 uint32_t Op = GetCompressedAnnotation(Next);
257 DecodedAnnotation Result;
258 Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
259 switch (Result.OpCode) {
260 case BinaryAnnotationsOpCode::Invalid:
261 Result.Name = "Invalid";
262 Next = ArrayRef<uint8_t>();
264 case BinaryAnnotationsOpCode::CodeOffset:
265 Result.Name = "CodeOffset";
266 Result.U1 = GetCompressedAnnotation(Next);
268 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
269 Result.Name = "ChangeCodeOffsetBase";
270 Result.U1 = GetCompressedAnnotation(Next);
272 case BinaryAnnotationsOpCode::ChangeCodeOffset:
273 Result.Name = "ChangeCodeOffset";
274 Result.U1 = GetCompressedAnnotation(Next);
276 case BinaryAnnotationsOpCode::ChangeCodeLength:
277 Result.Name = "ChangeCodeLength";
278 Result.U1 = GetCompressedAnnotation(Next);
280 case BinaryAnnotationsOpCode::ChangeFile:
281 Result.Name = "ChangeFile";
282 Result.U1 = GetCompressedAnnotation(Next);
284 case BinaryAnnotationsOpCode::ChangeLineEndDelta:
285 Result.Name = "ChangeLineEndDelta";
286 Result.U1 = GetCompressedAnnotation(Next);
288 case BinaryAnnotationsOpCode::ChangeRangeKind:
289 Result.Name = "ChangeRangeKind";
290 Result.U1 = GetCompressedAnnotation(Next);
292 case BinaryAnnotationsOpCode::ChangeColumnStart:
293 Result.Name = "ChangeColumnStart";
294 Result.U1 = GetCompressedAnnotation(Next);
296 case BinaryAnnotationsOpCode::ChangeColumnEnd:
297 Result.Name = "ChangeColumnEnd";
298 Result.U1 = GetCompressedAnnotation(Next);
300 case BinaryAnnotationsOpCode::ChangeLineOffset:
301 Result.Name = "ChangeLineOffset";
302 Result.S1 = DecodeSignedOperand(Next);
304 case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
305 Result.Name = "ChangeColumnEndDelta";
306 Result.S1 = DecodeSignedOperand(Next);
308 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
309 Result.Name = "ChangeCodeOffsetAndLineOffset";
310 uint32_t Annotation = GetCompressedAnnotation(Next);
311 Result.S1 = DecodeSignedOperand(Annotation >> 4);
312 Result.U1 = Annotation & 0xf;
315 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
316 Result.Name = "ChangeCodeLengthAndCodeOffset";
317 Result.U1 = GetCompressedAnnotation(Next);
318 Result.U2 = GetCompressedAnnotation(Next);
322 Result.Bytes = Data.take_front(Data.size() - Next.size());
327 Optional<DecodedAnnotation> Current;
328 ArrayRef<uint8_t> Data;
329 ArrayRef<uint8_t> Next;
333 class InlineSiteSym : public SymbolRecord {
335 explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
336 explicit InlineSiteSym(uint32_t RecordOffset)
337 : SymbolRecord(SymbolRecordKind::InlineSiteSym),
338 RecordOffset(RecordOffset) {}
340 iterator_range<BinaryAnnotationIterator> annotations() const {
341 return make_range(BinaryAnnotationIterator(AnnotationData),
342 BinaryAnnotationIterator());
348 std::vector<uint8_t> AnnotationData;
350 uint32_t RecordOffset = 0;
353 struct PublicSym32Header {
361 class PublicSym32 : public SymbolRecord {
363 PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
364 explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
365 explicit PublicSym32(uint32_t RecordOffset)
366 : SymbolRecord(SymbolRecordKind::PublicSym32),
367 RecordOffset(RecordOffset) {}
369 PublicSymFlags Flags = PublicSymFlags::None;
371 uint16_t Segment = 0;
374 uint32_t RecordOffset = 0;
378 class RegisterSym : public SymbolRecord {
380 explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
381 explicit RegisterSym(uint32_t RecordOffset)
382 : SymbolRecord(SymbolRecordKind::RegisterSym),
383 RecordOffset(RecordOffset) {}
389 uint32_t RecordOffset = 0;
392 // S_PROCREF, S_LPROCREF
393 class ProcRefSym : public SymbolRecord {
395 explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
396 explicit ProcRefSym(uint32_t RecordOffset)
397 : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
400 uint32_t SumName = 0;
401 uint32_t SymOffset = 0;
405 uint16_t modi() const { return Module - 1; }
406 uint32_t RecordOffset = 0;
410 class LocalSym : public SymbolRecord {
412 explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
413 explicit LocalSym(uint32_t RecordOffset)
414 : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
417 LocalSymFlags Flags = LocalSymFlags::None;
420 uint32_t RecordOffset = 0;
423 struct LocalVariableAddrRange {
424 uint32_t OffsetStart = 0;
425 uint16_t ISectStart = 0;
429 struct LocalVariableAddrGap {
430 uint16_t GapStartOffset = 0;
434 enum : uint16_t { MaxDefRange = 0xf000 };
437 class DefRangeSym : public SymbolRecord {
438 static constexpr uint32_t RelocationOffset = 8;
441 explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
442 explicit DefRangeSym(uint32_t RecordOffset)
443 : SymbolRecord(SymbolRecordKind::DefRangeSym),
444 RecordOffset(RecordOffset) {}
446 uint32_t getRelocationOffset() const {
447 return RecordOffset + RelocationOffset;
450 uint32_t Program = 0;
451 LocalVariableAddrRange Range;
452 std::vector<LocalVariableAddrGap> Gaps;
454 uint32_t RecordOffset = 0;
457 // S_DEFRANGE_SUBFIELD
458 class DefRangeSubfieldSym : public SymbolRecord {
459 static constexpr uint32_t RelocationOffset = 12;
462 explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
463 explicit DefRangeSubfieldSym(uint32_t RecordOffset)
464 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
465 RecordOffset(RecordOffset) {}
467 uint32_t getRelocationOffset() const {
468 return RecordOffset + RelocationOffset;
471 uint32_t Program = 0;
472 uint16_t OffsetInParent = 0;
473 LocalVariableAddrRange Range;
474 std::vector<LocalVariableAddrGap> Gaps;
476 uint32_t RecordOffset = 0;
479 struct DefRangeRegisterHeader {
480 ulittle16_t Register;
481 ulittle16_t MayHaveNoName;
484 // S_DEFRANGE_REGISTER
485 class DefRangeRegisterSym : public SymbolRecord {
487 explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
488 explicit DefRangeRegisterSym(uint32_t RecordOffset)
489 : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
490 RecordOffset(RecordOffset) {}
492 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
494 DefRangeRegisterHeader Hdr;
495 LocalVariableAddrRange Range;
496 std::vector<LocalVariableAddrGap> Gaps;
498 uint32_t RecordOffset = 0;
501 struct DefRangeSubfieldRegisterHeader {
502 ulittle16_t Register;
503 ulittle16_t MayHaveNoName;
504 ulittle32_t OffsetInParent;
507 // S_DEFRANGE_SUBFIELD_REGISTER
508 class DefRangeSubfieldRegisterSym : public SymbolRecord {
510 explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
511 : SymbolRecord(Kind) {}
512 explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
513 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
514 RecordOffset(RecordOffset) {}
516 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
518 DefRangeSubfieldRegisterHeader Hdr;
519 LocalVariableAddrRange Range;
520 std::vector<LocalVariableAddrGap> Gaps;
522 uint32_t RecordOffset = 0;
525 struct DefRangeFramePointerRelHeader {
529 // S_DEFRANGE_FRAMEPOINTER_REL
530 class DefRangeFramePointerRelSym : public SymbolRecord {
531 static constexpr uint32_t RelocationOffset = 8;
534 explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
535 : SymbolRecord(Kind) {}
536 explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
537 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
538 RecordOffset(RecordOffset) {}
540 uint32_t getRelocationOffset() const {
541 return RecordOffset + RelocationOffset;
544 DefRangeFramePointerRelHeader Hdr;
545 LocalVariableAddrRange Range;
546 std::vector<LocalVariableAddrGap> Gaps;
548 uint32_t RecordOffset = 0;
551 struct DefRangeRegisterRelHeader {
552 ulittle16_t Register;
554 little32_t BasePointerOffset;
557 // S_DEFRANGE_REGISTER_REL
558 class DefRangeRegisterRelSym : public SymbolRecord {
560 explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
561 explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
562 : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
563 RecordOffset(RecordOffset) {}
565 // The flags implement this notional bitfield:
566 // uint16_t IsSubfield : 1;
567 // uint16_t Padding : 3;
568 // uint16_t OffsetInParent : 12;
571 OffsetInParentShift = 4,
574 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
575 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
577 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
579 DefRangeRegisterRelHeader Hdr;
580 LocalVariableAddrRange Range;
581 std::vector<LocalVariableAddrGap> Gaps;
583 uint32_t RecordOffset = 0;
586 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
587 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
589 explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
590 : SymbolRecord(Kind) {}
591 explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
592 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
593 RecordOffset(RecordOffset) {}
597 uint32_t RecordOffset = 0;
601 class BlockSym : public SymbolRecord {
602 static constexpr uint32_t RelocationOffset = 16;
605 explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
606 explicit BlockSym(uint32_t RecordOffset)
607 : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
609 uint32_t getRelocationOffset() const {
610 return RecordOffset + RelocationOffset;
615 uint32_t CodeSize = 0;
616 uint32_t CodeOffset = 0;
617 uint16_t Segment = 0;
620 uint32_t RecordOffset = 0;
624 class LabelSym : public SymbolRecord {
625 static constexpr uint32_t RelocationOffset = 4;
628 explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
629 explicit LabelSym(uint32_t RecordOffset)
630 : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
632 uint32_t getRelocationOffset() const {
633 return RecordOffset + RelocationOffset;
636 uint32_t CodeOffset = 0;
637 uint16_t Segment = 0;
638 ProcSymFlags Flags = ProcSymFlags::None;
641 uint32_t RecordOffset = 0;
645 class ObjNameSym : public SymbolRecord {
647 explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
648 explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
649 explicit ObjNameSym(uint32_t RecordOffset)
650 : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
653 uint32_t Signature = 0;
656 uint32_t RecordOffset = 0;
660 class EnvBlockSym : public SymbolRecord {
662 explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
663 explicit EnvBlockSym(uint32_t RecordOffset)
664 : SymbolRecord(SymbolRecordKind::EnvBlockSym),
665 RecordOffset(RecordOffset) {}
667 std::vector<StringRef> Fields;
669 uint32_t RecordOffset = 0;
673 class ExportSym : public SymbolRecord {
675 explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
676 explicit ExportSym(uint32_t RecordOffset)
677 : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
679 uint16_t Ordinal = 0;
680 ExportFlags Flags = ExportFlags::None;
683 uint32_t RecordOffset = 0;
687 class FileStaticSym : public SymbolRecord {
689 explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
690 explicit FileStaticSym(uint32_t RecordOffset)
691 : SymbolRecord(SymbolRecordKind::FileStaticSym),
692 RecordOffset(RecordOffset) {}
695 uint32_t ModFilenameOffset = 0;
696 LocalSymFlags Flags = LocalSymFlags::None;
699 uint32_t RecordOffset = 0;
703 class Compile2Sym : public SymbolRecord {
705 explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
706 explicit Compile2Sym(uint32_t RecordOffset)
707 : SymbolRecord(SymbolRecordKind::Compile2Sym),
708 RecordOffset(RecordOffset) {}
710 CompileSym2Flags Flags = CompileSym2Flags::None;
712 uint16_t VersionFrontendMajor = 0;
713 uint16_t VersionFrontendMinor = 0;
714 uint16_t VersionFrontendBuild = 0;
715 uint16_t VersionBackendMajor = 0;
716 uint16_t VersionBackendMinor = 0;
717 uint16_t VersionBackendBuild = 0;
719 std::vector<StringRef> ExtraStrings;
721 uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
722 uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
724 uint32_t RecordOffset = 0;
728 class Compile3Sym : public SymbolRecord {
730 Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
731 explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
732 explicit Compile3Sym(uint32_t RecordOffset)
733 : SymbolRecord(SymbolRecordKind::Compile3Sym),
734 RecordOffset(RecordOffset) {}
736 CompileSym3Flags Flags = CompileSym3Flags::None;
738 uint16_t VersionFrontendMajor = 0;
739 uint16_t VersionFrontendMinor = 0;
740 uint16_t VersionFrontendBuild = 0;
741 uint16_t VersionFrontendQFE = 0;
742 uint16_t VersionBackendMajor = 0;
743 uint16_t VersionBackendMinor = 0;
744 uint16_t VersionBackendBuild = 0;
745 uint16_t VersionBackendQFE = 0;
748 void setLanguage(SourceLanguage Lang) {
749 Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
752 SourceLanguage getLanguage() const {
753 return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
755 CompileSym3Flags getFlags() const {
756 return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
759 bool hasOptimizations() const {
760 return CompileSym3Flags::None !=
761 (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
764 uint32_t RecordOffset = 0;
768 class FrameProcSym : public SymbolRecord {
770 explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
771 explicit FrameProcSym(uint32_t RecordOffset)
772 : SymbolRecord(SymbolRecordKind::FrameProcSym),
773 RecordOffset(RecordOffset) {}
775 uint32_t TotalFrameBytes = 0;
776 uint32_t PaddingFrameBytes = 0;
777 uint32_t OffsetToPadding = 0;
778 uint32_t BytesOfCalleeSavedRegisters = 0;
779 uint32_t OffsetOfExceptionHandler = 0;
780 uint16_t SectionIdOfExceptionHandler = 0;
781 FrameProcedureOptions Flags = FrameProcedureOptions::None;
783 /// Extract the register this frame uses to refer to local variables.
784 RegisterId getLocalFramePtrReg(CPUType CPU) const {
785 return decodeFramePtrReg(
786 EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
789 /// Extract the register this frame uses to refer to parameters.
790 RegisterId getParamFramePtrReg(CPUType CPU) const {
791 return decodeFramePtrReg(
792 EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
795 uint32_t RecordOffset = 0;
801 class CallSiteInfoSym : public SymbolRecord {
802 static constexpr uint32_t RelocationOffset = 4;
805 explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
806 explicit CallSiteInfoSym(uint32_t RecordOffset)
807 : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
809 uint32_t getRelocationOffset() const {
810 return RecordOffset + RelocationOffset;
813 uint32_t CodeOffset = 0;
814 uint16_t Segment = 0;
817 uint32_t RecordOffset = 0;
821 class HeapAllocationSiteSym : public SymbolRecord {
822 static constexpr uint32_t RelocationOffset = 4;
825 explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
826 explicit HeapAllocationSiteSym(uint32_t RecordOffset)
827 : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
828 RecordOffset(RecordOffset) {}
830 uint32_t getRelocationOffset() const {
831 return RecordOffset + RelocationOffset;
834 uint32_t CodeOffset = 0;
835 uint16_t Segment = 0;
836 uint16_t CallInstructionSize = 0;
839 uint32_t RecordOffset = 0;
843 class FrameCookieSym : public SymbolRecord {
844 static constexpr uint32_t RelocationOffset = 4;
847 explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
848 explicit FrameCookieSym(uint32_t RecordOffset)
849 : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
851 uint32_t getRelocationOffset() const {
852 return RecordOffset + RelocationOffset;
855 uint32_t CodeOffset = 0;
856 uint16_t Register = 0;
857 FrameCookieKind CookieKind;
860 uint32_t RecordOffset = 0;
864 class UDTSym : public SymbolRecord {
866 explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
867 explicit UDTSym(uint32_t RecordOffset)
868 : SymbolRecord(SymbolRecordKind::UDTSym) {}
873 uint32_t RecordOffset = 0;
877 class BuildInfoSym : public SymbolRecord {
879 explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
880 explicit BuildInfoSym(uint32_t RecordOffset)
881 : SymbolRecord(SymbolRecordKind::BuildInfoSym),
882 RecordOffset(RecordOffset) {}
886 uint32_t RecordOffset = 0;
890 class BPRelativeSym : public SymbolRecord {
892 explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
893 explicit BPRelativeSym(uint32_t RecordOffset)
894 : SymbolRecord(SymbolRecordKind::BPRelativeSym),
895 RecordOffset(RecordOffset) {}
901 uint32_t RecordOffset = 0;
905 class RegRelativeSym : public SymbolRecord {
907 explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
908 explicit RegRelativeSym(uint32_t RecordOffset)
909 : SymbolRecord(SymbolRecordKind::RegRelativeSym),
910 RecordOffset(RecordOffset) {}
917 uint32_t RecordOffset = 0;
920 // S_CONSTANT, S_MANCONSTANT
921 class ConstantSym : public SymbolRecord {
923 explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
924 explicit ConstantSym(uint32_t RecordOffset)
925 : SymbolRecord(SymbolRecordKind::ConstantSym),
926 RecordOffset(RecordOffset) {}
932 uint32_t RecordOffset = 0;
935 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
936 class DataSym : public SymbolRecord {
937 static constexpr uint32_t RelocationOffset = 8;
940 explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
941 explicit DataSym(uint32_t RecordOffset)
942 : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
944 uint32_t getRelocationOffset() const {
945 return RecordOffset + RelocationOffset;
949 uint32_t DataOffset = 0;
950 uint16_t Segment = 0;
953 uint32_t RecordOffset = 0;
956 // S_LTHREAD32, S_GTHREAD32
957 class ThreadLocalDataSym : public SymbolRecord {
958 static constexpr uint32_t RelocationOffset = 8;
961 explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
962 explicit ThreadLocalDataSym(uint32_t RecordOffset)
963 : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
964 RecordOffset(RecordOffset) {}
966 uint32_t getRelocationOffset() const {
967 return RecordOffset + RelocationOffset;
971 uint32_t DataOffset = 0;
972 uint16_t Segment = 0;
975 uint32_t RecordOffset = 0;
979 class UsingNamespaceSym : public SymbolRecord {
981 explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
982 explicit UsingNamespaceSym(uint32_t RecordOffset)
983 : SymbolRecord(SymbolRecordKind::UsingNamespaceSym),
984 RecordOffset(RecordOffset) {}
988 uint32_t RecordOffset = 0;
992 class AnnotationSym : public SymbolRecord {
994 explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
995 explicit AnnotationSym(uint32_t RecordOffset)
996 : SymbolRecord(SymbolRecordKind::AnnotationSym),
997 RecordOffset(RecordOffset) {}
999 uint32_t CodeOffset = 0;
1000 uint16_t Segment = 0;
1001 std::vector<StringRef> Strings;
1003 uint32_t RecordOffset = 0;
1006 using CVSymbol = CVRecord<SymbolKind>;
1007 using CVSymbolArray = VarStreamArray<CVSymbol>;
1009 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
1012 } // end namespace codeview
1013 } // end namespace llvm
1015 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H