4383534b0db2830421e421c049351e29bc112a7d
[lldb.git] / llvm / include / llvm / DebugInfo / CodeView / SymbolRecord.h
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 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
10 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
11
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>
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 = 0;
77   uint32_t End = 0;
78   uint32_t Next = 0;
79   uint32_t Offset = 0;
80   uint16_t Segment = 0;
81   uint16_t Length = 0;
82   ThunkOrdinal Thunk = ThunkOrdinal::Standard;
83   StringRef Name;
84   ArrayRef<uint8_t> VariantData;
85
86   uint32_t RecordOffset = 0;
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 = 0;
98   uint32_t ThunkOffset = 0;
99   uint32_t TargetOffset = 0;
100   uint16_t ThunkSection = 0;
101   uint16_t TargetSection = 0;
102
103   uint32_t RecordOffset = 0;
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 = 0;
114   uint8_t Alignment = 0;
115   uint32_t Rva = 0;
116   uint32_t Length = 0;
117   uint32_t Characteristics = 0;
118   StringRef Name;
119
120   uint32_t RecordOffset = 0;
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 = 0;
131   uint32_t Characteristics = 0;
132   uint32_t Offset = 0;
133   uint16_t Segment = 0;
134   StringRef Name;
135
136   uint32_t RecordOffset = 0;
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 = 0;
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 = 0;
157 };
158
159 struct DecodedAnnotation {
160   StringRef Name;
161   ArrayRef<uint8_t> Bytes;
162   BinaryAnnotationsOpCode OpCode = BinaryAnnotationsOpCode::Invalid;
163   uint32_t U1 = 0;
164   uint32_t U2 = 0;
165   int32_t S1 = 0;
166 };
167
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) {}
176
177   bool operator==(BinaryAnnotationIterator Other) const {
178     return Data == Other.Data;
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   const DecodedAnnotation &operator*() {
198     ParseCurrentAnnotation();
199     return Current.getValue();
200   }
201
202 private:
203   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
204     if (Annotations.empty())
205       return -1;
206
207     uint8_t FirstByte = Annotations.front();
208     Annotations = Annotations.drop_front();
209
210     if ((FirstByte & 0x80) == 0x00)
211       return FirstByte;
212
213     if (Annotations.empty())
214       return -1;
215
216     uint8_t SecondByte = Annotations.front();
217     Annotations = Annotations.drop_front();
218
219     if ((FirstByte & 0xC0) == 0x80)
220       return ((FirstByte & 0x3F) << 8) | SecondByte;
221
222     if (Annotations.empty())
223       return -1;
224
225     uint8_t ThirdByte = Annotations.front();
226     Annotations = Annotations.drop_front();
227
228     if (Annotations.empty())
229       return -1;
230
231     uint8_t FourthByte = Annotations.front();
232     Annotations = Annotations.drop_front();
233
234     if ((FirstByte & 0xE0) == 0xC0)
235       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
236              (ThirdByte << 8) | FourthByte;
237
238     return -1;
239   }
240
241   static int32_t DecodeSignedOperand(uint32_t Operand) {
242     if (Operand & 1)
243       return -(Operand >> 1);
244     return Operand >> 1;
245   }
246
247   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
248     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
249   }
250
251   bool ParseCurrentAnnotation() {
252     if (Current.hasValue())
253       return true;
254
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;
314     }
315     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
316       Result.Name = "ChangeCodeLengthAndCodeOffset";
317       Result.U1 = GetCompressedAnnotation(Next);
318       Result.U2 = GetCompressedAnnotation(Next);
319       break;
320     }
321     }
322     Result.Bytes = Data.take_front(Data.size() - Next.size());
323     Current = Result;
324     return true;
325   }
326
327   Optional<DecodedAnnotation> Current;
328   ArrayRef<uint8_t> Data;
329   ArrayRef<uint8_t> Next;
330 };
331
332 // S_INLINESITE
333 class InlineSiteSym : public SymbolRecord {
334 public:
335   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
336   explicit InlineSiteSym(uint32_t RecordOffset)
337       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
338         RecordOffset(RecordOffset) {}
339
340   iterator_range<BinaryAnnotationIterator> annotations() const {
341     return make_range(BinaryAnnotationIterator(AnnotationData),
342                       BinaryAnnotationIterator());
343   }
344
345   uint32_t Parent = 0;
346   uint32_t End = 0;
347   TypeIndex Inlinee;
348   std::vector<uint8_t> AnnotationData;
349
350   uint32_t RecordOffset = 0;
351 };
352
353 struct PublicSym32Header {
354   ulittle32_t Flags;
355   ulittle32_t Offset;
356   ulittle16_t Segment;
357   // char Name[];
358 };
359
360 // S_PUB32
361 class PublicSym32 : public SymbolRecord {
362 public:
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) {}
368
369   PublicSymFlags Flags = PublicSymFlags::None;
370   uint32_t Offset = 0;
371   uint16_t Segment = 0;
372   StringRef Name;
373
374   uint32_t RecordOffset = 0;
375 };
376
377 // S_REGISTER
378 class RegisterSym : public SymbolRecord {
379 public:
380   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
381   explicit RegisterSym(uint32_t RecordOffset)
382       : SymbolRecord(SymbolRecordKind::RegisterSym),
383         RecordOffset(RecordOffset) {}
384
385   TypeIndex Index;
386   RegisterId Register;
387   StringRef Name;
388
389   uint32_t RecordOffset = 0;
390 };
391
392 // S_PROCREF, S_LPROCREF
393 class ProcRefSym : public SymbolRecord {
394 public:
395   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
396   explicit ProcRefSym(uint32_t RecordOffset)
397       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
398   }
399
400   uint32_t SumName = 0;
401   uint32_t SymOffset = 0;
402   uint16_t Module = 0;
403   StringRef Name;
404
405   uint16_t modi() const { return Module - 1; }
406   uint32_t RecordOffset = 0;
407 };
408
409 // S_LOCAL
410 class LocalSym : public SymbolRecord {
411 public:
412   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
413   explicit LocalSym(uint32_t RecordOffset)
414       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
415
416   TypeIndex Type;
417   LocalSymFlags Flags = LocalSymFlags::None;
418   StringRef Name;
419
420   uint32_t RecordOffset = 0;
421 };
422
423 struct LocalVariableAddrRange {
424   uint32_t OffsetStart = 0;
425   uint16_t ISectStart = 0;
426   uint16_t Range = 0;
427 };
428
429 struct LocalVariableAddrGap {
430   uint16_t GapStartOffset = 0;
431   uint16_t Range = 0;
432 };
433
434 enum : uint16_t { MaxDefRange = 0xf000 };
435
436 // S_DEFRANGE
437 class DefRangeSym : public SymbolRecord {
438   static constexpr uint32_t RelocationOffset = 8;
439
440 public:
441   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
442   explicit DefRangeSym(uint32_t RecordOffset)
443       : SymbolRecord(SymbolRecordKind::DefRangeSym),
444         RecordOffset(RecordOffset) {}
445
446   uint32_t getRelocationOffset() const {
447     return RecordOffset + RelocationOffset;
448   }
449
450   uint32_t Program = 0;
451   LocalVariableAddrRange Range;
452   std::vector<LocalVariableAddrGap> Gaps;
453
454   uint32_t RecordOffset = 0;
455 };
456
457 // S_DEFRANGE_SUBFIELD
458 class DefRangeSubfieldSym : public SymbolRecord {
459   static constexpr uint32_t RelocationOffset = 12;
460
461 public:
462   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
463   explicit DefRangeSubfieldSym(uint32_t RecordOffset)
464       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
465         RecordOffset(RecordOffset) {}
466
467   uint32_t getRelocationOffset() const {
468     return RecordOffset + RelocationOffset;
469   }
470
471   uint32_t Program = 0;
472   uint16_t OffsetInParent = 0;
473   LocalVariableAddrRange Range;
474   std::vector<LocalVariableAddrGap> Gaps;
475
476   uint32_t RecordOffset = 0;
477 };
478
479 struct DefRangeRegisterHeader {
480   ulittle16_t Register;
481   ulittle16_t MayHaveNoName;
482 };
483
484 // S_DEFRANGE_REGISTER
485 class DefRangeRegisterSym : public SymbolRecord {
486 public:
487   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
488   explicit DefRangeRegisterSym(uint32_t RecordOffset)
489       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
490         RecordOffset(RecordOffset) {}
491
492   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
493
494   DefRangeRegisterHeader Hdr;
495   LocalVariableAddrRange Range;
496   std::vector<LocalVariableAddrGap> Gaps;
497
498   uint32_t RecordOffset = 0;
499 };
500
501 struct DefRangeSubfieldRegisterHeader {
502   ulittle16_t Register;
503   ulittle16_t MayHaveNoName;
504   ulittle32_t OffsetInParent;
505 };
506
507 // S_DEFRANGE_SUBFIELD_REGISTER
508 class DefRangeSubfieldRegisterSym : public SymbolRecord {
509 public:
510   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
511       : SymbolRecord(Kind) {}
512   explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
513       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
514         RecordOffset(RecordOffset) {}
515
516   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
517
518   DefRangeSubfieldRegisterHeader Hdr;
519   LocalVariableAddrRange Range;
520   std::vector<LocalVariableAddrGap> Gaps;
521
522   uint32_t RecordOffset = 0;
523 };
524
525 struct DefRangeFramePointerRelHeader {
526   little32_t Offset;
527 };
528
529 // S_DEFRANGE_FRAMEPOINTER_REL
530 class DefRangeFramePointerRelSym : public SymbolRecord {
531   static constexpr uint32_t RelocationOffset = 8;
532
533 public:
534   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
535       : SymbolRecord(Kind) {}
536   explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
537       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
538         RecordOffset(RecordOffset) {}
539
540   uint32_t getRelocationOffset() const {
541     return RecordOffset + RelocationOffset;
542   }
543
544   DefRangeFramePointerRelHeader Hdr;
545   LocalVariableAddrRange Range;
546   std::vector<LocalVariableAddrGap> Gaps;
547
548   uint32_t RecordOffset = 0;
549 };
550
551 struct DefRangeRegisterRelHeader {
552   ulittle16_t Register;
553   ulittle16_t Flags;
554   little32_t BasePointerOffset;
555 };
556
557 // S_DEFRANGE_REGISTER_REL
558 class DefRangeRegisterRelSym : public SymbolRecord {
559 public:
560   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
561   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
562       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
563         RecordOffset(RecordOffset) {}
564
565   // The flags implement this notional bitfield:
566   //   uint16_t IsSubfield : 1;
567   //   uint16_t Padding : 3;
568   //   uint16_t OffsetInParent : 12;
569   enum : uint16_t {
570     IsSubfieldFlag = 1,
571     OffsetInParentShift = 4,
572   };
573
574   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
575   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
576
577   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
578
579   DefRangeRegisterRelHeader Hdr;
580   LocalVariableAddrRange Range;
581   std::vector<LocalVariableAddrGap> Gaps;
582
583   uint32_t RecordOffset = 0;
584 };
585
586 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
587 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
588 public:
589   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
590       : SymbolRecord(Kind) {}
591   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
592       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
593         RecordOffset(RecordOffset) {}
594
595   int32_t Offset = 0;
596
597   uint32_t RecordOffset = 0;
598 };
599
600 // S_BLOCK32
601 class BlockSym : public SymbolRecord {
602   static constexpr uint32_t RelocationOffset = 16;
603
604 public:
605   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
606   explicit BlockSym(uint32_t RecordOffset)
607       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
608
609   uint32_t getRelocationOffset() const {
610     return RecordOffset + RelocationOffset;
611   }
612
613   uint32_t Parent = 0;
614   uint32_t End = 0;
615   uint32_t CodeSize = 0;
616   uint32_t CodeOffset = 0;
617   uint16_t Segment = 0;
618   StringRef Name;
619
620   uint32_t RecordOffset = 0;
621 };
622
623 // S_LABEL32
624 class LabelSym : public SymbolRecord {
625   static constexpr uint32_t RelocationOffset = 4;
626
627 public:
628   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
629   explicit LabelSym(uint32_t RecordOffset)
630       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
631
632   uint32_t getRelocationOffset() const {
633     return RecordOffset + RelocationOffset;
634   }
635
636   uint32_t CodeOffset = 0;
637   uint16_t Segment = 0;
638   ProcSymFlags Flags = ProcSymFlags::None;
639   StringRef Name;
640
641   uint32_t RecordOffset = 0;
642 };
643
644 // S_OBJNAME
645 class ObjNameSym : public SymbolRecord {
646 public:
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) {
651   }
652
653   uint32_t Signature = 0;
654   StringRef Name;
655
656   uint32_t RecordOffset = 0;
657 };
658
659 // S_ENVBLOCK
660 class EnvBlockSym : public SymbolRecord {
661 public:
662   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
663   explicit EnvBlockSym(uint32_t RecordOffset)
664       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
665         RecordOffset(RecordOffset) {}
666
667   std::vector<StringRef> Fields;
668
669   uint32_t RecordOffset = 0;
670 };
671
672 // S_EXPORT
673 class ExportSym : public SymbolRecord {
674 public:
675   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
676   explicit ExportSym(uint32_t RecordOffset)
677       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
678
679   uint16_t Ordinal = 0;
680   ExportFlags Flags = ExportFlags::None;
681   StringRef Name;
682
683   uint32_t RecordOffset = 0;
684 };
685
686 // S_FILESTATIC
687 class FileStaticSym : public SymbolRecord {
688 public:
689   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
690   explicit FileStaticSym(uint32_t RecordOffset)
691       : SymbolRecord(SymbolRecordKind::FileStaticSym),
692         RecordOffset(RecordOffset) {}
693
694   TypeIndex Index;
695   uint32_t ModFilenameOffset = 0;
696   LocalSymFlags Flags = LocalSymFlags::None;
697   StringRef Name;
698
699   uint32_t RecordOffset = 0;
700 };
701
702 // S_COMPILE2
703 class Compile2Sym : public SymbolRecord {
704 public:
705   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
706   explicit Compile2Sym(uint32_t RecordOffset)
707       : SymbolRecord(SymbolRecordKind::Compile2Sym),
708         RecordOffset(RecordOffset) {}
709
710   CompileSym2Flags Flags = CompileSym2Flags::None;
711   CPUType Machine;
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;
718   StringRef Version;
719   std::vector<StringRef> ExtraStrings;
720
721   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
722   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
723
724   uint32_t RecordOffset = 0;
725 };
726
727 // S_COMPILE3
728 class Compile3Sym : public SymbolRecord {
729 public:
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) {}
735
736   CompileSym3Flags Flags = CompileSym3Flags::None;
737   CPUType Machine;
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;
746   StringRef Version;
747
748   void setLanguage(SourceLanguage Lang) {
749     Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
750   }
751
752   SourceLanguage getLanguage() const {
753     return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
754   }
755   CompileSym3Flags getFlags() const {
756     return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
757   }
758
759   bool hasOptimizations() const {
760     return CompileSym3Flags::None !=
761            (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
762   }
763
764   uint32_t RecordOffset = 0;
765 };
766
767 // S_FRAMEPROC
768 class FrameProcSym : public SymbolRecord {
769 public:
770   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
771   explicit FrameProcSym(uint32_t RecordOffset)
772       : SymbolRecord(SymbolRecordKind::FrameProcSym),
773         RecordOffset(RecordOffset) {}
774
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;
782
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);
787   }
788
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);
793   }
794
795   uint32_t RecordOffset = 0;
796
797 private:
798 };
799
800 // S_CALLSITEINFO
801 class CallSiteInfoSym : public SymbolRecord {
802   static constexpr uint32_t RelocationOffset = 4;
803
804 public:
805   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
806   explicit CallSiteInfoSym(uint32_t RecordOffset)
807       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
808
809   uint32_t getRelocationOffset() const {
810     return RecordOffset + RelocationOffset;
811   }
812
813   uint32_t CodeOffset = 0;
814   uint16_t Segment = 0;
815   TypeIndex Type;
816
817   uint32_t RecordOffset = 0;
818 };
819
820 // S_HEAPALLOCSITE
821 class HeapAllocationSiteSym : public SymbolRecord {
822   static constexpr uint32_t RelocationOffset = 4;
823
824 public:
825   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
826   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
827       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
828         RecordOffset(RecordOffset) {}
829
830   uint32_t getRelocationOffset() const {
831     return RecordOffset + RelocationOffset;
832   }
833
834   uint32_t CodeOffset = 0;
835   uint16_t Segment = 0;
836   uint16_t CallInstructionSize = 0;
837   TypeIndex Type;
838
839   uint32_t RecordOffset = 0;
840 };
841
842 // S_FRAMECOOKIE
843 class FrameCookieSym : public SymbolRecord {
844   static constexpr uint32_t RelocationOffset = 4;
845
846 public:
847   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
848   explicit FrameCookieSym(uint32_t RecordOffset)
849       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
850
851   uint32_t getRelocationOffset() const {
852     return RecordOffset + RelocationOffset;
853   }
854
855   uint32_t CodeOffset = 0;
856   uint16_t Register = 0;
857   FrameCookieKind CookieKind;
858   uint8_t Flags = 0;
859
860   uint32_t RecordOffset = 0;
861 };
862
863 // S_UDT, S_COBOLUDT
864 class UDTSym : public SymbolRecord {
865 public:
866   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
867   explicit UDTSym(uint32_t RecordOffset)
868       : SymbolRecord(SymbolRecordKind::UDTSym) {}
869
870   TypeIndex Type;
871   StringRef Name;
872
873   uint32_t RecordOffset = 0;
874 };
875
876 // S_BUILDINFO
877 class BuildInfoSym : public SymbolRecord {
878 public:
879   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
880   explicit BuildInfoSym(uint32_t RecordOffset)
881       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
882         RecordOffset(RecordOffset) {}
883
884   TypeIndex BuildId;
885
886   uint32_t RecordOffset = 0;
887 };
888
889 // S_BPREL32
890 class BPRelativeSym : public SymbolRecord {
891 public:
892   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
893   explicit BPRelativeSym(uint32_t RecordOffset)
894       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
895         RecordOffset(RecordOffset) {}
896
897   int32_t Offset = 0;
898   TypeIndex Type;
899   StringRef Name;
900
901   uint32_t RecordOffset = 0;
902 };
903
904 // S_REGREL32
905 class RegRelativeSym : public SymbolRecord {
906 public:
907   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
908   explicit RegRelativeSym(uint32_t RecordOffset)
909       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
910         RecordOffset(RecordOffset) {}
911
912   uint32_t Offset = 0;
913   TypeIndex Type;
914   RegisterId Register;
915   StringRef Name;
916
917   uint32_t RecordOffset = 0;
918 };
919
920 // S_CONSTANT, S_MANCONSTANT
921 class ConstantSym : public SymbolRecord {
922 public:
923   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
924   explicit ConstantSym(uint32_t RecordOffset)
925       : SymbolRecord(SymbolRecordKind::ConstantSym),
926         RecordOffset(RecordOffset) {}
927
928   TypeIndex Type;
929   APSInt Value;
930   StringRef Name;
931
932   uint32_t RecordOffset = 0;
933 };
934
935 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
936 class DataSym : public SymbolRecord {
937   static constexpr uint32_t RelocationOffset = 8;
938
939 public:
940   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
941   explicit DataSym(uint32_t RecordOffset)
942       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
943
944   uint32_t getRelocationOffset() const {
945     return RecordOffset + RelocationOffset;
946   }
947
948   TypeIndex Type;
949   uint32_t DataOffset = 0;
950   uint16_t Segment = 0;
951   StringRef Name;
952
953   uint32_t RecordOffset = 0;
954 };
955
956 // S_LTHREAD32, S_GTHREAD32
957 class ThreadLocalDataSym : public SymbolRecord {
958   static constexpr uint32_t RelocationOffset = 8;
959
960 public:
961   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
962   explicit ThreadLocalDataSym(uint32_t RecordOffset)
963       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
964         RecordOffset(RecordOffset) {}
965
966   uint32_t getRelocationOffset() const {
967     return RecordOffset + RelocationOffset;
968   }
969
970   TypeIndex Type;
971   uint32_t DataOffset = 0;
972   uint16_t Segment = 0;
973   StringRef Name;
974
975   uint32_t RecordOffset = 0;
976 };
977
978 // S_UNAMESPACE
979 class UsingNamespaceSym : public SymbolRecord {
980 public:
981   explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
982   explicit UsingNamespaceSym(uint32_t RecordOffset)
983       : SymbolRecord(SymbolRecordKind::UsingNamespaceSym),
984         RecordOffset(RecordOffset) {}
985
986   StringRef Name;
987
988   uint32_t RecordOffset = 0;
989 };
990
991 // S_ANNOTATION
992 class AnnotationSym : public SymbolRecord {
993 public:
994   explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
995   explicit AnnotationSym(uint32_t RecordOffset)
996       : SymbolRecord(SymbolRecordKind::AnnotationSym),
997         RecordOffset(RecordOffset) {}
998
999   uint32_t CodeOffset = 0;
1000   uint16_t Segment = 0;
1001   std::vector<StringRef> Strings;
1002
1003   uint32_t RecordOffset = 0;
1004 };
1005
1006 using CVSymbol = CVRecord<SymbolKind>;
1007 using CVSymbolArray = VarStreamArray<CVSymbol>;
1008
1009 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
1010                                         uint32_t Offset);
1011
1012 } // end namespace codeview
1013 } // end namespace llvm
1014
1015 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H