Coverage Report

Created: 2018-07-18 22:01

/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
3.79k
  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
  explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
362
  explicit PublicSym32(uint32_t RecordOffset)
363
      : SymbolRecord(SymbolRecordKind::PublicSym32),
364
        RecordOffset(RecordOffset) {}
365
366
  PublicSymFlags Flags = PublicSymFlags::None;
367
  uint32_t Offset = 0;
368
  uint16_t Segment = 0;
369
  StringRef Name;
370
371
  uint32_t RecordOffset = 0;
372
};
373
374
// S_REGISTER
375
class RegisterSym : public SymbolRecord {
376
public:
377
  explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
378
  RegisterSym(uint32_t RecordOffset)
379
      : SymbolRecord(SymbolRecordKind::RegisterSym),
380
        RecordOffset(RecordOffset) {}
381
382
  TypeIndex Index;
383
  RegisterId Register;
384
  StringRef Name;
385
386
  uint32_t RecordOffset;
387
};
388
389
// S_PROCREF, S_LPROCREF
390
class ProcRefSym : public SymbolRecord {
391
public:
392
  explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
393
  explicit ProcRefSym(uint32_t RecordOffset)
394
      : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
395
  }
396
397
  uint32_t SumName;
398
  uint32_t SymOffset;
399
  uint16_t Module;
400
  StringRef Name;
401
402
  uint32_t RecordOffset;
403
};
404
405
// S_LOCAL
406
class LocalSym : public SymbolRecord {
407
public:
408
  explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
409
  explicit LocalSym(uint32_t RecordOffset)
410
      : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
411
412
  TypeIndex Type;
413
  LocalSymFlags Flags;
414
  StringRef Name;
415
416
  uint32_t RecordOffset;
417
};
418
419
struct LocalVariableAddrRange {
420
  uint32_t OffsetStart;
421
  uint16_t ISectStart;
422
  uint16_t Range;
423
};
424
425
struct LocalVariableAddrGap {
426
  uint16_t GapStartOffset;
427
  uint16_t Range;
428
};
429
430
enum : uint16_t { MaxDefRange = 0xf000 };
431
432
// S_DEFRANGE
433
class DefRangeSym : public SymbolRecord {
434
  static constexpr uint32_t RelocationOffset = 8;
435
436
public:
437
  explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
438
  explicit DefRangeSym(uint32_t RecordOffset)
439
      : SymbolRecord(SymbolRecordKind::DefRangeSym),
440
        RecordOffset(RecordOffset) {}
441
442
  uint32_t getRelocationOffset() const {
443
    return RecordOffset + RelocationOffset;
444
  }
445
446
  uint32_t Program;
447
  LocalVariableAddrRange Range;
448
  std::vector<LocalVariableAddrGap> Gaps;
449
450
  uint32_t RecordOffset;
451
};
452
453
// S_DEFRANGE_SUBFIELD
454
class DefRangeSubfieldSym : public SymbolRecord {
455
  static constexpr uint32_t RelocationOffset = 12;
456
457
public:
458
  explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
459
  DefRangeSubfieldSym(uint32_t RecordOffset)
460
      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
461
        RecordOffset(RecordOffset) {}
462
463
  uint32_t getRelocationOffset() const {
464
    return RecordOffset + RelocationOffset;
465
  }
466
467
  uint32_t Program;
468
  uint16_t OffsetInParent;
469
  LocalVariableAddrRange Range;
470
  std::vector<LocalVariableAddrGap> Gaps;
471
472
  uint32_t RecordOffset;
473
};
474
475
// S_DEFRANGE_REGISTER
476
class DefRangeRegisterSym : public SymbolRecord {
477
public:
478
  struct Header {
479
    ulittle16_t Register;
480
    ulittle16_t MayHaveNoName;
481
  };
482
483
  explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
484
  DefRangeRegisterSym(uint32_t RecordOffset)
485
      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
486
61
        RecordOffset(RecordOffset) {}
487
488
  uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
489
490
  Header Hdr;
491
  LocalVariableAddrRange Range;
492
  std::vector<LocalVariableAddrGap> Gaps;
493
494
  uint32_t RecordOffset;
495
};
496
497
// S_DEFRANGE_SUBFIELD_REGISTER
498
class DefRangeSubfieldRegisterSym : public SymbolRecord {
499
public:
500
  struct Header {
501
    ulittle16_t Register;
502
    ulittle16_t MayHaveNoName;
503
    ulittle32_t OffsetInParent;
504
  };
505
506
  explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
507
      : SymbolRecord(Kind) {}
508
  DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
509
      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
510
14
        RecordOffset(RecordOffset) {}
511
512
  uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
513
514
  Header Hdr;
515
  LocalVariableAddrRange Range;
516
  std::vector<LocalVariableAddrGap> Gaps;
517
518
  uint32_t RecordOffset;
519
};
520
521
// S_DEFRANGE_FRAMEPOINTER_REL
522
class DefRangeFramePointerRelSym : public SymbolRecord {
523
  static constexpr uint32_t RelocationOffset = 8;
524
525
public:
526
  explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
527
      : SymbolRecord(Kind) {}
528
  DefRangeFramePointerRelSym(uint32_t RecordOffset)
529
      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
530
        RecordOffset(RecordOffset) {}
531
532
  uint32_t getRelocationOffset() const {
533
    return RecordOffset + RelocationOffset;
534
  }
535
536
  int32_t Offset;
537
  LocalVariableAddrRange Range;
538
  std::vector<LocalVariableAddrGap> Gaps;
539
540
  uint32_t RecordOffset;
541
};
542
543
// S_DEFRANGE_REGISTER_REL
544
class DefRangeRegisterRelSym : public SymbolRecord {
545
public:
546
  struct Header {
547
    ulittle16_t Register;
548
    ulittle16_t Flags;
549
    little32_t BasePointerOffset;
550
  };
551
552
  explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
553
  explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
554
      : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
555
212
        RecordOffset(RecordOffset) {}
556
557
  // The flags implement this notional bitfield:
558
  //   uint16_t IsSubfield : 1;
559
  //   uint16_t Padding : 3;
560
  //   uint16_t OffsetInParent : 12;
561
  enum : uint16_t {
562
    IsSubfieldFlag = 1,
563
    OffsetInParentShift = 4,
564
  };
565
566
  bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
567
  uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
568
569
  uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
570
571
  Header Hdr;
572
  LocalVariableAddrRange Range;
573
  std::vector<LocalVariableAddrGap> Gaps;
574
575
  uint32_t RecordOffset;
576
};
577
578
// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
579
class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
580
public:
581
  explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
