Line data Source code
1 : //===- SymbolRecord.h -------------------------------------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
11 : #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
12 :
13 : #include "llvm/ADT/APSInt.h"
14 : #include "llvm/ADT/ArrayRef.h"
15 : #include "llvm/ADT/Optional.h"
16 : #include "llvm/ADT/StringRef.h"
17 : #include "llvm/ADT/iterator_range.h"
18 : #include "llvm/DebugInfo/CodeView/CVRecord.h"
19 : #include "llvm/DebugInfo/CodeView/CodeView.h"
20 : #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
21 : #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 : #include "llvm/Support/BinaryStreamArray.h"
23 : #include "llvm/Support/Endian.h"
24 : #include <cstdint>
25 : #include <vector>
26 :
27 : namespace llvm {
28 : namespace codeview {
29 :
30 : class SymbolRecord {
31 : protected:
32 4087 : explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
33 :
34 : public:
35 0 : 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 998 : explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
47 : ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
48 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
49 :
50 0 : uint32_t getRelocationOffset() const {
51 182 : 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 4 : explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
73 : Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
74 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
75 :
76 : uint32_t Parent;
77 : uint32_t End;
78 : uint32_t Next;
79 : uint32_t Offset;
80 : uint16_t Segment;
81 : uint16_t Length;
82 : ThunkOrdinal Thunk;
83 : StringRef Name;
84 : ArrayRef<uint8_t> VariantData;
85 :
86 : uint32_t RecordOffset;
87 : };
88 :
89 : // S_TRAMPOLINE
90 : class TrampolineSym : public SymbolRecord {
91 : public:
92 6 : explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
93 : TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
94 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
95 :
96 : TrampolineType Type;
97 : uint16_t Size;
98 : uint32_t ThunkOffset;
99 : uint32_t TargetOffset;
100 : uint16_t ThunkSection;
101 : uint16_t TargetSection;
102 :
103 : uint32_t RecordOffset;
104 : };
105 :
106 : // S_SECTION
107 : class SectionSym : public SymbolRecord {
108 : public:
109 291 : explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
110 : SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
111 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
112 :
113 : uint16_t SectionNumber;
114 : uint8_t Alignment;
115 : uint32_t Rva;
116 : uint32_t Length;
117 : uint32_t Characteristics;
118 : StringRef Name;
119 :
120 : uint32_t RecordOffset;
121 : };
122 :
123 : // S_COFFGROUP
124 : class CoffGroupSym : public SymbolRecord {
125 : public:
126 30 : explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
127 : CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
128 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
129 :
130 : uint32_t Size;
131 : uint32_t Characteristics;
132 : uint32_t Offset;
133 : uint16_t Segment;
134 : StringRef Name;
135 :
136 : uint32_t RecordOffset;
137 : };
138 :
139 : class ScopeEndSym : public SymbolRecord {
140 : public:
141 358 : explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
142 : ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
143 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
144 :
145 : uint32_t RecordOffset;
146 : };
147 :
148 2 : class CallerSym : public SymbolRecord {
149 : public:
150 15 : explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
151 : CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
152 : : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
153 :
154 : std::vector<TypeIndex> Indices;
155 :
156 : uint32_t RecordOffset;
157 : };
158 :
159 : struct BinaryAnnotationIterator {
160 : struct AnnotationData {
161 : BinaryAnnotationsOpCode OpCode;
162 : StringRef Name;
163 : uint32_t U1;
164 : uint32_t U2;
165 : int32_t S1;
166 : };
167 :
168 : BinaryAnnotationIterator() = default;
169 : BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
170 : BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
171 250 : : Data(Other.Data) {}
172 :
173 125 : bool operator==(BinaryAnnotationIterator Other) const {
174 125 : return Data == Other.Data;
175 : }
176 :
177 0 : bool operator!=(const BinaryAnnotationIterator &Other) const {
178 125 : return !(*this == Other);
179 : }
180 :
181 0 : BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
182 0 : Data = Other.Data;
183 0 : return *this;
184 : }
185 :
186 95 : BinaryAnnotationIterator &operator++() {
187 95 : if (!ParseCurrentAnnotation()) {
188 : *this = BinaryAnnotationIterator();
189 0 : return *this;
190 : }
191 95 : Data = Next;
192 95 : Next = ArrayRef<uint8_t>();
193 : Current.reset();
194 : return *this;
195 : }
196 :
197 : BinaryAnnotationIterator operator++(int) {
198 : BinaryAnnotationIterator Orig(*this);
199 : ++(*this);
200 : return Orig;
201 : }
202 :
203 : const AnnotationData &operator*() {
204 95 : ParseCurrentAnnotation();
205 : return Current.getValue();
206 : }
207 :
208 : private:
209 195 : static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
210 195 : if (Annotations.empty())
211 : return -1;
212 :
213 195 : uint8_t FirstByte = Annotations.front();
214 195 : Annotations = Annotations.drop_front();
215 :
216 195 : if ((FirstByte & 0x80) == 0x00)
217 195 : return FirstByte;
218 :
219 0 : if (Annotations.empty())
220 : return -1;
221 :
222 0 : uint8_t SecondByte = Annotations.front();
223 0 : Annotations = Annotations.drop_front();
224 :
225 0 : if ((FirstByte & 0xC0) == 0x80)
226 0 : return ((FirstByte & 0x3F) << 8) | SecondByte;
227 :
228 0 : if (Annotations.empty())
229 : return -1;
230 :
231 0 : uint8_t ThirdByte = Annotations.front();
232 0 : Annotations = Annotations.drop_front();
233 :
234 0 : if (Annotations.empty())
235 : return -1;
236 :
237 0 : uint8_t FourthByte = Annotations.front();
238 0 : Annotations = Annotations.drop_front();
239 :
240 0 : if ((FirstByte & 0xE0) == 0xC0)
241 0 : return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
242 0 : (ThirdByte << 8) | FourthByte;
243 :
244 : return -1;
245 : };
246 :
247 : static int32_t DecodeSignedOperand(uint32_t Operand) {
248 14 : if (Operand & 1)
249 2 : return -(Operand >> 1);
250 48 : return Operand >> 1;
251 : };
252 :
253 : static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
254 14 : return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
255 : };
256 :
257 190 : bool ParseCurrentAnnotation() {
258 190 : if (Current.hasValue())
259 : return true;
260 :
261 95 : Next = Data;
262 95 : uint32_t Op = GetCompressedAnnotation(Next);
263 : AnnotationData Result;
264 : Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
265 95 : switch (Result.OpCode) {
266 : case BinaryAnnotationsOpCode::Invalid:
267 : Result.Name = "Invalid";
268 0 : Next = ArrayRef<uint8_t>();
269 0 : break;
270 : case BinaryAnnotationsOpCode::CodeOffset:
271 : Result.Name = "CodeOffset";
272 0 : Result.U1 = GetCompressedAnnotation(Next);
273 0 : break;
274 : case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
275 : Result.Name = "ChangeCodeOffsetBase";
276 0 : Result.U1 = GetCompressedAnnotation(Next);
277 0 : break;
278 : case BinaryAnnotationsOpCode::ChangeCodeOffset:
279 : Result.Name = "ChangeCodeOffset";
280 9 : Result.U1 = GetCompressedAnnotation(Next);
281 9 : break;
282 : case BinaryAnnotationsOpCode::ChangeCodeLength:
283 : Result.Name = "ChangeCodeLength";
284 27 : Result.U1 = GetCompressedAnnotation(Next);
285 27 : break;
286 : case BinaryAnnotationsOpCode::ChangeFile:
287 : Result.Name = "ChangeFile";
288 4 : Result.U1 = GetCompressedAnnotation(Next);
289 4 : break;
290 : case BinaryAnnotationsOpCode::ChangeLineEndDelta:
291 : Result.Name = "ChangeLineEndDelta";
292 0 : Result.U1 = GetCompressedAnnotation(Next);
293 0 : break;
294 : case BinaryAnnotationsOpCode::ChangeRangeKind:
295 : Result.Name = "ChangeRangeKind";
296 0 : Result.U1 = GetCompressedAnnotation(Next);
297 0 : break;
298 : case BinaryAnnotationsOpCode::ChangeColumnStart:
299 : Result.Name = "ChangeColumnStart";
300 0 : Result.U1 = GetCompressedAnnotation(Next);
301 0 : break;
302 : case BinaryAnnotationsOpCode::ChangeColumnEnd:
303 : Result.Name = "ChangeColumnEnd";
304 0 : Result.U1 = GetCompressedAnnotation(Next);
305 0 : break;
306 : case BinaryAnnotationsOpCode::ChangeLineOffset:
307 : Result.Name = "ChangeLineOffset";
308 : Result.S1 = DecodeSignedOperand(Next);
309 : break;
310 : case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
311 : Result.Name = "ChangeColumnEndDelta";
312 : Result.S1 = DecodeSignedOperand(Next);
313 : break;
314 : case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
315 : Result.Name = "ChangeCodeOffsetAndLineOffset";
316 36 : uint32_t Annotation = GetCompressedAnnotation(Next);
317 36 : Result.S1 = DecodeSignedOperand(Annotation >> 4);
318 36 : Result.U1 = Annotation & 0xf;
319 36 : break;
320 : }
321 : case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
322 : Result.Name = "ChangeCodeLengthAndCodeOffset";
323 5 : Result.U1 = GetCompressedAnnotation(Next);
324 5 : Result.U2 = GetCompressedAnnotation(Next);
325 5 : break;
326 : }
327 : }
328 : Current = Result;
329 : return true;
330 : }
331 :
332 : Optional<AnnotationData> Current;
333 : ArrayRef<uint8_t> Data;
334 : ArrayRef<uint8_t> Next;
335 : };
336 :
337 : // S_INLINESITE
338 : class InlineSiteSym : public SymbolRecord {
339 : public:
340 32 : explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
341 : InlineSiteSym(uint32_t RecordOffset)
342 : : SymbolRecord(SymbolRecordKind::InlineSiteSym),
343 : RecordOffset(RecordOffset) {}
344 :
345 : iterator_range<BinaryAnnotationIterator> annotations() const {
346 : return make_range(BinaryAnnotationIterator(AnnotationData),
347 : BinaryAnnotationIterator());
348 : }
349 :
350 : uint32_t Parent;
351 : uint32_t End;
352 : TypeIndex Inlinee;
353 : std::vector<uint8_t> AnnotationData;
354 :
355 : uint32_t RecordOffset;
356 : };
357 :
358 : // S_PUB32
359 : class PublicSym32 : public SymbolRecord {
360 : public:
361 : PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {}
362 18 : explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
363 : explicit PublicSym32(uint32_t RecordOffset)
364 442 : : SymbolRecord(SymbolRecordKind::PublicSym32),
365 663 : RecordOffset(RecordOffset) {}
366 :
367 : PublicSymFlags Flags = PublicSymFlags::None;
368 : uint32_t Offset = 0;
369 : uint16_t Segment = 0;
370 : StringRef Name;
371 :
372 : uint32_t RecordOffset = 0;
373 : };
374 :
375 : // S_REGISTER
376 : class RegisterSym : public SymbolRecord {
377 : public:
378 1 : explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
379 : RegisterSym(uint32_t RecordOffset)
380 : : SymbolRecord(SymbolRecordKind::RegisterSym),
381 : RecordOffset(RecordOffset) {}
382 :
383 : TypeIndex Index;
384 : RegisterId Register;
385 : StringRef Name;
386 :
387 : uint32_t RecordOffset;
388 : };
389 :
390 : // S_PROCREF, S_LPROCREF
391 : class ProcRefSym : public SymbolRecord {
392 : public:
393 17 : explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
394 : explicit ProcRefSym(uint32_t RecordOffset)
395 : : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
396 : }
397 :
398 : uint32_t SumName;
399 : uint32_t SymOffset;
400 : uint16_t Module;
401 : StringRef Name;
402 :
403 : uint32_t RecordOffset;
404 : };
405 :
406 : // S_LOCAL
407 : class LocalSym : public SymbolRecord {
408 : public:
409 231 : 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 0 : explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
439 : explicit DefRangeSym(uint32_t RecordOffset)
440 : : SymbolRecord(SymbolRecordKind::DefRangeSym),
441 : RecordOffset(RecordOffset) {}
442 :
443 0 : uint32_t getRelocationOffset() const {
444 0 : 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 0 : explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
460 : DefRangeSubfieldSym(uint32_t RecordOffset)
461 : : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
462 : RecordOffset(RecordOffset) {}
463 :
464 0 : uint32_t getRelocationOffset() const {
465 0 : 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 54 : explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
485 : DefRangeRegisterSym(uint32_t RecordOffset)
486 : : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
487 : RecordOffset(RecordOffset) {}
488 :
489 35 : 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 7 : : SymbolRecord(Kind) {}
509 : DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
510 : : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
511 : RecordOffset(RecordOffset) {}
512 :
513 7 : 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 160 : : SymbolRecord(Kind) {}
529 : DefRangeFramePointerRelSym(uint32_t RecordOffset)
530 : : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
531 : RecordOffset(RecordOffset) {}
532 :
533 0 : uint32_t getRelocationOffset() const {
534 148 : 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 25 : 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 20 : bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
568 12 : uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
569 :
570 4 : 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 8 : : 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 18 : explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
599 : explicit BlockSym(uint32_t RecordOffset)
600 : : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
601 :
602 0 : uint32_t getRelocationOffset() const {
603 10 : 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 1 : explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
622 : explicit LabelSym(uint32_t RecordOffset)
623 : : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
624 :
625 0 : uint32_t getRelocationOffset() const {
626 1 : 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 195 : 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 111 : 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 0 : 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 6 : 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 0 : 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 0 : uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
715 0 : 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 284 : 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 88 : Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
743 : }
744 :
745 0 : SourceLanguage getLanguage() const {
746 0 : return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF);
747 : }
748 0 : CompileSym3Flags getFlags() const {
749 99 : 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 271 : 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 0 : RegisterId getLocalFramePtrReg(CPUType CPU) const {
778 422 : return decodeFramePtrReg(
779 211 : EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);
780 : }
781 :
782 : /// Extract the register this frame uses to refer to parameters.
783 0 : RegisterId getParamFramePtrReg(CPUType CPU) const {
784 422 : return decodeFramePtrReg(
785 211 : 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 0 : explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
799 : explicit CallSiteInfoSym(uint32_t RecordOffset)
800 : : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
801 :
802 0 : uint32_t getRelocationOffset() const {
803 0 : 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 2 : explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
819 : explicit HeapAllocationSiteSym(uint32_t RecordOffset)
820 : : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
821 : RecordOffset(RecordOffset) {}
822 :
823 0 : uint32_t getRelocationOffset() const {
824 0 : 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 0 : explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
841 : explicit FrameCookieSym(uint32_t RecordOffset)
842 : : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
843 :
844 0 : uint32_t getRelocationOffset() const {
845 0 : 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 765 : explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
860 : explicit UDTSym(uint32_t RecordOffset)
861 120 : : 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 155 : 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 9 : 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 47 : 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 0 : class ConstantSym : public SymbolRecord {
915 : public:
916 0 : explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
917 : ConstantSym(uint32_t RecordOffset)
918 0 : : 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 96 : explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
934 : DataSym(uint32_t RecordOffset)
935 : : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
936 :
937 0 : uint32_t getRelocationOffset() const {
938 57 : 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 2 : explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
955 : explicit ThreadLocalDataSym(uint32_t RecordOffset)
956 : : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
957 : RecordOffset(RecordOffset) {}
958 :
959 0 : uint32_t getRelocationOffset() const {
960 1 : 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 9 : 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
|