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