Coverage Report

Created: 2019-02-15 18:59

/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
// 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_range.h"
17
#include "llvm/DebugInfo/CodeView/CVRecord.h"
18
#include "llvm/DebugInfo/CodeView/CodeView.h"
19
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
20
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
21
#include "llvm/Support/BinaryStreamArray.h"
22
#include "llvm/Support/Endian.h"
23
#include <cstdint>
24
#include <vector>
25
26
namespace llvm {
27
namespace codeview {
28
29
class SymbolRecord {
30
protected:
31
4.39k
  explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
32
33
public:
34
  SymbolRecordKind getKind() const { return Kind; }
35
36
  SymbolRecordKind Kind;
37
};
38
39
// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
40
// S_LPROC32_DPC_ID
41
class ProcSym : public SymbolRecord {
42
  static constexpr uint32_t RelocationOffset = 32;
43
44
public:
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
69
class Thunk32Sym : public SymbolRecord {
70
public:
71
  explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
72
  Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
73
      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
74
75
  uint32_t Parent;
76
  uint32_t End;
77
  uint32_t Next;
78
  uint32_t Offset;
79
  uint16_t Segment;
80
  uint16_t Length;
81
  ThunkOrdinal Thunk;
82
  StringRef Name;
83
  ArrayRef<uint8_t> VariantData;
84
85
  uint32_t RecordOffset;
86
};
87
88
// S_TRAMPOLINE
89
class TrampolineSym : public SymbolRecord {
90
public:
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;
97
  uint32_t ThunkOffset;
98
  uint32_t TargetOffset;
99
  uint16_t ThunkSection;
100
  uint16_t TargetSection;
101
102
  uint32_t RecordOffset;
103
};
104
105
// S_SECTION
106
class SectionSym : public SymbolRecord {
107
public:
108
  explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
109
  SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
110
      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
111
112
  uint16_t SectionNumber;
113
  uint8_t Alignment;
114
  uint32_t Rva;
115
  uint32_t Length;
116
  uint32_t Characteristics;
117
  StringRef Name;
118
119
  uint32_t RecordOffset;
120
};
121
122
// S_COFFGROUP
123
class CoffGroupSym : public SymbolRecord {
124
public:
125
  explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
126
  CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
127
      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
128
129
  uint32_t Size;
130
  uint32_t Characteristics;
131
  uint32_t Offset;
132
  uint16_t Segment;
133
  StringRef Name;
134
135
  uint32_t RecordOffset;
136
};
137
138
class ScopeEndSym : public SymbolRecord {
139
public:
140
  explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
141
  ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
142
      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
143
144
  uint32_t RecordOffset;
145
};
146
147
class CallerSym : public SymbolRecord {
148
public:
149
  explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
150
  CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
151
      : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
152
153
  std::vector<TypeIndex> Indices;
154
155
  uint32_t RecordOffset;
156
};
157
158
struct BinaryAnnotationIterator {
159
  struct AnnotationData {
160
    BinaryAnnotationsOpCode OpCode;
161
    StringRef Name;
162
    uint32_t U1;
163
    uint32_t U2;
164
    int32_t S1;
165
  };
166
167
  BinaryAnnotationIterator() = default;
168
  BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
169
  BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
170
      : Data(Other.Data) {}
171
172
  bool operator==(BinaryAnnotationIterator Other) const {
173
    return Data == Other.Data;
174
  }
175
176
  bool operator!=(const BinaryAnnotationIterator &Other) const {
177
    return !(*this == Other);
178
  }
179
180
  BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
181
    Data = Other.Data;
182
    return *this;
183
  }
184
185
  BinaryAnnotationIterator &operator++() {
186
    if (!ParseCurrentAnnotation()) {
187
      *this = BinaryAnnotationIterator();
188
      return *this;
189
    }
190
    Data = Next;
191
    Next = ArrayRef<uint8_t>();
192
    Current.reset();
193
    return *this;
194
  }
195
196
  BinaryAnnotationIterator operator++(int) {
197
    BinaryAnnotationIterator Orig(*this);
198
    ++(*this);
199
    return Orig;
200
  }
201
202
  const AnnotationData &operator*() {
203
    ParseCurrentAnnotation();
204
    return Current.getValue();
205
  }
206
207
private:
208
  static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
209
    if (Annotations.empty())
210
      return -1;
211
212
    uint8_t FirstByte = Annotations.front();
213
    Annotations = Annotations.drop_front();
214
215
    if ((FirstByte & 0x80) == 0x00)
216
      return FirstByte;
217
218
    if (Annotations.empty())
219
      return -1;
220
221
    uint8_t SecondByte = Annotations.front();
222
    Annotations = Annotations.drop_front();
223
224
    if ((FirstByte & 0xC0) == 0x80)
225
      return ((FirstByte & 0x3F) << 8) | SecondByte;
226
227
    if (Annotations.empty())
228
      return -1;
229
230
    uint8_t ThirdByte = Annotations.front();
231
    Annotations = Annotations.drop_front();
232
233
    if (Annotations.empty())
234
      return -1;
235
236
    uint8_t FourthByte = Annotations.front();
237
    Annotations = Annotations.drop_front();
238
239
    if ((FirstByte & 0xE0) == 0xC0)
240
      return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
241
             (ThirdByte << 8) | FourthByte;
242
243
    return -1;
244
  };
245
246
  static int32_t DecodeSignedOperand(uint32_t Operand) {
247
    if (Operand & 1)
248
      return -(Operand >> 1);
249
    return Operand >> 1;
250
  };
251
252
  static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
253
    return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
254
  };
255
256
  bool ParseCurrentAnnotation() {
257
    if (Current.hasValue())
258
      return true;
259
260
    Next = Data;
261
    uint32_t Op = GetCompressedAnnotation(Next);
262
    AnnotationData Result;
263
    Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
264
    switch (Result.OpCode) {
265
    case BinaryAnnotationsOpCode::Invalid:
266
      Result.Name = "Invalid";
267
      Next = ArrayRef<uint8_t>();
268
      break;
269
    case BinaryAnnotationsOpCode::CodeOffset:
270
      Result.Name = "CodeOffset";
271
      Result.U1 = GetCompressedAnnotation(Next);
272
      break;
273
    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
274
      Result.Name = "ChangeCodeOffsetBase";
275
      Result.U1 = GetCompressedAnnotation(Next);
276
      break;
277
    case BinaryAnnotationsOpCode::ChangeCodeOffset:
278
      Result.Name = "ChangeCodeOffset";
279
      Result.U1 = GetCompressedAnnotation(Next);
280
      break;
281
    case BinaryAnnotationsOpCode::ChangeCodeLength:
282
      Result.Name = "ChangeCodeLength";
283
      Result.U1 = GetCompressedAnnotation(Next);
284
      break;
285
    case BinaryAnnotationsOpCode::ChangeFile:
286
      Result.Name = "ChangeFile";
287
      Result.U1 = GetCompressedAnnotation(Next);
288
      break;
289
    case BinaryAnnotationsOpCode::ChangeLineEndDelta:
290
      Result.Name = "ChangeLineEndDelta";
291
      Result.U1 = GetCompressedAnnotation(Next);
292
      break;
293
    case BinaryAnnotationsOpCode::ChangeRangeKind:
294
      Result.Name = "ChangeRangeKind";
295
      Result.U1 = GetCompressedAnnotation(Next);
296
      break;
297
    case BinaryAnnotationsOpCode::ChangeColumnStart:
298
      Result.Name = "ChangeColumnStart";
299
      Result.U1 = GetCompressedAnnotation(Next);
300
      break;
301
    case BinaryAnnotationsOpCode::ChangeColumnEnd:
302
      Result.Name = "ChangeColumnEnd";
303
      Result.U1 = GetCompressedAnnotation(Next);
304
      break;
305
    case BinaryAnnotationsOpCode::ChangeLineOffset:
306
      Result.Name = "ChangeLineOffset";
307
      Result.S1 = DecodeSignedOperand(Next);
308
      break;
309
    case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
310
      Result.Name = "ChangeColumnEndDelta";
311
      Result.S1 = DecodeSignedOperand(Next);
312
      break;
313
    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
314
      Result.Name = "ChangeCodeOffsetAndLineOffset";
315
      uint32_t Annotation = GetCompressedAnnotation(Next);
316
      Result.S1 = DecodeSignedOperand(Annotation >> 4);
317
      Result.U1 = Annotation & 0xf;
318
      break;
319
    }
320
    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
321
      Result.Name = "ChangeCodeLengthAndCodeOffset";
322
      Result.U1 = GetCompressedAnnotation(Next);
323
      Result.U2 = GetCompressedAnnotation(Next);
324
      break;
325
    }
326
    }
