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