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