582
      : SymbolRecord(Kind) {}
583
  explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
584
      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
585
        RecordOffset(RecordOffset) {}
586
587
  int32_t Offset;
588
589
  uint32_t RecordOffset;
590
};
591
592
// S_BLOCK32
593
class BlockSym : public SymbolRecord {
594
  static constexpr uint32_t RelocationOffset = 16;
595
596
public:
597
  explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
598
  explicit BlockSym(uint32_t RecordOffset)
599
      : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
600
601
  uint32_t getRelocationOffset() const {
602
    return RecordOffset + RelocationOffset;
603
  }
604
605
  uint32_t Parent;
606
  uint32_t End;
607
  uint32_t CodeSize;
608
  uint32_t CodeOffset;
609
  uint16_t Segment;
610
  StringRef Name;
611
612
  uint32_t RecordOffset;
613
};
614
615
// S_LABEL32
616
class LabelSym : public SymbolRecord {
617
  static constexpr uint32_t RelocationOffset = 4;
618
619
public:
620
  explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
621
  explicit LabelSym(uint32_t RecordOffset)
622
      : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
623
624
  uint32_t getRelocationOffset() const {
625
    return RecordOffset + RelocationOffset;
626
  }
627
628
  uint32_t CodeOffset;
629
  uint16_t Segment;
630
  ProcSymFlags Flags;
631
  StringRef Name;
632
633
  uint32_t RecordOffset;
634
};
635
636
// S_OBJNAME
637
class ObjNameSym : public SymbolRecord {
638
public:
639
  explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
640
  ObjNameSym(uint32_t RecordOffset)
641
      : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
642
  }
643
644
  uint32_t Signature;
645
  StringRef Name;
646
647
  uint32_t RecordOffset;
