Coverage Report

Created: 2019-07-24 05:18

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