[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / include / llvm / DebugInfo / CodeView / SymbolRecord.h
blob6aa589cf33eb52dda9ca0d50593b4c66c863bd5a
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 //===----------------------------------------------------------------------===//
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"
24 #include <cstdint>
25 #include <vector>
27 namespace llvm {
28 namespace codeview {
30 class SymbolRecord {
31 protected:
32 explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
34 public:
35 SymbolRecordKind getKind() const { return Kind; }
37 SymbolRecordKind Kind;
40 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
41 // S_LPROC32_DPC_ID
42 class ProcSym : public SymbolRecord {
43 static constexpr uint32_t RelocationOffset = 32;
45 public:
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;
54 uint32_t Parent = 0;
55 uint32_t End = 0;
56 uint32_t Next = 0;
57 uint32_t CodeSize = 0;
58 uint32_t DbgStart = 0;
59 uint32_t DbgEnd = 0;
60 TypeIndex FunctionType;
61 uint32_t CodeOffset = 0;
62 uint16_t Segment = 0;
63 ProcSymFlags Flags = ProcSymFlags::None;
64 StringRef Name;
66 uint32_t RecordOffset = 0;
69 // S_THUNK32
70 class Thunk32Sym : public SymbolRecord {
71 public:
72 explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
73 Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
74 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
76 uint32_t Parent;
77 uint32_t End;
78 uint32_t Next;
79 uint32_t Offset;
80 uint16_t Segment;
81 uint16_t Length;
82 ThunkOrdinal Thunk;
83 StringRef Name;
84 ArrayRef<uint8_t> VariantData;
86 uint32_t RecordOffset;
89 // S_TRAMPOLINE
90 class TrampolineSym : public SymbolRecord {
91 public:
92 explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
93 TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
94 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
96 TrampolineType Type;
97 uint16_t Size;
98 uint32_t ThunkOffset;
99 uint32_t TargetOffset;
100 uint16_t ThunkSection;
101 uint16_t TargetSection;
103 uint32_t RecordOffset;
106 // S_SECTION
107 class SectionSym : public SymbolRecord {
108 public:
109 explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
110 SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
111 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
113 uint16_t SectionNumber;
114 uint8_t Alignment;
115 uint32_t Rva;
116 uint32_t Length;
117 uint32_t Characteristics;
118 StringRef Name;
120 uint32_t RecordOffset;
123 // S_COFFGROUP
124 class CoffGroupSym : public SymbolRecord {
125 public:
126 explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
127 CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
128 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
130 uint32_t Size;
131 uint32_t Characteristics;
132 uint32_t Offset;
133 uint16_t Segment;
134 StringRef Name;
136 uint32_t RecordOffset;
139 class ScopeEndSym : public SymbolRecord {
140 public:
141 explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
142 ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
143 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
145 uint32_t RecordOffset;
148 class CallerSym : public SymbolRecord {
149 public:
150 explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
151 CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
152 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
154 std::vector<TypeIndex> Indices;
156 uint32_t RecordOffset;
159 struct DecodedAnnotation {
160 StringRef Name;
161 ArrayRef<uint8_t> Bytes;
162 BinaryAnnotationsOpCode OpCode;
163 uint32_t U1 = 0;
164 uint32_t U2 = 0;
165 int32_t S1 = 0;
168 struct BinaryAnnotationIterator
169 : public iterator_facade_base<BinaryAnnotationIterator,
170 std::forward_iterator_tag,
171 DecodedAnnotation> {
172 BinaryAnnotationIterator() = default;
173 BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
174 BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
175 : Data(Other.Data) {}
177 bool operator==(BinaryAnnotationIterator Other) const {
178 return Data == Other.Data;
181 BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
182 Data = Other.Data;
183 return *this;
186 BinaryAnnotationIterator &operator++() {
187 if (!ParseCurrentAnnotation()) {
188 *this = BinaryAnnotationIterator();
189 return *this;
191 Data = Next;
192 Next = ArrayRef<uint8_t>();
193 Current.reset();
194 return *this;
197 const DecodedAnnotation &operator*() {
198 ParseCurrentAnnotation();
199 return Current.getValue();
202 private:
203 static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
204 if (Annotations.empty())
205 return -1;
207 uint8_t FirstByte = Annotations.front();
208 Annotations = Annotations.drop_front();
210 if ((FirstByte & 0x80) == 0x00)
211 return FirstByte;
213 if (Annotations.empty())
214 return -1;
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())
223 return -1;
225 uint8_t ThirdByte = Annotations.front();
226 Annotations = Annotations.drop_front();
228 if (Annotations.empty())
229 return -1;
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;
238 return -1;
241 static int32_t DecodeSignedOperand(uint32_t Operand) {
242 if (Operand & 1)
243 return -(Operand >> 1);
244 return Operand >> 1;
247 static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
248 return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
251 bool ParseCurrentAnnotation() {
252 if (Current.hasValue())
253 return true;
255 Next = Data;
256 uint32_t Op = GetCompressedAnnotation(Next);
257 DecodedAnnotation Result;
258 Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
259 switch (Result.OpCode) {
260 case BinaryAnnotationsOpCode::Invalid:
261 Result.Name = "Invalid";
262 Next = ArrayRef<uint8_t>();
263 break;
264 case BinaryAnnotationsOpCode::CodeOffset:
265 Result.Name = "CodeOffset";
266 Result.U1 = GetCompressedAnnotation(Next);
267 break;
268 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
269 Result.Name = "ChangeCodeOffsetBase";
270 Result.U1 = GetCompressedAnnotation(Next);
271 break;
272 case BinaryAnnotationsOpCode::ChangeCodeOffset:
273 Result.Name = "ChangeCodeOffset";
274 Result.U1 = GetCompressedAnnotation(Next);
275 break;
276 case BinaryAnnotationsOpCode::ChangeCodeLength:
277 Result.Name = "ChangeCodeLength";
278 Result.U1 = GetCompressedAnnotation(Next);
279 break;
280 case BinaryAnnotationsOpCode::ChangeFile:
281 Result.Name = "ChangeFile";
282 Result.U1 = GetCompressedAnnotation(Next);
283 break;
284 case BinaryAnnotationsOpCode::ChangeLineEndDelta:
285 Result.Name = "ChangeLineEndDelta";
286 Result.U1 = GetCompressedAnnotation(Next);
287 break;
288 case BinaryAnnotationsOpCode::ChangeRangeKind:
289 Result.Name = "ChangeRangeKind";
290 Result.U1 = GetCompressedAnnotation(Next);
291 break;
292 case BinaryAnnotationsOpCode::ChangeColumnStart:
293 Result.Name = "ChangeColumnStart";
294 Result.U1 = GetCompressedAnnotation(Next);
295 break;
296 case BinaryAnnotationsOpCode::ChangeColumnEnd:
297 Result.Name = "ChangeColumnEnd";
298 Result.U1 = GetCompressedAnnotation(Next);
299 break;
300 case BinaryAnnotationsOpCode::ChangeLineOffset:
301 Result.Name = "ChangeLineOffset";
302 Result.S1 = DecodeSignedOperand(Next);
303 break;
304 case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
305 Result.Name = "ChangeColumnEndDelta";
306 Result.S1 = DecodeSignedOperand(Next);
307 break;
308 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
309 Result.Name = "ChangeCodeOffsetAndLineOffset";
310 uint32_t Annotation = GetCompressedAnnotation(Next);
311 Result.S1 = DecodeSignedOperand(Annotation >> 4);
312 Result.U1 = Annotation & 0xf;
313 break;
315 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
316 Result.Name = "ChangeCodeLengthAndCodeOffset";
317 Result.U1 = GetCompressedAnnotation(Next);
318 Result.U2 = GetCompressedAnnotation(Next);
319 break;
322 Result.Bytes = Data.take_front(Data.size() - Next.size());
323 Current = Result;
324 return true;
327 Optional<DecodedAnnotation> Current;
328 ArrayRef<uint8_t> Data;
329 ArrayRef<uint8_t> Next;
332 // S_INLINESITE
333 class InlineSiteSym : public SymbolRecord {
334 public:
335 explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
336 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());
345 uint32_t Parent;
346 uint32_t End;
347 TypeIndex Inlinee;
348 std::vector<uint8_t> AnnotationData;
350 uint32_t RecordOffset;
353 // S_PUB32
354 class PublicSym32 : public SymbolRecord {
355 public:
356 PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
357 explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
358 explicit PublicSym32(uint32_t RecordOffset)
359 : SymbolRecord(SymbolRecordKind::PublicSym32),
360 RecordOffset(RecordOffset) {}
362 PublicSymFlags Flags = PublicSymFlags::None;
363 uint32_t Offset = 0;
364 uint16_t Segment = 0;
365 StringRef Name;
367 uint32_t RecordOffset = 0;
370 // S_REGISTER
371 class RegisterSym : public SymbolRecord {
372 public:
373 explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
374 RegisterSym(uint32_t RecordOffset)
375 : SymbolRecord(SymbolRecordKind::RegisterSym),
376 RecordOffset(RecordOffset) {}
378 TypeIndex Index;
379 RegisterId Register;
380 StringRef Name;
382 uint32_t RecordOffset;
385 // S_PROCREF, S_LPROCREF
386 class ProcRefSym : public SymbolRecord {
387 public:
388 explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
389 explicit ProcRefSym(uint32_t RecordOffset)
390 : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
393 uint32_t SumName;
394 uint32_t SymOffset;
395 uint16_t Module;
396 StringRef Name;
398 uint16_t modi() const { return Module - 1; }
399 uint32_t RecordOffset;
402 // S_LOCAL
403 class LocalSym : public SymbolRecord {
404 public:
405 explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
406 explicit LocalSym(uint32_t RecordOffset)
407 : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
409 TypeIndex Type;
410 LocalSymFlags Flags;
411 StringRef Name;
413 uint32_t RecordOffset;
416 struct LocalVariableAddrRange {
417 uint32_t OffsetStart;
418 uint16_t ISectStart;
419 uint16_t Range;
422 struct LocalVariableAddrGap {
423 uint16_t GapStartOffset;
424 uint16_t Range;
427 enum : uint16_t { MaxDefRange = 0xf000 };
429 // S_DEFRANGE
430 class DefRangeSym : public SymbolRecord {
431 static constexpr uint32_t RelocationOffset = 8;
433 public:
434 explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
435 explicit DefRangeSym(uint32_t RecordOffset)
436 : SymbolRecord(SymbolRecordKind::DefRangeSym),
437 RecordOffset(RecordOffset) {}
439 uint32_t getRelocationOffset() const {
440 return RecordOffset + RelocationOffset;
443 uint32_t Program;
444 LocalVariableAddrRange Range;
445 std::vector<LocalVariableAddrGap> Gaps;
447 uint32_t RecordOffset;
450 // S_DEFRANGE_SUBFIELD
451 class DefRangeSubfieldSym : public SymbolRecord {
452 static constexpr uint32_t RelocationOffset = 12;
454 public:
455 explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
456 DefRangeSubfieldSym(uint32_t RecordOffset)
457 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
458 RecordOffset(RecordOffset) {}
460 uint32_t getRelocationOffset() const {
461 return RecordOffset + RelocationOffset;
464 uint32_t Program;
465 uint16_t OffsetInParent;
466 LocalVariableAddrRange Range;
467 std::vector<LocalVariableAddrGap> Gaps;
469 uint32_t RecordOffset;
472 // S_DEFRANGE_REGISTER
473 class DefRangeRegisterSym : public SymbolRecord {
474 public:
475 struct Header {
476 ulittle16_t Register;
477 ulittle16_t MayHaveNoName;
480 explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
481 DefRangeRegisterSym(uint32_t RecordOffset)
482 : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
483 RecordOffset(RecordOffset) {}
485 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
487 Header Hdr;
488 LocalVariableAddrRange Range;
489 std::vector<LocalVariableAddrGap> Gaps;
491 uint32_t RecordOffset;
494 // S_DEFRANGE_SUBFIELD_REGISTER
495 class DefRangeSubfieldRegisterSym : public SymbolRecord {
496 public:
497 struct Header {
498 ulittle16_t Register;
499 ulittle16_t MayHaveNoName;
500 ulittle32_t OffsetInParent;
503 explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
504 : SymbolRecord(Kind) {}
505 DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
506 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
507 RecordOffset(RecordOffset) {}
509 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
511 Header Hdr;
512 LocalVariableAddrRange Range;
513 std::vector<LocalVariableAddrGap> Gaps;
515 uint32_t RecordOffset;
518 // S_DEFRANGE_FRAMEPOINTER_REL
519 class DefRangeFramePointerRelSym : public SymbolRecord {
520 static constexpr uint32_t RelocationOffset = 8;
522 public:
523 struct Header {
524 little32_t Offset;
527 explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
528 : SymbolRecord(Kind) {}
529 DefRangeFramePointerRelSym(uint32_t RecordOffset)
530 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
531 RecordOffset(RecordOffset) {}
533 uint32_t getRelocationOffset() const {
534 return RecordOffset + RelocationOffset;
537 Header Hdr;
538 LocalVariableAddrRange Range;
539 std::vector<LocalVariableAddrGap> Gaps;
541 uint32_t RecordOffset;
544 // S_DEFRANGE_REGISTER_REL
545 class DefRangeRegisterRelSym : public SymbolRecord {
546 public:
547 struct Header {
548 ulittle16_t Register;
549 ulittle16_t Flags;
550 little32_t BasePointerOffset;
553 explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
554 explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
555 : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
556 RecordOffset(RecordOffset) {}
558 // The flags implement this notional bitfield:
559 // uint16_t IsSubfield : 1;
560 // uint16_t Padding : 3;
561 // uint16_t OffsetInParent : 12;
562 enum : uint16_t {
563 IsSubfieldFlag = 1,
564 OffsetInParentShift = 4,
567 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
568 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
570 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
572 Header Hdr;
573 LocalVariableAddrRange Range;
574 std::vector<LocalVariableAddrGap> Gaps;
576 uint32_t RecordOffset;
579 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
580 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
581 public:
582 explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
583 : SymbolRecord(Kind) {}
584 explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
585 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
586 RecordOffset(RecordOffset) {}
588 int32_t Offset;
590 uint32_t RecordOffset;
593 // S_BLOCK32
594 class BlockSym : public SymbolRecord {
595 static constexpr uint32_t RelocationOffset = 16;
597 public:
598 explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
599 explicit BlockSym(uint32_t RecordOffset)
600 : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
602 uint32_t getRelocationOffset() const {
603 return RecordOffset + RelocationOffset;
606 uint32_t Parent;
607 uint32_t End;
608 uint32_t CodeSize;
609 uint32_t CodeOffset;
610 uint16_t Segment;
611 StringRef Name;
613 uint32_t RecordOffset;
616 // S_LABEL32
617 class LabelSym : public SymbolRecord {
618 static constexpr uint32_t RelocationOffset = 4;
620 public:
621 explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
622 explicit LabelSym(uint32_t RecordOffset)
623 : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
625 uint32_t getRelocationOffset() const {
626 return RecordOffset + RelocationOffset;
629 uint32_t CodeOffset;
630 uint16_t Segment;
631 ProcSymFlags Flags;
632 StringRef Name;
634 uint32_t RecordOffset;
637 // S_OBJNAME
638 class ObjNameSym : public SymbolRecord {
639 public:
640 explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
641 explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
642 ObjNameSym(uint32_t RecordOffset)
643 : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
646 uint32_t Signature;
647 StringRef Name;
649 uint32_t RecordOffset;
652 // S_ENVBLOCK
653 class EnvBlockSym : public SymbolRecord {
654 public:
655 explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
656 EnvBlockSym(uint32_t RecordOffset)
657 : SymbolRecord(SymbolRecordKind::EnvBlockSym),
658 RecordOffset(RecordOffset) {}
660 std::vector<StringRef> Fields;
662 uint32_t RecordOffset;
665 // S_EXPORT
666 class ExportSym : public SymbolRecord {
667 public:
668 explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
669 ExportSym(uint32_t RecordOffset)
670 : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
672 uint16_t Ordinal;
673 ExportFlags Flags;
674 StringRef Name;
676 uint32_t RecordOffset;
679 // S_FILESTATIC
680 class FileStaticSym : public SymbolRecord {
681 public:
682 explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
683 FileStaticSym(uint32_t RecordOffset)
684 : SymbolRecord(SymbolRecordKind::FileStaticSym),
685 RecordOffset(RecordOffset) {}
687 TypeIndex Index;
688 uint32_t ModFilenameOffset;
689 LocalSymFlags Flags;
690 StringRef Name;
692 uint32_t RecordOffset;
695 // S_COMPILE2
696 class Compile2Sym : public SymbolRecord {
697 public:
698 explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
699 Compile2Sym(uint32_t RecordOffset)
700 : SymbolRecord(SymbolRecordKind::Compile2Sym),
701 RecordOffset(RecordOffset) {}
703 CompileSym2Flags Flags;
704 CPUType Machine;
705 uint16_t VersionFrontendMajor;
706 uint16_t VersionFrontendMinor;
707 uint16_t VersionFrontendBuild;
708 uint16_t VersionBackendMajor;
709 uint16_t VersionBackendMinor;
710 uint16_t VersionBackendBuild;
711 StringRef Version;
712 std::vector<StringRef> ExtraStrings;
714 uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
715 uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
717 uint32_t RecordOffset;
720 // S_COMPILE3
721 class Compile3Sym : public SymbolRecord {
722 public:
723 Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
724 explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
725 Compile3Sym(uint32_t RecordOffset)
726 : SymbolRecord(SymbolRecordKind::Compile3Sym),
727 RecordOffset(RecordOffset) {}
729 CompileSym3Flags Flags;
730 CPUType Machine;
731 uint16_t VersionFrontendMajor;
732 uint16_t VersionFrontendMinor;
733 uint16_t VersionFrontendBuild;
734 uint16_t VersionFrontendQFE;
735 uint16_t VersionBackendMajor;
736 uint16_t VersionBackendMinor;
737 uint16_t VersionBackendBuild;
738 uint16_t VersionBackendQFE;
739 StringRef Version;
741 void setLanguage(SourceLanguage Lang) {
742 Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
745 SourceLanguage getLanguage() const {
746 return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
748 CompileSym3Flags getFlags() const {
749 return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
752 bool hasOptimizations() const {
753 return CompileSym3Flags::None !=
754 (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
757 uint32_t RecordOffset;
760 // S_FRAMEPROC
761 class FrameProcSym : public SymbolRecord {
762 public:
763 explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
764 explicit FrameProcSym(uint32_t RecordOffset)
765 : SymbolRecord(SymbolRecordKind::FrameProcSym),
766 RecordOffset(RecordOffset) {}
768 uint32_t TotalFrameBytes;
769 uint32_t PaddingFrameBytes;
770 uint32_t OffsetToPadding;
771 uint32_t BytesOfCalleeSavedRegisters;
772 uint32_t OffsetOfExceptionHandler;
773 uint16_t SectionIdOfExceptionHandler;
774 FrameProcedureOptions Flags;
776 /// Extract the register this frame uses to refer to local variables.
777 RegisterId getLocalFramePtrReg(CPUType CPU) const {
778 return decodeFramePtrReg(
779 EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
782 /// Extract the register this frame uses to refer to parameters.
783 RegisterId getParamFramePtrReg(CPUType CPU) const {
784 return decodeFramePtrReg(
785 EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
788 uint32_t RecordOffset;
790 private:
793 // S_CALLSITEINFO
794 class CallSiteInfoSym : public SymbolRecord {
795 static constexpr uint32_t RelocationOffset = 4;
797 public:
798 explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
799 explicit CallSiteInfoSym(uint32_t RecordOffset)
800 : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
802 uint32_t getRelocationOffset() const {
803 return RecordOffset + RelocationOffset;
806 uint32_t CodeOffset;
807 uint16_t Segment;
808 TypeIndex Type;
810 uint32_t RecordOffset;
813 // S_HEAPALLOCSITE
814 class HeapAllocationSiteSym : public SymbolRecord {
815 static constexpr uint32_t RelocationOffset = 4;
817 public:
818 explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
819 explicit HeapAllocationSiteSym(uint32_t RecordOffset)
820 : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
821 RecordOffset(RecordOffset) {}
823 uint32_t getRelocationOffset() const {
824 return RecordOffset + RelocationOffset;
827 uint32_t CodeOffset;
828 uint16_t Segment;
829 uint16_t CallInstructionSize;
830 TypeIndex Type;
832 uint32_t RecordOffset;
835 // S_FRAMECOOKIE
836 class FrameCookieSym : public SymbolRecord {
837 static constexpr uint32_t RelocationOffset = 4;
839 public:
840 explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
841 explicit FrameCookieSym(uint32_t RecordOffset)
842 : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
844 uint32_t getRelocationOffset() const {
845 return RecordOffset + RelocationOffset;
848 uint32_t CodeOffset;
849 uint16_t Register;
850 FrameCookieKind CookieKind;
851 uint8_t Flags;
853 uint32_t RecordOffset;
856 // S_UDT, S_COBOLUDT
857 class UDTSym : public SymbolRecord {
858 public:
859 explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
860 explicit UDTSym(uint32_t RecordOffset)
861 : SymbolRecord(SymbolRecordKind::UDTSym) {}
863 TypeIndex Type;
864 StringRef Name;
866 uint32_t RecordOffset;
869 // S_BUILDINFO
870 class BuildInfoSym : public SymbolRecord {
871 public:
872 explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
873 BuildInfoSym(uint32_t RecordOffset)
874 : SymbolRecord(SymbolRecordKind::BuildInfoSym),
875 RecordOffset(RecordOffset) {}
877 TypeIndex BuildId;
879 uint32_t RecordOffset;
882 // S_BPREL32
883 class BPRelativeSym : public SymbolRecord {
884 public:
885 explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
886 explicit BPRelativeSym(uint32_t RecordOffset)
887 : SymbolRecord(SymbolRecordKind::BPRelativeSym),
888 RecordOffset(RecordOffset) {}
890 int32_t Offset;
891 TypeIndex Type;
892 StringRef Name;
894 uint32_t RecordOffset;
897 // S_REGREL32
898 class RegRelativeSym : public SymbolRecord {
899 public:
900 explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
901 explicit RegRelativeSym(uint32_t RecordOffset)
902 : SymbolRecord(SymbolRecordKind::RegRelativeSym),
903 RecordOffset(RecordOffset) {}
905 uint32_t Offset;
906 TypeIndex Type;
907 RegisterId Register;
908 StringRef Name;
910 uint32_t RecordOffset;
913 // S_CONSTANT, S_MANCONSTANT
914 class ConstantSym : public SymbolRecord {
915 public:
916 explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
917 ConstantSym(uint32_t RecordOffset)
918 : SymbolRecord(SymbolRecordKind::ConstantSym),
919 RecordOffset(RecordOffset) {}
921 TypeIndex Type;
922 APSInt Value;
923 StringRef Name;
925 uint32_t RecordOffset;
928 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
929 class DataSym : public SymbolRecord {
930 static constexpr uint32_t RelocationOffset = 8;
932 public:
933 explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
934 DataSym(uint32_t RecordOffset)
935 : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
937 uint32_t getRelocationOffset() const {
938 return RecordOffset + RelocationOffset;
941 TypeIndex Type;
942 uint32_t DataOffset;
943 uint16_t Segment;
944 StringRef Name;
946 uint32_t RecordOffset;
949 // S_LTHREAD32, S_GTHREAD32
950 class ThreadLocalDataSym : public SymbolRecord {
951 static constexpr uint32_t RelocationOffset = 8;
953 public:
954 explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
955 explicit ThreadLocalDataSym(uint32_t RecordOffset)
956 : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
957 RecordOffset(RecordOffset) {}
959 uint32_t getRelocationOffset() const {
960 return RecordOffset + RelocationOffset;
963 TypeIndex Type;
964 uint32_t DataOffset;
965 uint16_t Segment;
966 StringRef Name;
968 uint32_t RecordOffset;
971 // S_UNAMESPACE
972 class UsingNamespaceSym : public SymbolRecord {
973 public:
974 explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
975 explicit UsingNamespaceSym(uint32_t RecordOffset)
976 : SymbolRecord(SymbolRecordKind::UsingNamespaceSym),
977 RecordOffset(RecordOffset) {}
979 StringRef Name;
981 uint32_t RecordOffset;
984 // S_ANNOTATION
985 class AnnotationSym : public SymbolRecord {
986 public:
987 explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
988 explicit AnnotationSym(uint32_t RecordOffset)
989 : SymbolRecord(SymbolRecordKind::AnnotationSym),
990 RecordOffset(RecordOffset) {}
992 uint32_t CodeOffset = 0;
993 uint16_t Segment = 0;
994 std::vector<StringRef> Strings;
996 uint32_t RecordOffset;
999 using CVSymbol = CVRecord<SymbolKind>;
1000 using CVSymbolArray = VarStreamArray<CVSymbol>;
1002 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
1003 uint32_t Offset);
1005 } // end namespace codeview
1006 } // end namespace llvm
1008 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H