Coverage Report

Created: 2018-11-16 02:38

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