SymbolRecord.h revision 360784
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
27namespace llvm {
28namespace codeview {
29
30class SymbolRecord {
31protected:
32  explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
33
34public:
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
42class ProcSym : public SymbolRecord {
43  static constexpr uint32_t RelocationOffset = 32;
44
45public:
46  explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
47  ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
48      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
49
50  uint32_t getRelocationOffset() const {
51    return RecordOffset + RelocationOffset;
52  }
53
54  uint32_t Parent = 0;
55  uint32_t End = 0;
56  uint32_t Next = 0;
57  uint32_t CodeSize = 0;
58  uint32_t DbgStart = 0;
59  uint32_t DbgEnd = 0;
60  TypeIndex FunctionType;
61  uint32_t CodeOffset = 0;
62  uint16_t Segment = 0;
63  ProcSymFlags Flags = ProcSymFlags::None;
64  StringRef Name;
65
66  uint32_t RecordOffset = 0;
67};
68
69// S_THUNK32
70class Thunk32Sym : public SymbolRecord {
71public:
72  explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
73  Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
74      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
75
76  uint32_t Parent = 0;
77  uint32_t End = 0;
78  uint32_t Next = 0;
79  uint32_t Offset = 0;
80  uint16_t Segment = 0;
81  uint16_t Length = 0;
82  ThunkOrdinal Thunk = ThunkOrdinal::Standard;
83  StringRef Name;
84  ArrayRef<uint8_t> VariantData;
85
86  uint32_t RecordOffset = 0;
87};
88
89// S_TRAMPOLINE
90class TrampolineSym : public SymbolRecord {
91public:
92  explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
93  TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
94      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
95
96  TrampolineType Type;
97  uint16_t Size = 0;
98  uint32_t ThunkOffset = 0;
99  uint32_t TargetOffset = 0;
100  uint16_t ThunkSection = 0;
101  uint16_t TargetSection = 0;
102
103  uint32_t RecordOffset = 0;
104};
105
106// S_SECTION
107class SectionSym : public SymbolRecord {
108public:
109  explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
110  SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
111      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
112
113  uint16_t SectionNumber = 0;
114  uint8_t Alignment = 0;
115  uint32_t Rva = 0;
116  uint32_t Length = 0;
117  uint32_t Characteristics = 0;
118  StringRef Name;
119
120  uint32_t RecordOffset = 0;
121};
122
123// S_COFFGROUP
124class CoffGroupSym : public SymbolRecord {
125public:
126  explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
127  CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
128      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
129
130  uint32_t Size = 0;
131  uint32_t Characteristics = 0;
132  uint32_t Offset = 0;
133  uint16_t Segment = 0;
134  StringRef Name;
135
136  uint32_t RecordOffset = 0;
137};
138
139class ScopeEndSym : public SymbolRecord {
140public:
141  explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
142  ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
143      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
144
145  uint32_t RecordOffset = 0;
146};
147
148class CallerSym : public SymbolRecord {
149public:
150  explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
151  CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
152      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
153
154  std::vector<TypeIndex> Indices;
155
156  uint32_t RecordOffset = 0;
157};
158
159struct 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
168struct BinaryAnnotationIterator
169    : public iterator_facade_base<BinaryAnnotationIterator,
170                                  std::forward_iterator_tag,
171                                  DecodedAnnotation> {
172  BinaryAnnotationIterator() = default;
173  BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
174  BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
175      : Data(Other.Data) {}
176
177  bool operator==(BinaryAnnotationIterator Other) const {
178    return Data == Other.Data;
179  }
180
181  BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
182    Data = Other.Data;
183    return *this;
184  }
185
186  BinaryAnnotationIterator &operator++() {
187    if (!ParseCurrentAnnotation()) {
188      *this = BinaryAnnotationIterator();
189      return *this;
190    }
191    Data = Next;
192    Next = ArrayRef<uint8_t>();
193    Current.reset();
194    return *this;
195  }
196
197  const DecodedAnnotation &operator*() {
198    ParseCurrentAnnotation();
199    return Current.getValue();
200  }
201
202private:
203  static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
204    if (Annotations.empty())
205      return -1;
206
207    uint8_t FirstByte = Annotations.front();
208    Annotations = Annotations.drop_front();
209
210    if ((FirstByte & 0x80) == 0x00)
211      return FirstByte;
212
213    if (Annotations.empty())
214      return -1;
215
216    uint8_t SecondByte = Annotations.front();
217    Annotations = Annotations.drop_front();
218
219    if ((FirstByte & 0xC0) == 0x80)
220      return ((FirstByte & 0x3F) << 8) | SecondByte;
221
222    if (Annotations.empty())
223      return -1;
224
225    uint8_t ThirdByte = Annotations.front();
226    Annotations = Annotations.drop_front();
227
228    if (Annotations.empty())
229      return -1;
230
231    uint8_t FourthByte = Annotations.front();
232    Annotations = Annotations.drop_front();
233
234    if ((FirstByte & 0xE0) == 0xC0)
235      return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
236             (ThirdByte << 8) | FourthByte;
237
238    return -1;
239  }
240
241  static int32_t DecodeSignedOperand(uint32_t Operand) {
242    if (Operand & 1)
243      return -(Operand >> 1);
244    return Operand >> 1;
245  }
246
247  static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
248    return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
249  }
250
251  bool ParseCurrentAnnotation() {
252    if (Current.hasValue())
253      return true;
254
255    Next = Data;
256    uint32_t Op = GetCompressedAnnotation(Next);
257    DecodedAnnotation Result;
258    Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
259    switch (Result.OpCode) {
260    case BinaryAnnotationsOpCode::Invalid:
261      Result.Name = "Invalid";
262      Next = ArrayRef<uint8_t>();
263      break;
264    case BinaryAnnotationsOpCode::CodeOffset:
265      Result.Name = "CodeOffset";
266      Result.U1 = GetCompressedAnnotation(Next);
267      break;
268    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
269      Result.Name = "ChangeCodeOffsetBase";
270      Result.U1 = GetCompressedAnnotation(Next);
271      break;
272    case BinaryAnnotationsOpCode::ChangeCodeOffset:
273      Result.Name = "ChangeCodeOffset";
274      Result.U1 = GetCompressedAnnotation(Next);
275      break;
276    case BinaryAnnotationsOpCode::ChangeCodeLength:
277      Result.Name = "ChangeCodeLength";
278      Result.U1 = GetCompressedAnnotation(Next);
279      break;
280    case BinaryAnnotationsOpCode::ChangeFile:
281      Result.Name = "ChangeFile";
282      Result.U1 = GetCompressedAnnotation(Next);
283      break;
284    case BinaryAnnotationsOpCode::ChangeLineEndDelta:
285      Result.Name = "ChangeLineEndDelta";
286      Result.U1 = GetCompressedAnnotation(Next);
287      break;
288    case BinaryAnnotationsOpCode::ChangeRangeKind:
289      Result.Name = "ChangeRangeKind";
290      Result.U1 = GetCompressedAnnotation(Next);
291      break;
292    case BinaryAnnotationsOpCode::ChangeColumnStart:
293      Result.Name = "ChangeColumnStart";
294      Result.U1 = GetCompressedAnnotation(Next);
295      break;
296    case BinaryAnnotationsOpCode::ChangeColumnEnd:
297      Result.Name = "ChangeColumnEnd";
298      Result.U1 = GetCompressedAnnotation(Next);
299      break;
300    case BinaryAnnotationsOpCode::ChangeLineOffset:
301      Result.Name = "ChangeLineOffset";
302      Result.S1 = DecodeSignedOperand(Next);
303      break;
304    case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
305      Result.Name = "ChangeColumnEndDelta";
306      Result.S1 = DecodeSignedOperand(Next);
307      break;
308    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
309      Result.Name = "ChangeCodeOffsetAndLineOffset";
310      uint32_t Annotation = GetCompressedAnnotation(Next);
311      Result.S1 = DecodeSignedOperand(Annotation >> 4);
312      Result.U1 = Annotation & 0xf;
313      break;
314    }
315    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
316      Result.Name = "ChangeCodeLengthAndCodeOffset";
317      Result.U1 = GetCompressedAnnotation(Next);
318      Result.U2 = GetCompressedAnnotation(Next);
319      break;
320    }
321    }
322    Result.Bytes = Data.take_front(Data.size() - Next.size());
323    Current = Result;
324    return true;
325  }
326
327  Optional<DecodedAnnotation> Current;
328  ArrayRef<uint8_t> Data;
329  ArrayRef<uint8_t> Next;
330};
331
332// S_INLINESITE
333class InlineSiteSym : public SymbolRecord {
334public:
335  explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
336  explicit InlineSiteSym(uint32_t RecordOffset)
337      : SymbolRecord(SymbolRecordKind::InlineSiteSym),
338        RecordOffset(RecordOffset) {}
339
340  iterator_range<BinaryAnnotationIterator> annotations() const {
341    return make_range(BinaryAnnotationIterator(AnnotationData),
342                      BinaryAnnotationIterator());
343  }
344
345  uint32_t Parent = 0;
346  uint32_t End = 0;
347  TypeIndex Inlinee;
348  std::vector<uint8_t> AnnotationData;
349
350  uint32_t RecordOffset = 0;
351};
352
353// S_PUB32
354class PublicSym32 : public SymbolRecord {
355public:
356  PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
357  explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
371class RegisterSym : public SymbolRecord {
372public:
373  explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
386class ProcRefSym : public SymbolRecord {
387public:
388  explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
398  uint16_t modi() const { return Module - 1; }
399  uint32_t RecordOffset = 0;
400};
401
402// S_LOCAL
403class LocalSym : public SymbolRecord {
404public:
405  explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
416struct LocalVariableAddrRange {
417  uint32_t OffsetStart = 0;
418  uint16_t ISectStart = 0;
419  uint16_t Range = 0;
420};
421
422struct LocalVariableAddrGap {
423  uint16_t GapStartOffset = 0;
424  uint16_t Range = 0;
425};
426
427enum : uint16_t { MaxDefRange = 0xf000 };
428
429// S_DEFRANGE
430class DefRangeSym : public SymbolRecord {
431  static constexpr uint32_t RelocationOffset = 8;
432
433public:
434  explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
435  explicit DefRangeSym(uint32_t RecordOffset)
436      : SymbolRecord(SymbolRecordKind::DefRangeSym),
437        RecordOffset(RecordOffset) {}
438
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
451class DefRangeSubfieldSym : public SymbolRecord {
452  static constexpr uint32_t RelocationOffset = 12;
453
454public:
455  explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
456  explicit DefRangeSubfieldSym(uint32_t RecordOffset)
457      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
458        RecordOffset(RecordOffset) {}
459
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
472struct DefRangeRegisterHeader {
473  ulittle16_t Register;
474  ulittle16_t MayHaveNoName;
475};
476
477// S_DEFRANGE_REGISTER
478class DefRangeRegisterSym : public SymbolRecord {
479public:
480  explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
481  explicit DefRangeRegisterSym(uint32_t RecordOffset)
482      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
483        RecordOffset(RecordOffset) {}
484
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
494struct DefRangeSubfieldRegisterHeader {
495  ulittle16_t Register;
496  ulittle16_t MayHaveNoName;
497  ulittle32_t OffsetInParent;
498};
499
500// S_DEFRANGE_SUBFIELD_REGISTER
501class DefRangeSubfieldRegisterSym : public SymbolRecord {
502public:
503  explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
504      : SymbolRecord(Kind) {}
505  explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
506      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
507        RecordOffset(RecordOffset) {}
508
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
518struct DefRangeFramePointerRelHeader {
519  little32_t Offset;
520};
521
522// S_DEFRANGE_FRAMEPOINTER_REL
523class DefRangeFramePointerRelSym : public SymbolRecord {
524  static constexpr uint32_t RelocationOffset = 8;
525
526public:
527  explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
528      : SymbolRecord(Kind) {}
529  explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
530      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
531        RecordOffset(RecordOffset) {}
532
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
544struct DefRangeRegisterRelHeader {
545  ulittle16_t Register;
546  ulittle16_t Flags;
547  little32_t BasePointerOffset;
548};
549
550// S_DEFRANGE_REGISTER_REL
551class DefRangeRegisterRelSym : public SymbolRecord {
552public:
553  explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
567  bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
568  uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
569
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
580class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
581public:
582  explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
583      : SymbolRecord(Kind) {}
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
594class BlockSym : public SymbolRecord {
595  static constexpr uint32_t RelocationOffset = 16;
596
597public:
598  explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
599  explicit BlockSym(uint32_t RecordOffset)
600      : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
601
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
617class LabelSym : public SymbolRecord {
618  static constexpr uint32_t RelocationOffset = 4;
619
620public:
621  explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
622  explicit LabelSym(uint32_t RecordOffset)
623      : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
624
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
638class ObjNameSym : public SymbolRecord {
639public:
640  explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
641  explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
653class EnvBlockSym : public SymbolRecord {
654public:
655  explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
666class ExportSym : public SymbolRecord {
667public:
668  explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
680class FileStaticSym : public SymbolRecord {
681public:
682  explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
696class Compile2Sym : public SymbolRecord {
697public:
698  explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
714  uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
715  uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
716
717  uint32_t RecordOffset = 0;
718};
719
720// S_COMPILE3
721class Compile3Sym : public SymbolRecord {
722public:
723  Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
724  explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
741  void setLanguage(SourceLanguage Lang) {
742    Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
743  }
744
745  SourceLanguage getLanguage() const {
746    return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
747  }
748  CompileSym3Flags getFlags() const {
749    return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
750  }
751
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
761class FrameProcSym : public SymbolRecord {
762public:
763  explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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.
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.
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
790private:
791};
792
793// S_CALLSITEINFO
794class CallSiteInfoSym : public SymbolRecord {
795  static constexpr uint32_t RelocationOffset = 4;
796
797public:
798  explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
799  explicit CallSiteInfoSym(uint32_t RecordOffset)
800      : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
801
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
814class HeapAllocationSiteSym : public SymbolRecord {
815  static constexpr uint32_t RelocationOffset = 4;
816
817public:
818  explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
819  explicit HeapAllocationSiteSym(uint32_t RecordOffset)
820      : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
821        RecordOffset(RecordOffset) {}
822
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
836class FrameCookieSym : public SymbolRecord {
837  static constexpr uint32_t RelocationOffset = 4;
838
839public:
840  explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
841  explicit FrameCookieSym(uint32_t RecordOffset)
842      : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
843
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
857class UDTSym : public SymbolRecord {
858public:
859  explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
870class BuildInfoSym : public SymbolRecord {
871public:
872  explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
883class BPRelativeSym : public SymbolRecord {
884public:
885  explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
898class RegRelativeSym : public SymbolRecord {
899public:
900  explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
914class ConstantSym : public SymbolRecord {
915public:
916  explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
929class DataSym : public SymbolRecord {
930  static constexpr uint32_t RelocationOffset = 8;
931
932public:
933  explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
934  explicit DataSym(uint32_t RecordOffset)
935      : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
936
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
950class ThreadLocalDataSym : public SymbolRecord {
951  static constexpr uint32_t RelocationOffset = 8;
952
953public:
954  explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
955  explicit ThreadLocalDataSym(uint32_t RecordOffset)
956      : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
957        RecordOffset(RecordOffset) {}
958
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
972class UsingNamespaceSym : public SymbolRecord {
973public:
974  explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
985class AnnotationSym : public SymbolRecord {
986public:
987  explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
999using CVSymbol = CVRecord<SymbolKind>;
1000using CVSymbolArray = VarStreamArray<CVSymbol>;
1001
1002Expected<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