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
26namespace llvm {
27namespace codeview {
28
29class SymbolRecord {
30protected:
31 explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
32
33public:
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
41class ProcSym : public SymbolRecord {
42 static constexpr uint32_t RelocationOffset = 32;
43
44public:
45 explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
46 ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
47 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
48
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
69class Thunk32Sym : public SymbolRecord {
70public:
71 explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
89class TrampolineSym : public SymbolRecord {
90public:
91 explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
106class SectionSym : public SymbolRecord {
107public:
108 explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
123class CoffGroupSym : public SymbolRecord {
124public:
125 explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
138class ScopeEndSym : public SymbolRecord {
139public:
140 explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
141 ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
142 : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
143
144 uint32_t RecordOffset = 0;
145};
146
147class JumpTableSym : public SymbolRecord {
148public:
149 explicit JumpTableSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
168class CallerSym : public SymbolRecord {
169public:
170 explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
179struct 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
188struct BinaryAnnotationIterator
189 : public iterator_facade_base<BinaryAnnotationIterator,
190 std::forward_iterator_tag,
191 DecodedAnnotation> {
192 BinaryAnnotationIterator() = default;
193 BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
194 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
222private:
223 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
261 static int32_t DecodeSignedOperand(uint32_t Operand) {
262 if (Operand & 1)
263 return -(Operand >> 1);
264 return Operand >> 1;
265 }
266
267 static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
268 return DecodeSignedOperand(Operand: GetCompressedAnnotation(Annotations));
269 }
270
271 bool ParseCurrentAnnotation() {
272 if (Current)
273 return true;
274
275 Next = Data;
276 uint32_t Op = GetCompressedAnnotation(Annotations&: 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(Annotations&: Next);
287 break;
288 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
289 Result.Name = "ChangeCodeOffsetBase";
290 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
291 break;
292 case BinaryAnnotationsOpCode::ChangeCodeOffset:
293 Result.Name = "ChangeCodeOffset";
294 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
295 break;
296 case BinaryAnnotationsOpCode::ChangeCodeLength:
297 Result.Name = "ChangeCodeLength";
298 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
299 break;
300 case BinaryAnnotationsOpCode::ChangeFile:
301 Result.Name = "ChangeFile";
302 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
303 break;
304 case BinaryAnnotationsOpCode::ChangeLineEndDelta:
305 Result.Name = "ChangeLineEndDelta";
306 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
307 break;
308 case BinaryAnnotationsOpCode::ChangeRangeKind:
309 Result.Name = "ChangeRangeKind";
310 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
311 break;
312 case BinaryAnnotationsOpCode::ChangeColumnStart:
313 Result.Name = "ChangeColumnStart";
314 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
315 break;
316 case BinaryAnnotationsOpCode::ChangeColumnEnd:
317 Result.Name = "ChangeColumnEnd";
318 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
319 break;
320 case BinaryAnnotationsOpCode::ChangeLineOffset:
321 Result.Name = "ChangeLineOffset";
322 Result.S1 = DecodeSignedOperand(Annotations&: Next);
323 break;
324 case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
325 Result.Name = "ChangeColumnEndDelta";
326 Result.S1 = DecodeSignedOperand(Annotations&: Next);
327 break;
328 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
329 Result.Name = "ChangeCodeOffsetAndLineOffset";
330 uint32_t Annotation = GetCompressedAnnotation(Annotations&: Next);
331 Result.S1 = DecodeSignedOperand(Operand: Annotation >> 4);
332 Result.U1 = Annotation & 0xf;
333 break;
334 }
335 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
336 Result.Name = "ChangeCodeLengthAndCodeOffset";
337 Result.U1 = GetCompressedAnnotation(Annotations&: Next);
338 Result.U2 = GetCompressedAnnotation(Annotations&: Next);
339 break;
340 }
341 }
342 Result.Bytes = Data.take_front(N: 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
353class InlineSiteSym : public SymbolRecord {
354public:
355 explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
356 explicit InlineSiteSym(uint32_t RecordOffset)
357 : SymbolRecord(SymbolRecordKind::InlineSiteSym),
358 RecordOffset(RecordOffset) {}
359
360 iterator_range<BinaryAnnotationIterator> annotations() const {
361 return make_range(x: BinaryAnnotationIterator(AnnotationData),
362 y: 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
373struct PublicSym32Header {
374 ulittle32_t Flags;
375 ulittle32_t Offset;
376 ulittle16_t Segment;
377 // char Name[];
378};
379
380// S_PUB32
381class PublicSym32 : public SymbolRecord {
382public:
383 PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
384 explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
398class RegisterSym : public SymbolRecord {
399public:
400 explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
413class ProcRefSym : public SymbolRecord {
414public:
415 explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
425 uint16_t modi() const { return Module - 1; }
426 uint32_t RecordOffset = 0;
427};
428
429// S_LOCAL
430class LocalSym : public SymbolRecord {
431public:
432 explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
443struct LocalVariableAddrRange {
444 uint32_t OffsetStart = 0;
445 uint16_t ISectStart = 0;
446 uint16_t Range = 0;
447};
448
449struct LocalVariableAddrGap {
450 uint16_t GapStartOffset = 0;
451 uint16_t Range = 0;
452};
453
454enum : uint16_t { MaxDefRange = 0xf000 };
455
456// S_DEFRANGE
457class DefRangeSym : public SymbolRecord {
458 static constexpr uint32_t RelocationOffset = 8;
459
460public:
461 explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
462 explicit DefRangeSym(uint32_t RecordOffset)
463 : SymbolRecord(SymbolRecordKind::DefRangeSym),
464 RecordOffset(RecordOffset) {}
465
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
478class DefRangeSubfieldSym : public SymbolRecord {
479 static constexpr uint32_t RelocationOffset = 12;
480
481public:
482 explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
483 explicit DefRangeSubfieldSym(uint32_t RecordOffset)
484 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
485 RecordOffset(RecordOffset) {}
486
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
499struct DefRangeRegisterHeader {
500 ulittle16_t Register;
501 ulittle16_t MayHaveNoName;
502};
503
504// S_DEFRANGE_REGISTER
505class DefRangeRegisterSym : public SymbolRecord {
506public:
507 explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
508 explicit DefRangeRegisterSym(uint32_t RecordOffset)
509 : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
510 RecordOffset(RecordOffset) {}
511
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
521struct DefRangeSubfieldRegisterHeader {
522 ulittle16_t Register;
523 ulittle16_t MayHaveNoName;
524 ulittle32_t OffsetInParent;
525};
526
527// S_DEFRANGE_SUBFIELD_REGISTER
528class DefRangeSubfieldRegisterSym : public SymbolRecord {
529public:
530 explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
531 : SymbolRecord(Kind) {}
532 explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
533 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
534 RecordOffset(RecordOffset) {}
535
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
545struct DefRangeFramePointerRelHeader {
546 little32_t Offset;
547};
548
549// S_DEFRANGE_FRAMEPOINTER_REL
550class DefRangeFramePointerRelSym : public SymbolRecord {
551 static constexpr uint32_t RelocationOffset = 8;
552
553public:
554 explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
555 : SymbolRecord(Kind) {}
556 explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
557 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
558 RecordOffset(RecordOffset) {}
559
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
571struct DefRangeRegisterRelHeader {
572 ulittle16_t Register;
573 ulittle16_t Flags;
574 little32_t BasePointerOffset;
575};
576
577// S_DEFRANGE_REGISTER_REL
578class DefRangeRegisterRelSym : public SymbolRecord {
579public:
580 explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
594 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
595 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
596
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
607class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
608public:
609 explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
610 : SymbolRecord(Kind) {}
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
621class BlockSym : public SymbolRecord {
622 static constexpr uint32_t RelocationOffset = 16;
623
624public:
625 explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
626 explicit BlockSym(uint32_t RecordOffset)
627 : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
628
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
644class LabelSym : public SymbolRecord {
645 static constexpr uint32_t RelocationOffset = 4;
646
647public:
648 explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
649 explicit LabelSym(uint32_t RecordOffset)
650 : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
651
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
665class ObjNameSym : public SymbolRecord {
666public:
667 explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
668 explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
680class EnvBlockSym : public SymbolRecord {
681public:
682 explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
693class ExportSym : public SymbolRecord {
694public:
695 explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
707class FileStaticSym : public SymbolRecord {
708public:
709 explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
723class Compile2Sym : public SymbolRecord {
724public:
725 explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
741 uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
742 uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
743
744 uint32_t RecordOffset = 0;
745};
746
747// S_COMPILE3
748class Compile3Sym : public SymbolRecord {
749public:
750 Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
751 explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
768 void setLanguage(SourceLanguage Lang) {
769 Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
770 }
771
772 SourceLanguage getLanguage() const {
773 return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
774 }
775 CompileSym3Flags getFlags() const {
776 return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF);
777 }
778
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
788class FrameProcSym : public SymbolRecord {
789public:
790 explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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.
804 RegisterId getLocalFramePtrReg(CPUType CPU) const {
805 return decodeFramePtrReg(
806 EncodedReg: EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
807 }
808
809 /// Extract the register this frame uses to refer to parameters.
810 RegisterId getParamFramePtrReg(CPUType CPU) const {
811 return decodeFramePtrReg(
812 EncodedReg: EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
813 }
814
815 uint32_t RecordOffset = 0;
816
817private:
818};
819
820// S_CALLSITEINFO
821class CallSiteInfoSym : public SymbolRecord {
822 static constexpr uint32_t RelocationOffset = 4;
823
824public:
825 explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
826 explicit CallSiteInfoSym(uint32_t RecordOffset)
827 : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
828
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
841class HeapAllocationSiteSym : public SymbolRecord {
842 static constexpr uint32_t RelocationOffset = 4;
843
844public:
845 explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
846 explicit HeapAllocationSiteSym(uint32_t RecordOffset)
847 : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
848 RecordOffset(RecordOffset) {}
849
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
863class FrameCookieSym : public SymbolRecord {
864 static constexpr uint32_t RelocationOffset = 4;
865
866public:
867 explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
868 explicit FrameCookieSym(uint32_t RecordOffset)
869 : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
870
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
884class UDTSym : public SymbolRecord {
885public:
886 explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
897class BuildInfoSym : public SymbolRecord {
898public:
899 explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
910class BPRelativeSym : public SymbolRecord {
911public:
912 explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
925class RegRelativeSym : public SymbolRecord {
926public:
927 explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
941class ConstantSym : public SymbolRecord {
942public:
943 explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
956class DataSym : public SymbolRecord {
957 static constexpr uint32_t RelocationOffset = 8;
958
959public:
960 explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
961 explicit DataSym(uint32_t RecordOffset)
962 : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
963
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
977class ThreadLocalDataSym : public SymbolRecord {
978 static constexpr uint32_t RelocationOffset = 8;
979
980public:
981 explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
982 explicit ThreadLocalDataSym(uint32_t RecordOffset)
983 : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
984 RecordOffset(RecordOffset) {}
985
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
999class UsingNamespaceSym : public SymbolRecord {
1000public:
1001 explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
1012class AnnotationSym : public SymbolRecord {
1013public:
1014 explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
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
1026Expected<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

source code of llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h