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