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