• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SymbolRecord(SymbolRecordKind Kind)32   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
33 
34 public:
getKind()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:
ProcSym(SymbolRecordKind Kind)46   explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ProcSym(SymbolRecordKind Kind,uint32_t RecordOffset)47   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
48       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
49 
getRelocationOffset()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:
Thunk32Sym(SymbolRecordKind Kind)72   explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Thunk32Sym(SymbolRecordKind Kind,uint32_t RecordOffset)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:
TrampolineSym(SymbolRecordKind Kind)92   explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
TrampolineSym(SymbolRecordKind Kind,uint32_t RecordOffset)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:
SectionSym(SymbolRecordKind Kind)109   explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
SectionSym(SymbolRecordKind Kind,uint32_t RecordOffset)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:
CoffGroupSym(SymbolRecordKind Kind)126   explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CoffGroupSym(SymbolRecordKind Kind,uint32_t RecordOffset)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:
ScopeEndSym(SymbolRecordKind Kind)141   explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ScopeEndSym(SymbolRecordKind Kind,uint32_t RecordOffset)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:
CallerSym(SymbolRecordKind Kind)150   explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CallerSym(SymbolRecordKind Kind,uint32_t RecordOffset)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;
BinaryAnnotationIteratorBinaryAnnotationIterator169   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
BinaryAnnotationIteratorBinaryAnnotationIterator170   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:
GetCompressedAnnotationBinaryAnnotationIterator209   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 
DecodeSignedOperandBinaryAnnotationIterator247   static int32_t DecodeSignedOperand(uint32_t Operand) {
248     if (Operand & 1)
249       return -(Operand >> 1);
250     return Operand >> 1;
251   };
252 
DecodeSignedOperandBinaryAnnotationIterator253   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
254     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
255   };
256 
ParseCurrentAnnotationBinaryAnnotationIterator257   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:
InlineSiteSym(SymbolRecordKind Kind)340   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
InlineSiteSym(uint32_t RecordOffset)341   InlineSiteSym(uint32_t RecordOffset)
342       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
343         RecordOffset(RecordOffset) {}
344 
annotations()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:
PublicSym32(SymbolRecordKind Kind)361   explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
PublicSym32(uint32_t RecordOffset)362   explicit PublicSym32(uint32_t RecordOffset)
363       : SymbolRecord(SymbolRecordKind::PublicSym32),
364         RecordOffset(RecordOffset) {}
365 
366   PublicSymFlags Flags = PublicSymFlags::None;
367   uint32_t Offset = 0;
368   uint16_t Segment = 0;
369   StringRef Name;
370 
371   uint32_t RecordOffset = 0;
372 };
373 
374 // S_REGISTER
375 class RegisterSym : public SymbolRecord {
376 public:
RegisterSym(SymbolRecordKind Kind)377   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
RegisterSym(uint32_t RecordOffset)378   RegisterSym(uint32_t RecordOffset)
379       : SymbolRecord(SymbolRecordKind::RegisterSym),
380         RecordOffset(RecordOffset) {}
381 
382   TypeIndex Index;
383   RegisterId Register;
384   StringRef Name;
385 
386   uint32_t RecordOffset;
387 };
388 
389 // S_PROCREF, S_LPROCREF
390 class ProcRefSym : public SymbolRecord {
391 public:
ProcRefSym(SymbolRecordKind Kind)392   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ProcRefSym(uint32_t RecordOffset)393   explicit ProcRefSym(uint32_t RecordOffset)
394       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
395   }
396 
397   uint32_t SumName;
398   uint32_t SymOffset;
399   uint16_t Module;
400   StringRef Name;
401 
402   uint32_t RecordOffset;
403 };
404 
405 // S_LOCAL
406 class LocalSym : public SymbolRecord {
407 public:
LocalSym(SymbolRecordKind Kind)408   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
LocalSym(uint32_t RecordOffset)409   explicit LocalSym(uint32_t RecordOffset)
410       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
411 
412   TypeIndex Type;
413   LocalSymFlags Flags;
414   StringRef Name;
415 
416   uint32_t RecordOffset;
417 };
418 
419 struct LocalVariableAddrRange {
420   uint32_t OffsetStart;
421   uint16_t ISectStart;
422   uint16_t Range;
423 };
424 
425 struct LocalVariableAddrGap {
426   uint16_t GapStartOffset;
427   uint16_t Range;
428 };
429 
430 enum : uint16_t { MaxDefRange = 0xf000 };
431 
432 // S_DEFRANGE
433 class DefRangeSym : public SymbolRecord {
434   static constexpr uint32_t RelocationOffset = 8;
435 
436 public:
DefRangeSym(SymbolRecordKind Kind)437   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeSym(uint32_t RecordOffset)438   explicit DefRangeSym(uint32_t RecordOffset)
439       : SymbolRecord(SymbolRecordKind::DefRangeSym),
440         RecordOffset(RecordOffset) {}
441 
getRelocationOffset()442   uint32_t getRelocationOffset() const {
443     return RecordOffset + RelocationOffset;
444   }
445 
446   uint32_t Program;
447   LocalVariableAddrRange Range;
448   std::vector<LocalVariableAddrGap> Gaps;
449 
450   uint32_t RecordOffset;
451 };
452 
453 // S_DEFRANGE_SUBFIELD
454 class DefRangeSubfieldSym : public SymbolRecord {
455   static constexpr uint32_t RelocationOffset = 12;
456 
457 public:
DefRangeSubfieldSym(SymbolRecordKind Kind)458   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeSubfieldSym(uint32_t RecordOffset)459   DefRangeSubfieldSym(uint32_t RecordOffset)
460       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
461         RecordOffset(RecordOffset) {}
462 
getRelocationOffset()463   uint32_t getRelocationOffset() const {
464     return RecordOffset + RelocationOffset;
465   }
466 
467   uint32_t Program;
468   uint16_t OffsetInParent;
469   LocalVariableAddrRange Range;
470   std::vector<LocalVariableAddrGap> Gaps;
471 
472   uint32_t RecordOffset;
473 };
474 
475 // S_DEFRANGE_REGISTER
476 class DefRangeRegisterSym : public SymbolRecord {
477 public:
478   struct Header {
479     ulittle16_t Register;
480     ulittle16_t MayHaveNoName;
481   };
482 
DefRangeRegisterSym(SymbolRecordKind Kind)483   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeRegisterSym(uint32_t RecordOffset)484   DefRangeRegisterSym(uint32_t RecordOffset)
485       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
486         RecordOffset(RecordOffset) {}
487 
getRelocationOffset()488   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
489 
490   Header Hdr;
491   LocalVariableAddrRange Range;
492   std::vector<LocalVariableAddrGap> Gaps;
493 
494   uint32_t RecordOffset;
495 };
496 
497 // S_DEFRANGE_SUBFIELD_REGISTER
498 class DefRangeSubfieldRegisterSym : public SymbolRecord {
499 public:
500   struct Header {
501     ulittle16_t Register;
502     ulittle16_t MayHaveNoName;
503     ulittle32_t OffsetInParent;
504   };
505 
DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)506   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
507       : SymbolRecord(Kind) {}
DefRangeSubfieldRegisterSym(uint32_t RecordOffset)508   DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
509       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
510         RecordOffset(RecordOffset) {}
511 
getRelocationOffset()512   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
513 
514   Header Hdr;
515   LocalVariableAddrRange Range;
516   std::vector<LocalVariableAddrGap> Gaps;
517 
518   uint32_t RecordOffset;
519 };
520 
521 // S_DEFRANGE_FRAMEPOINTER_REL
522 class DefRangeFramePointerRelSym : public SymbolRecord {
523   static constexpr uint32_t RelocationOffset = 8;
524 
525 public:
DefRangeFramePointerRelSym(SymbolRecordKind Kind)526   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
527       : SymbolRecord(Kind) {}
DefRangeFramePointerRelSym(uint32_t RecordOffset)528   DefRangeFramePointerRelSym(uint32_t RecordOffset)
529       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
530         RecordOffset(RecordOffset) {}
531 
getRelocationOffset()532   uint32_t getRelocationOffset() const {
533     return RecordOffset + RelocationOffset;
534   }
535 
536   int32_t Offset;
537   LocalVariableAddrRange Range;
538   std::vector<LocalVariableAddrGap> Gaps;
539 
540   uint32_t RecordOffset;
541 };
542 
543 // S_DEFRANGE_REGISTER_REL
544 class DefRangeRegisterRelSym : public SymbolRecord {
545 public:
546   struct Header {
547     ulittle16_t Register;
548     ulittle16_t Flags;
549     little32_t BasePointerOffset;
550   };
551 
DefRangeRegisterRelSym(SymbolRecordKind Kind)552   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeRegisterRelSym(uint32_t RecordOffset)553   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
554       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
555         RecordOffset(RecordOffset) {}
556 
557   // The flags implement this notional bitfield:
558   //   uint16_t IsSubfield : 1;
559   //   uint16_t Padding : 3;
560   //   uint16_t OffsetInParent : 12;
561   enum : uint16_t {
562     IsSubfieldFlag = 1,
563     OffsetInParentShift = 4,
564   };
565 
hasSpilledUDTMember()566   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
offsetInParent()567   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
568 
getRelocationOffset()569   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
570 
571   Header Hdr;
572   LocalVariableAddrRange Range;
573   std::vector<LocalVariableAddrGap> Gaps;
574 
575   uint32_t RecordOffset;
576 };
577 
578 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
579 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
580 public:
DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)581   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
582       : SymbolRecord(Kind) {}
DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)583   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
584       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
585         RecordOffset(RecordOffset) {}
586 
587   int32_t Offset;
588 
589   uint32_t RecordOffset;
590 };
591 
592 // S_BLOCK32
593 class BlockSym : public SymbolRecord {
594   static constexpr uint32_t RelocationOffset = 16;
595 
596 public:
BlockSym(SymbolRecordKind Kind)597   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BlockSym(uint32_t RecordOffset)598   explicit BlockSym(uint32_t RecordOffset)
599       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
600 
getRelocationOffset()601   uint32_t getRelocationOffset() const {
602     return RecordOffset + RelocationOffset;
603   }
604 
605   uint32_t Parent;
606   uint32_t End;
607   uint32_t CodeSize;
608   uint32_t CodeOffset;
609   uint16_t Segment;
610   StringRef Name;
611 
612   uint32_t RecordOffset;
613 };
614 
615 // S_LABEL32
616 class LabelSym : public SymbolRecord {
617   static constexpr uint32_t RelocationOffset = 4;
618 
619 public:
LabelSym(SymbolRecordKind Kind)620   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
LabelSym(uint32_t RecordOffset)621   explicit LabelSym(uint32_t RecordOffset)
622       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
623 
getRelocationOffset()624   uint32_t getRelocationOffset() const {
625     return RecordOffset + RelocationOffset;
626   }
627 
628   uint32_t CodeOffset;
629   uint16_t Segment;
630   ProcSymFlags Flags;
631   StringRef Name;
632 
633   uint32_t RecordOffset;
634 };
635 
636 // S_OBJNAME
637 class ObjNameSym : public SymbolRecord {
638 public:
ObjNameSym(SymbolRecordKind Kind)639   explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ObjNameSym(uint32_t RecordOffset)640   ObjNameSym(uint32_t RecordOffset)
641       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
642   }
643 
644   uint32_t Signature;
645   StringRef Name;
646 
647   uint32_t RecordOffset;
648 };
649 
650 // S_ENVBLOCK
651 class EnvBlockSym : public SymbolRecord {
652 public:
EnvBlockSym(SymbolRecordKind Kind)653   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
EnvBlockSym(uint32_t RecordOffset)654   EnvBlockSym(uint32_t RecordOffset)
655       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
656         RecordOffset(RecordOffset) {}
657 
658   std::vector<StringRef> Fields;
659 
660   uint32_t RecordOffset;
661 };
662 
663 // S_EXPORT
664 class ExportSym : public SymbolRecord {
665 public:
ExportSym(SymbolRecordKind Kind)666   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ExportSym(uint32_t RecordOffset)667   ExportSym(uint32_t RecordOffset)
668       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
669 
670   uint16_t Ordinal;
671   ExportFlags Flags;
672   StringRef Name;
673 
674   uint32_t RecordOffset;
675 };
676 
677 // S_FILESTATIC
678 class FileStaticSym : public SymbolRecord {
679 public:
FileStaticSym(SymbolRecordKind Kind)680   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FileStaticSym(uint32_t RecordOffset)681   FileStaticSym(uint32_t RecordOffset)
682       : SymbolRecord(SymbolRecordKind::FileStaticSym),
683         RecordOffset(RecordOffset) {}
684 
685   TypeIndex Index;
686   uint32_t ModFilenameOffset;
687   LocalSymFlags Flags;
688   StringRef Name;
689 
690   uint32_t RecordOffset;
691 };
692 
693 // S_COMPILE2
694 class Compile2Sym : public SymbolRecord {
695 public:
Compile2Sym(SymbolRecordKind Kind)696   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Compile2Sym(uint32_t RecordOffset)697   Compile2Sym(uint32_t RecordOffset)
698       : SymbolRecord(SymbolRecordKind::Compile2Sym),
699         RecordOffset(RecordOffset) {}
700 
701   CompileSym2Flags Flags;
702   CPUType Machine;
703   uint16_t VersionFrontendMajor;
704   uint16_t VersionFrontendMinor;
705   uint16_t VersionFrontendBuild;
706   uint16_t VersionBackendMajor;
707   uint16_t VersionBackendMinor;
708   uint16_t VersionBackendBuild;
709   StringRef Version;
710   std::vector<StringRef> ExtraStrings;
711 
getLanguage()712   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
getFlags()713   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
714 
715   uint32_t RecordOffset;
716 };
717 
718 // S_COMPILE3
719 class Compile3Sym : public SymbolRecord {
720 public:
Compile3Sym(SymbolRecordKind Kind)721   explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Compile3Sym(uint32_t RecordOffset)722   Compile3Sym(uint32_t RecordOffset)
723       : SymbolRecord(SymbolRecordKind::Compile3Sym),
724         RecordOffset(RecordOffset) {}
725 
726   CompileSym3Flags Flags;
727   CPUType Machine;
728   uint16_t VersionFrontendMajor;
729   uint16_t VersionFrontendMinor;
730   uint16_t VersionFrontendBuild;
731   uint16_t VersionFrontendQFE;
732   uint16_t VersionBackendMajor;
733   uint16_t VersionBackendMinor;
734   uint16_t VersionBackendBuild;
735   uint16_t VersionBackendQFE;
736   StringRef Version;
737 
setLanguage(SourceLanguage Lang)738   void setLanguage(SourceLanguage Lang) {
739     Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
740   }
741 
getLanguage()742   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
getFlags()743   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
744 
745   uint32_t RecordOffset;
746 };
747 
748 // S_FRAMEPROC
749 class FrameProcSym : public SymbolRecord {
750 public:
FrameProcSym(SymbolRecordKind Kind)751   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FrameProcSym(uint32_t RecordOffset)752   explicit FrameProcSym(uint32_t RecordOffset)
753       : SymbolRecord(SymbolRecordKind::FrameProcSym),
754         RecordOffset(RecordOffset) {}
755 
756   uint32_t TotalFrameBytes;
757   uint32_t PaddingFrameBytes;
758   uint32_t OffsetToPadding;
759   uint32_t BytesOfCalleeSavedRegisters;
760   uint32_t OffsetOfExceptionHandler;
761   uint16_t SectionIdOfExceptionHandler;
762   FrameProcedureOptions Flags;
763 
764   uint32_t RecordOffset;
765 };
766 
767 // S_CALLSITEINFO
768 class CallSiteInfoSym : public SymbolRecord {
769   static constexpr uint32_t RelocationOffset = 4;
770 
771 public:
CallSiteInfoSym(SymbolRecordKind Kind)772   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CallSiteInfoSym(uint32_t RecordOffset)773   explicit CallSiteInfoSym(uint32_t RecordOffset)
774       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
775 
getRelocationOffset()776   uint32_t getRelocationOffset() const {
777     return RecordOffset + RelocationOffset;
778   }
779 
780   uint32_t CodeOffset;
781   uint16_t Segment;
782   TypeIndex Type;
783 
784   uint32_t RecordOffset;
785 };
786 
787 // S_HEAPALLOCSITE
788 class HeapAllocationSiteSym : public SymbolRecord {
789   static constexpr uint32_t RelocationOffset = 4;
790 
791 public:
HeapAllocationSiteSym(SymbolRecordKind Kind)792   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
HeapAllocationSiteSym(uint32_t RecordOffset)793   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
794       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
795         RecordOffset(RecordOffset) {}
796 
getRelocationOffset()797   uint32_t getRelocationOffset() const {
798     return RecordOffset + RelocationOffset;
799   }
800 
801   uint32_t CodeOffset;
802   uint16_t Segment;
803   uint16_t CallInstructionSize;
804   TypeIndex Type;
805 
806   uint32_t RecordOffset;
807 };
808 
809 // S_FRAMECOOKIE
810 class FrameCookieSym : public SymbolRecord {
811   static constexpr uint32_t RelocationOffset = 4;
812 
813 public:
FrameCookieSym(SymbolRecordKind Kind)814   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FrameCookieSym(uint32_t RecordOffset)815   explicit FrameCookieSym(uint32_t RecordOffset)
816       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
817 
getRelocationOffset()818   uint32_t getRelocationOffset() const {
819     return RecordOffset + RelocationOffset;
820   }
821 
822   uint32_t CodeOffset;
823   uint16_t Register;
824   FrameCookieKind CookieKind;
825   uint8_t Flags;
826 
827   uint32_t RecordOffset;
828 };
829 
830 // S_UDT, S_COBOLUDT
831 class UDTSym : public SymbolRecord {
832 public:
UDTSym(SymbolRecordKind Kind)833   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
UDTSym(uint32_t RecordOffset)834   explicit UDTSym(uint32_t RecordOffset)
835       : SymbolRecord(SymbolRecordKind::UDTSym) {}
836 
837   TypeIndex Type;
838   StringRef Name;
839 
840   uint32_t RecordOffset;
841 };
842 
843 // S_BUILDINFO
844 class BuildInfoSym : public SymbolRecord {
845 public:
BuildInfoSym(SymbolRecordKind Kind)846   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BuildInfoSym(uint32_t RecordOffset)847   BuildInfoSym(uint32_t RecordOffset)
848       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
849         RecordOffset(RecordOffset) {}
850 
851   TypeIndex BuildId;
852 
853   uint32_t RecordOffset;
854 };
855 
856 // S_BPREL32
857 class BPRelativeSym : public SymbolRecord {
858 public:
BPRelativeSym(SymbolRecordKind Kind)859   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BPRelativeSym(uint32_t RecordOffset)860   explicit BPRelativeSym(uint32_t RecordOffset)
861       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
862         RecordOffset(RecordOffset) {}
863 
864   int32_t Offset;
865   TypeIndex Type;
866   StringRef Name;
867 
868   uint32_t RecordOffset;
869 };
870 
871 // S_REGREL32
872 class RegRelativeSym : public SymbolRecord {
873 public:
RegRelativeSym(SymbolRecordKind Kind)874   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
RegRelativeSym(uint32_t RecordOffset)875   explicit RegRelativeSym(uint32_t RecordOffset)
876       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
877         RecordOffset(RecordOffset) {}
878 
879   uint32_t Offset;
880   TypeIndex Type;
881   RegisterId Register;
882   StringRef Name;
883 
884   uint32_t RecordOffset;
885 };
886 
887 // S_CONSTANT, S_MANCONSTANT
888 class ConstantSym : public SymbolRecord {
889 public:
ConstantSym(SymbolRecordKind Kind)890   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ConstantSym(uint32_t RecordOffset)891   ConstantSym(uint32_t RecordOffset)
892       : SymbolRecord(SymbolRecordKind::ConstantSym),
893         RecordOffset(RecordOffset) {}
894 
895   TypeIndex Type;
896   APSInt Value;
897   StringRef Name;
898 
899   uint32_t RecordOffset;
900 };
901 
902 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
903 class DataSym : public SymbolRecord {
904   static constexpr uint32_t RelocationOffset = 8;
905 
906 public:
DataSym(SymbolRecordKind Kind)907   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DataSym(uint32_t RecordOffset)908   DataSym(uint32_t RecordOffset)
909       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
910 
getRelocationOffset()911   uint32_t getRelocationOffset() const {
912     return RecordOffset + RelocationOffset;
913   }
914 
915   TypeIndex Type;
916   uint32_t DataOffset;
917   uint16_t Segment;
918   StringRef Name;
919 
920   uint32_t RecordOffset;
921 };
922 
923 // S_LTHREAD32, S_GTHREAD32
924 class ThreadLocalDataSym : public SymbolRecord {
925   static constexpr uint32_t RelocationOffset = 8;
926 
927 public:
ThreadLocalDataSym(SymbolRecordKind Kind)928   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ThreadLocalDataSym(uint32_t RecordOffset)929   explicit ThreadLocalDataSym(uint32_t RecordOffset)
930       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
931         RecordOffset(RecordOffset) {}
932 
getRelocationOffset()933   uint32_t getRelocationOffset() const {
934     return RecordOffset + RelocationOffset;
935   }
936 
937   TypeIndex Type;
938   uint32_t DataOffset;
939   uint16_t Segment;
940   StringRef Name;
941 
942   uint32_t RecordOffset;
943 };
944 
945 // S_UNAMESPACE
946 class UsingNamespaceSym : public SymbolRecord {
947 public:
UsingNamespaceSym(SymbolRecordKind Kind)948   explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
UsingNamespaceSym(uint32_t RecordOffset)949   explicit UsingNamespaceSym(uint32_t RecordOffset)
950       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
951         RecordOffset(RecordOffset) {}
952 
953   StringRef Name;
954 
955   uint32_t RecordOffset;
956 };
957 
958 // S_ANNOTATION
959 
960 using CVSymbol = CVRecord<SymbolKind>;
961 using CVSymbolArray = VarStreamArray<CVSymbol>;
962 
963 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
964                                         uint32_t Offset);
965 
966 } // end namespace codeview
967 } // end namespace llvm
968 
969 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
970