327
    Current = Result;
328
    return true;
329
  }
330
331
  Optional<AnnotationData> Current;
332
  ArrayRef<uint8_t> Data;
333
  ArrayRef<uint8_t> Next;
334
};
335
336
// S_INLINESITE
337
class InlineSiteSym : public SymbolRecord {
338
public:
339
  explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
340
  InlineSiteSym(uint32_t RecordOffset)
341
      : SymbolRecord(SymbolRecordKind::InlineSiteSym),
342
        RecordOffset(RecordOffset) {}
343
344
  iterator_range<BinaryAnnotationIterator> annotations() const {
345
    return make_range(BinaryAnnotationIterator(AnnotationData),
346
                      BinaryAnnotationIterator());
347
  }
348
349
  uint32_t Parent;
350
  uint32_t End;
351
  TypeIndex Inlinee;
352
  std::vector<uint8_t> AnnotationData;
353
354
  uint32_t RecordOffset;
355
};
356
357
// S_PUB32
358
class PublicSym32 : public SymbolRecord {
359
public:
360
  PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
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
  uint16_t modi() const { return Module - 1; }
403
  uint32_t RecordOffset;
404
};
405
406
// S_LOCAL
407
class LocalSym : public SymbolRecord {
408
public:
409
  explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
410
  explicit LocalSym(uint32_t RecordOffset)
411
      : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
412
413
  TypeIndex Type;
414
  LocalSymFlags Flags;
415
  StringRef Name;
416
417
  uint32_t RecordOffset;
418
};
419
420
struct LocalVariableAddrRange {
421
  uint32_t OffsetStart;
422
  uint16_t ISectStart;
423
  uint16_t Range;
424
};
425
426
struct LocalVariableAddrGap {
427
  uint16_t GapStartOffset;
428
  uint16_t Range;
429
};
430
431
enum : uint16_t { MaxDefRange = 0xf000 };
432
433
// S_DEFRANGE
434
class DefRangeSym : public SymbolRecord {
435
  static constexpr uint32_t RelocationOffset = 8;
436
437
public:
438
  explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
439
  explicit DefRangeSym(uint32_t RecordOffset)
440
      : SymbolRecord(SymbolRecordKind::DefRangeSym),
441
        RecordOffset(RecordOffset) {}
442
443
  uint32_t getRelocationOffset() const {
444
    return RecordOffset + RelocationOffset;
445
  }
446
447
  uint32_t Program;
448
  LocalVariableAddrRange Range;
449
  std::vector<LocalVariableAddrGap> Gaps;
450
451
  uint32_t RecordOffset;
452
};
453
454
// S_DEFRANGE_SUBFIELD
455
class DefRangeSubfieldSym : public SymbolRecord {
456
  static constexpr uint32_t RelocationOffset = 12;
457
458
public:
459
  explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
460
  DefRangeSubfieldSym(uint32_t RecordOffset)
461
      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
462
        RecordOffset(RecordOffset) {}
463
464
  uint32_t getRelocationOffset() const {
465
    return RecordOffset + RelocationOffset;
466
  }
467
468
  uint32_t Program;
469
  uint16_t OffsetInParent;
470
  LocalVariableAddrRange Range;
471
  std::vector<LocalVariableAddrGap> Gaps;
472
473
  uint32_t RecordOffset;
474
};
475
476
// S_DEFRANGE_REGISTER
477
class DefRangeRegisterSym : public SymbolRecord {
478
public:
479
  struct Header {
480
    ulittle16_t Register;
481
    ulittle16_t MayHaveNoName;
482
  };
483
484
  explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
485
  DefRangeRegisterSym(uint32_t RecordOffset)
486
      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
487
        RecordOffset(RecordOffset) {}
488
489
  uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
490
491
  Header Hdr;
492
  LocalVariableAddrRange Range;
493
  std::vector<LocalVariableAddrGap> Gaps;
494
495
  uint32_t RecordOffset;
496
};
497
498
// S_DEFRANGE_SUBFIELD_REGISTER
499
class DefRangeSubfieldRegisterSym : public SymbolRecord {
500
public:
501
  struct Header {
502
    ulittle16_t Register;
503
    ulittle16_t MayHaveNoName;
504
    ulittle32_t OffsetInParent;
505
  };
506
507
  explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
508
      : SymbolRecord(Kind) {}
509
  DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
510
      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
511
        RecordOffset(RecordOffset) {}
512
513
  uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
514
515
  Header Hdr;
516
  LocalVariableAddrRange Range;
517
  std::vector<LocalVariableAddrGap> Gaps;
518
519
  uint32_t RecordOffset;
520
};
521
522
// S_DEFRANGE_FRAMEPOINTER_REL
523
class DefRangeFramePointerRelSym : public SymbolRecord {
524
  static constexpr uint32_t RelocationOffset = 8;
525
526
public:
527
  explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
528
      : SymbolRecord(Kind) {}
529
  DefRangeFramePointerRelSym(uint32_t RecordOffset)
530
      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
531
        RecordOffset(RecordOffset) {}
532
533
  uint32_t getRelocationOffset() const {
534
    return RecordOffset + RelocationOffset;
535
  }
536
537
  int32_t Offset;
538
  LocalVariableAddrRange Range;
539
  std::vector<LocalVariableAddrGap> Gaps;
540
541
  uint32_t RecordOffset;
542
};
543
544
// S_DEFRANGE_REGISTER_REL
545
class DefRangeRegisterRelSym : public SymbolRecord {
546
public:
547
  struct Header {
548
    ulittle16_t Register;
549
    ulittle16_t Flags;
550
    little32_t BasePointerOffset;
551
  };
552
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(Header); }
571
572
  Header Hdr;