648
};
649
650
// S_ENVBLOCK
651
class EnvBlockSym : public SymbolRecord {
652
public:
653
  explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
654
  EnvBlockSym(uint32_t RecordOffset)
655
      : SymbolRecord(SymbolRecordKind::EnvBlockSym),
656
        RecordOffset(RecordOffset) {}
657
658
  std::vector<StringRef> Fields;
659
660
  uint32_t RecordOffset;
661
};
662
663
// S_EXPORT
664
class ExportSym : public SymbolRecord {
665
public:
666
  explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
667
  ExportSym(uint32_t RecordOffset)
668
      : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
669
670
  uint16_t Ordinal;
671
  ExportFlags Flags;
672
  StringRef Name;
673
674
  uint32_t RecordOffset;
675
};
676
677
// S_FILESTATIC
678
class FileStaticSym : public SymbolRecord {
679
public:
680
  explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
681
  FileStaticSym(uint32_t RecordOffset)
682
      : SymbolRecord(SymbolRecordKind::FileStaticSym),
683
        RecordOffset(RecordOffset) {}
684
685
  TypeIndex Index;
686
  uint32_t ModFilenameOffset;
687
  LocalSymFlags Flags;
688
  StringRef Name;
689
690
  uint32_t RecordOffset;
691
};
692
693
// S_COMPILE2
694
class Compile2Sym : public SymbolRecord {
695
public:
696
  explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
697
  Compile2Sym(uint32_t RecordOffset)
698
      : SymbolRecord(SymbolRecordKind::Compile2Sym),
699
        RecordOffset(RecordOffset) {}
700
701
  CompileSym2Flags Flags;
702
  CPUType Machine;
703
  uint16_t VersionFrontendMajor;
704
  uint16_t VersionFrontendMinor;
705
  uint16_t VersionFrontendBuild;
706
  uint16_t VersionBackendMajor;
707
  uint16_t VersionBackendMinor;
708
  uint16_t VersionBackendBuild;
709
  StringRef Version;
710
  std::vector<StringRef> ExtraStrings;
711
712
  uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
713
  uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
714
715
  uint32_t RecordOffset;
716
};
717
718
// S_COMPILE3
719
class Compile3Sym : public SymbolRecord {
720
public:
721
  explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
722
  Compile3Sym(uint32_t RecordOffset)
723
      : SymbolRecord(SymbolRecordKind::Compile3Sym),
724
        RecordOffset(RecordOffset) {}
725
726
  CompileSym3Flags Flags;
727
  CPUType Machine;
728
  uint16_t VersionFrontendMajor;
729
  uint16_t VersionFrontendMinor;
730
  uint16_t VersionFrontendBuild;
731
  uint16_t VersionFrontendQFE;
732
  uint16_t VersionBackendMajor;
733
  uint16_t VersionBackendMinor;
734
  uint16_t VersionBackendBuild;
735
  uint16_t VersionBackendQFE;
736
  StringRef Version;
737
738
  void setLanguage(SourceLanguage Lang) {
739
    Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
740
  }
741
742
  uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
743
  uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
744
745
  uint32_t RecordOffset;
746
};
747
748
// S_FRAMEPROC
749
class FrameProcSym : public SymbolRecord {
750
public:
751
  explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
752
  explicit FrameProcSym(uint32_t RecordOffset)
753
      : SymbolRecord(SymbolRecordKind::FrameProcSym),
754
        RecordOffset(RecordOffset) {}
755
756
  uint32_t TotalFrameBytes;
757
  uint32_t PaddingFrameBytes;
758
  uint32_t OffsetToPadding;
759
  uint32_t BytesOfCalleeSavedRegisters;
760
  uint32_t OffsetOfExceptionHandler;
761
  uint16_t SectionIdOfExceptionHandler;
762
  FrameProcedureOptions Flags;
763
764
  uint32_t RecordOffset;
765
};
766
767
// S_CALLSITEINFO
768
class CallSiteInfoSym : public SymbolRecord {
769
  static constexpr uint32_t RelocationOffset = 4;
770
771
public:
772
  explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
773
  explicit CallSiteInfoSym(uint32_t RecordOffset)
774
      : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
775
776
  uint32_t getRelocationOffset() const {
777
    return RecordOffset + RelocationOffset;
778
  }
779
780
  uint32_t CodeOffset;
781
  uint16_t Segment;
782
  TypeIndex Type;
783
784
  uint32_t RecordOffset;
785
};
786
787
// S_HEAPALLOCSITE
788
class HeapAllocationSiteSym : public SymbolRecord {
789
  static constexpr uint32_t RelocationOffset = 4;
790
791
public:
792
  explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
793
  explicit HeapAllocationSiteSym(uint32_t RecordOffset)
794
      : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
795
        RecordOffset(RecordOffset) {}
796
797
  uint32_t getRelocationOffset() const {
798
    return RecordOffset + RelocationOffset;
799
  }
800
801
  uint32_t CodeOffset;
802
  uint16_t Segment;
803
  uint16_t CallInstructionSize;
804
  TypeIndex Type;
805
806
  uint32_t RecordOffset;
807
};
808
809
// S_FRAMECOOKIE
810
class FrameCookieSym : public SymbolRecord {
811
  static constexpr uint32_t RelocationOffset = 4;
812
813
public:
814
  explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
815
  explicit FrameCookieSym(uint32_t RecordOffset)
816
      : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
817
818
  uint32_t getRelocationOffset() const {
819
    return RecordOffset + RelocationOffset;
820
  }
821
822
  uint32_t CodeOffset;
823
  uint16_t Register;
824
  FrameCookieKind CookieKind;
825
  uint8_t Flags;
826
827
  uint32_t RecordOffset;
828
};
829
830
// S_UDT, S_COBOLUDT
831
class UDTSym : public SymbolRecord {
832
public:
833
  explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
834
  explicit UDTSym(uint32_t RecordOffset)
835
      : SymbolRecord(SymbolRecordKind::UDTSym) {}
836
837
  TypeIndex Type;
838
  StringRef Name;
839
840
  uint32_t RecordOffset;
841
};
842
843
// S_BUILDINFO
844
class BuildInfoSym : public SymbolRecord {
845
public:
846
  explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
847
  BuildInfoSym(uint32_t RecordOffset)
848
      : SymbolRecord(SymbolRecordKind::BuildInfoSym),
849
        RecordOffset(RecordOffset) {}
850
851
  TypeIndex BuildId;
852
853
  uint32_t RecordOffset;
854
};
855
856
// S_BPREL32
857
class BPRelativeSym : public SymbolRecord {
858
public:
859
  explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
860
  explicit BPRelativeSym(uint32_t RecordOffset)
861
      : SymbolRecord(SymbolRecordKind::BPRelativeSym),
862
        RecordOffset(RecordOffset) {}
863
864
  int32_t Offset;
865
  TypeIndex Type;
866
  StringRef Name;
867
868
  uint32_t RecordOffset;
869
};
870
871
// S_REGREL32
872
class RegRelativeSym : public SymbolRecord {
873
public:
874
  explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
875
  explicit RegRelativeSym(uint32_t RecordOffset)
876
      : SymbolRecord(SymbolRecordKind::RegRelativeSym),
877
        RecordOffset(RecordOffset) {}
878
879
  uint32_t Offset;
880
  TypeIndex Type;
881
  RegisterId Register;
882
  StringRef Name;
883
884
  uint32_t RecordOffset;
885
};
886
887
// S_CONSTANT, S_MANCONSTANT
888
class ConstantSym : public SymbolRecord {
889
public:
890
  explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
891
  ConstantSym(uint32_t RecordOffset)
892
      : SymbolRecord(SymbolRecordKind::ConstantSym),
893
0
        RecordOffset(RecordOffset) {}
894
895
  TypeIndex Type;
896
  APSInt Value;
897
  StringRef Name;
898
899
  uint32_t RecordOffset;
900
};
901
902
// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
903
class DataSym : public SymbolRecord {
904
  static constexpr uint32_t RelocationOffset = 8;
905
906
public:
907
  explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
908
  DataSym(uint32_t RecordOffset)
909
      : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
910
911
  uint32_t getRelocationOffset() const {
912
    return RecordOffset + RelocationOffset;
913
  }
914
915
  TypeIndex Type;
916
  uint32_t DataOffset;
917
  uint16_t Segment;
918
  StringRef Name;
919
920
  uint32_t RecordOffset;
921
};
922
923
// S_LTHREAD32, S_GTHREAD32
924
class ThreadLocalDataSym : public SymbolRecord {
925
  static constexpr uint32_t RelocationOffset = 8;
926
927
public:
928
  explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
929
  explicit ThreadLocalDataSym(uint32_t RecordOffset)
930
      : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
931
        RecordOffset(RecordOffset) {}
932
933
  uint32_t getRelocationOffset() const {
934
    return RecordOffset + RelocationOffset;
935
  }
936
937
  TypeIndex Type;
938
  uint32_t DataOffset;
939
  uint16_t Segment;
940
  StringRef Name;
941
942
  uint32_t RecordOffset;
943
};
944
945
// S_ANNOTATION
946
947
using CVSymbol = CVRecord<SymbolKind>;
948
using CVSymbolArray = VarStreamArray<CVSymbol>;
949
950
Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
951
                                        uint32_t Offset);
952
953
} // end namespace codeview
954
} // end namespace llvm
955
956
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H