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