573
  LocalVariableAddrRange Range;
574
  std::vector<LocalVariableAddrGap> Gaps;
575
576
  uint32_t RecordOffset;
577
};
578
579
// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
580
class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
581
public:
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;
589
590
  uint32_t RecordOffset;
591
};
592
593
// S_BLOCK32
594
class BlockSym : public SymbolRecord {
595
  static constexpr uint32_t RelocationOffset = 16;
596
597
public:
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;
607
  uint32_t End;
608
  uint32_t CodeSize;
609
  uint32_t CodeOffset;
610
  uint16_t Segment;
611
  StringRef Name;
612
613
  uint32_t RecordOffset;
614
};
615
616
// S_LABEL32
617
class LabelSym : public SymbolRecord {
618
  static constexpr uint32_t RelocationOffset = 4;
619
620
public:
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;
630
  uint16_t Segment;
631
  ProcSymFlags Flags;
632
  StringRef Name;
633
634
  uint32_t RecordOffset;
635
};
636
637
// S_OBJNAME
638
class ObjNameSym : public SymbolRecord {
639
public:
640
  explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
641
  explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
642
  ObjNameSym(uint32_t RecordOffset)
643
      : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
644
  }
645
646
  uint32_t Signature;
647
  StringRef Name;
648
649
  uint32_t RecordOffset;
