Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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