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