650
};
651
652
// S_ENVBLOCK
653
class EnvBlockSym : public SymbolRecord {
654
public:
655
  explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
656
  EnvBlockSym(uint32_t RecordOffset)
657
      : SymbolRecord(SymbolRecordKind::EnvBlockSym),
658
        RecordOffset(RecordOffset) {}
659
660
  std::vector<StringRef> Fields;
661
662
  uint32_t RecordOffset;
663
};
664
665
// S_EXPORT
666
class ExportSym : public SymbolRecord {
667
public:
668
  explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
669
  ExportSym(uint32_t RecordOffset)
670
      : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
671
672
  uint16_t Ordinal;
673
  ExportFlags Flags;
674
  StringRef Name;
675
676
  uint32_t RecordOffset;
677
};
678
679
// S_FILESTATIC
680
class FileStaticSym : public SymbolRecord {
681
public:
682
  explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
683
  FileStaticSym(uint32_t RecordOffset)
684
      : SymbolRecord(SymbolRecordKind::FileStaticSym),
685
        RecordOffset(RecordOffset) {}
686
687
  TypeIndex Index;
688
  uint32_t ModFilenameOffset;
689
  LocalSymFlags Flags;
690
  StringRef Name;
691
692
  uint32_t RecordOffset;
693
};
694
695
// S_COMPILE2
696
class Compile2Sym : public SymbolRecord {
697
public:
698
  explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
699
  Compile2Sym(uint32_t RecordOffset)
700
      : SymbolRecord(SymbolRecordKind::Compile2Sym),
701
        RecordOffset(RecordOffset) {}
702
703
  CompileSym2Flags Flags;
704
  CPUType Machine;
705
  uint16_t VersionFrontendMajor;
706
  uint16_t VersionFrontendMinor;
707
  uint16_t VersionFrontendBuild;
708
  uint16_t VersionBackendMajor;
709
  uint16_t VersionBackendMinor;
710
  uint16_t VersionBackendBuild;
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;
718
};
719
720
// S_COMPILE3
721
class Compile3Sym : public SymbolRecord {
722
public:
723
  Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
724
  explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
725
  Compile3Sym(uint32_t RecordOffset)
726
      : SymbolRecord(SymbolRecordKind::Compile3Sym),
727
        RecordOffset(RecordOffset) {}
728
729
  CompileSym3Flags Flags;
730
  CPUType Machine;
731
  uint16_t VersionFrontendMajor;
732
  uint16_t VersionFrontendMinor;
733
  uint16_t VersionFrontendBuild;
734
  uint16_t VersionFrontendQFE;
735
  uint16_t VersionBackendMajor;
736
  uint16_t VersionBackendMinor;
737
  uint16_t VersionBackendBuild;
738
  uint16_t VersionBackendQFE;
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;
758
};
759
760
// S_FRAMEPROC
761
class FrameProcSym : public SymbolRecord {
762
public:
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;
769
  uint32_t PaddingFrameBytes;
770
  uint32_t OffsetToPadding;
771
  uint32_t BytesOfCalleeSavedRegisters;
772
  uint32_t OffsetOfExceptionHandler;
773
  uint16_t SectionIdOfExceptionHandler;
774
  FrameProcedureOptions Flags;
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;
789
790
private:
791
};
792
793
// S_CALLSITEINFO
794
class CallSiteInfoSym : public SymbolRecord {
795
  static constexpr uint32_t RelocationOffset = 4;
796
797
public:
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;
807
  uint16_t Segment;
808
  TypeIndex Type;
809
810
  uint32_t RecordOffset;
811
};
812
813
// S_HEAPALLOCSITE
814
class HeapAllocationSiteSym : public SymbolRecord {
815
  static constexpr uint32_t RelocationOffset = 4;
816
817
public:
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;
828
  uint16_t Segment;
829
  uint16_t CallInstructionSize;
830
  TypeIndex Type;
831
832
  uint32_t RecordOffset;
833
};
834
835
// S_FRAMECOOKIE
836
class FrameCookieSym : public SymbolRecord {
837
  static constexpr uint32_t RelocationOffset = 4;
838
839
public:
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;
849
  uint16_t Register;
850
  FrameCookieKind CookieKind;
851
  uint8_t Flags;
852
853
  uint32_t RecordOffset;
854
};
855
856
// S_UDT, S_COBOLUDT
857
class UDTSym : public SymbolRecord {
858
public:
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;
867
};
868
869
// S_BUILDINFO
870
class BuildInfoSym : public SymbolRecord {
871
public:
872
  explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
873
  BuildInfoSym(uint32_t RecordOffset)
874
      : SymbolRecord(SymbolRecordKind::BuildInfoSym),
875
        RecordOffset(RecordOffset) {}
876
877
  TypeIndex BuildId;
878
879
  uint32_t RecordOffset;
880
};
881
882
// S_BPREL32
883
class BPRelativeSym : public SymbolRecord {
884
public:
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;
891
  TypeIndex Type;
892
  StringRef Name;
893
894
  uint32_t RecordOffset;
895
};
896
897
// S_REGREL32
898
class RegRelativeSym : public SymbolRecord {
899
public:
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;
906
  TypeIndex Type;
907
  RegisterId Register;
908
  StringRef Name;
909
910
  uint32_t RecordOffset;
911
};
912
913
// S_CONSTANT, S_MANCONSTANT
914
class ConstantSym : public SymbolRecord {
915
public:
916
  explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
917
  ConstantSym(uint32_t RecordOffset)
918
      : SymbolRecord(SymbolRecordKind::ConstantSym),
919
0
        RecordOffset(RecordOffset) {}
920
921
  TypeIndex Type;
922
  APSInt Value;
923
  StringRef Name;
924
925
  uint32_t RecordOffset;
926
};
927
928
// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
929
class DataSym : public SymbolRecord {
930
  static constexpr uint32_t RelocationOffset = 8;
931
932
public:
933
  explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
934
  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;
943
  uint16_t Segment;
944
  StringRef Name;
945
946
  uint32_t RecordOffset;
947
};
948
949
// S_LTHREAD32, S_GTHREAD32
950
class ThreadLocalDataSym : public SymbolRecord {
951
  static constexpr uint32_t RelocationOffset = 8;
952
953
public:
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;
965
  uint16_t Segment;
966
  StringRef Name;
967
968
  uint32_t RecordOffset;
969
};
970
971
// S_UNAMESPACE
972
class UsingNamespaceSym : public SymbolRecord {
973
public:
974
  explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
975
  explicit UsingNamespaceSym(uint32_t RecordOffset)
976
      : SymbolRecord(SymbolRecordKind::RegRelativeSym),
977
        RecordOffset(RecordOffset) {}
978
979
  StringRef Name;
980
981
  uint32_t RecordOffset;
982
};
983
984
// S_ANNOTATION
985
986
using CVSymbol = CVRecord<SymbolKind>;
987
using CVSymbolArray = VarStreamArray<CVSymbol>;
988
989
Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
990
                                        uint32_t Offset);
991
992
} // end namespace codeview
993
} // end namespace llvm
994
995
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H