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()361 PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {} PublicSym32(SymbolRecordKind Kind)362 explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {} PublicSym32(uint32_t RecordOffset)363 explicit PublicSym32(uint32_t RecordOffset) 364 : SymbolRecord(SymbolRecordKind::PublicSym32), 365 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: RegisterSym(SymbolRecordKind Kind)378 explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} RegisterSym(uint32_t RecordOffset)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: ProcRefSym(SymbolRecordKind Kind)393 explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ProcRefSym(uint32_t RecordOffset)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 modi()403 uint16_t modi() const { return Module - 1; } 404 uint32_t RecordOffset; 405 }; 406 407 // S_LOCAL 408 class LocalSym : public SymbolRecord { 409 public: LocalSym(SymbolRecordKind Kind)410 explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} LocalSym(uint32_t RecordOffset)411 explicit LocalSym(uint32_t RecordOffset) 412 : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {} 413 414 TypeIndex Type; 415 LocalSymFlags Flags; 416 StringRef Name; 417 418 uint32_t RecordOffset; 419 }; 420 421 struct LocalVariableAddrRange { 422 uint32_t OffsetStart; 423 uint16_t ISectStart; 424 uint16_t Range; 425 }; 426 427 struct LocalVariableAddrGap { 428 uint16_t GapStartOffset; 429 uint16_t Range; 430 }; 431 432 enum : uint16_t { MaxDefRange = 0xf000 }; 433 434 // S_DEFRANGE 435 class DefRangeSym : public SymbolRecord { 436 static constexpr uint32_t RelocationOffset = 8; 437 438 public: DefRangeSym(SymbolRecordKind Kind)439 explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeSym(uint32_t RecordOffset)440 explicit DefRangeSym(uint32_t RecordOffset) 441 : SymbolRecord(SymbolRecordKind::DefRangeSym), 442 RecordOffset(RecordOffset) {} 443 getRelocationOffset()444 uint32_t getRelocationOffset() const { 445 return RecordOffset + RelocationOffset; 446 } 447 448 uint32_t Program; 449 LocalVariableAddrRange Range; 450 std::vector<LocalVariableAddrGap> Gaps; 451 452 uint32_t RecordOffset; 453 }; 454 455 // S_DEFRANGE_SUBFIELD 456 class DefRangeSubfieldSym : public SymbolRecord { 457 static constexpr uint32_t RelocationOffset = 12; 458 459 public: DefRangeSubfieldSym(SymbolRecordKind Kind)460 explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeSubfieldSym(uint32_t RecordOffset)461 DefRangeSubfieldSym(uint32_t RecordOffset) 462 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym), 463 RecordOffset(RecordOffset) {} 464 getRelocationOffset()465 uint32_t getRelocationOffset() const { 466 return RecordOffset + RelocationOffset; 467 } 468 469 uint32_t Program; 470 uint16_t OffsetInParent; 471 LocalVariableAddrRange Range; 472 std::vector<LocalVariableAddrGap> Gaps; 473 474 uint32_t RecordOffset; 475 }; 476 477 // S_DEFRANGE_REGISTER 478 class DefRangeRegisterSym : public SymbolRecord { 479 public: 480 struct Header { 481 ulittle16_t Register; 482 ulittle16_t MayHaveNoName; 483 }; 484 DefRangeRegisterSym(SymbolRecordKind Kind)485 explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeRegisterSym(uint32_t RecordOffset)486 DefRangeRegisterSym(uint32_t RecordOffset) 487 : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), 488 RecordOffset(RecordOffset) {} 489 getRelocationOffset()490 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } 491 492 Header Hdr; 493 LocalVariableAddrRange Range; 494 std::vector<LocalVariableAddrGap> Gaps; 495 496 uint32_t RecordOffset; 497 }; 498 499 // S_DEFRANGE_SUBFIELD_REGISTER 500 class DefRangeSubfieldRegisterSym : public SymbolRecord { 501 public: 502 struct Header { 503 ulittle16_t Register; 504 ulittle16_t MayHaveNoName; 505 ulittle32_t OffsetInParent; 506 }; 507 DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)508 explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind) 509 : SymbolRecord(Kind) {} DefRangeSubfieldRegisterSym(uint32_t RecordOffset)510 DefRangeSubfieldRegisterSym(uint32_t RecordOffset) 511 : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), 512 RecordOffset(RecordOffset) {} 513 getRelocationOffset()514 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } 515 516 Header Hdr; 517 LocalVariableAddrRange Range; 518 std::vector<LocalVariableAddrGap> Gaps; 519 520 uint32_t RecordOffset; 521 }; 522 523 // S_DEFRANGE_FRAMEPOINTER_REL 524 class DefRangeFramePointerRelSym : public SymbolRecord { 525 static constexpr uint32_t RelocationOffset = 8; 526 527 public: DefRangeFramePointerRelSym(SymbolRecordKind Kind)528 explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind) 529 : SymbolRecord(Kind) {} DefRangeFramePointerRelSym(uint32_t RecordOffset)530 DefRangeFramePointerRelSym(uint32_t RecordOffset) 531 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym), 532 RecordOffset(RecordOffset) {} 533 getRelocationOffset()534 uint32_t getRelocationOffset() const { 535 return RecordOffset + RelocationOffset; 536 } 537 538 int32_t Offset; 539 LocalVariableAddrRange Range; 540 std::vector<LocalVariableAddrGap> Gaps; 541 542 uint32_t RecordOffset; 543 }; 544 545 // S_DEFRANGE_REGISTER_REL 546 class DefRangeRegisterRelSym : public SymbolRecord { 547 public: 548 struct Header { 549 ulittle16_t Register; 550 ulittle16_t Flags; 551 little32_t BasePointerOffset; 552 }; 553 DefRangeRegisterRelSym(SymbolRecordKind Kind)554 explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeRegisterRelSym(uint32_t RecordOffset)555 explicit DefRangeRegisterRelSym(uint32_t RecordOffset) 556 : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), 557 RecordOffset(RecordOffset) {} 558 559 // The flags implement this notional bitfield: 560 // uint16_t IsSubfield : 1; 561 // uint16_t Padding : 3; 562 // uint16_t OffsetInParent : 12; 563 enum : uint16_t { 564 IsSubfieldFlag = 1, 565 OffsetInParentShift = 4, 566 }; 567 hasSpilledUDTMember()568 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; } offsetInParent()569 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; } 570 getRelocationOffset()571 uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } 572 573 Header Hdr; 574 LocalVariableAddrRange Range; 575 std::vector<LocalVariableAddrGap> Gaps; 576 577 uint32_t RecordOffset; 578 }; 579 580 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 581 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord { 582 public: DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)583 explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind) 584 : SymbolRecord(Kind) {} DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)585 explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset) 586 : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym), 587 RecordOffset(RecordOffset) {} 588 589 int32_t Offset; 590 591 uint32_t RecordOffset; 592 }; 593 594 // S_BLOCK32 595 class BlockSym : public SymbolRecord { 596 static constexpr uint32_t RelocationOffset = 16; 597 598 public: BlockSym(SymbolRecordKind Kind)599 explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} BlockSym(uint32_t RecordOffset)600 explicit BlockSym(uint32_t RecordOffset) 601 : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {} 602 getRelocationOffset()603 uint32_t getRelocationOffset() const { 604 return RecordOffset + RelocationOffset; 605 } 606 607 uint32_t Parent; 608 uint32_t End; 609 uint32_t CodeSize; 610 uint32_t CodeOffset; 611 uint16_t Segment; 612 StringRef Name; 613 614 uint32_t RecordOffset; 615 }; 616 617 // S_LABEL32 618 class LabelSym : public SymbolRecord { 619 static constexpr uint32_t RelocationOffset = 4; 620 621 public: LabelSym(SymbolRecordKind Kind)622 explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} LabelSym(uint32_t RecordOffset)623 explicit LabelSym(uint32_t RecordOffset) 624 : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {} 625 getRelocationOffset()626 uint32_t getRelocationOffset() const { 627 return RecordOffset + RelocationOffset; 628 } 629 630 uint32_t CodeOffset; 631 uint16_t Segment; 632 ProcSymFlags Flags; 633 StringRef Name; 634 635 uint32_t RecordOffset; 636 }; 637 638 // S_OBJNAME 639 class ObjNameSym : public SymbolRecord { 640 public: ObjNameSym()641 explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {} ObjNameSym(SymbolRecordKind Kind)642 explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ObjNameSym(uint32_t RecordOffset)643 ObjNameSym(uint32_t RecordOffset) 644 : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) { 645 } 646 647 uint32_t Signature; 648 StringRef Name; 649 650 uint32_t RecordOffset; 651 }; 652 653 // S_ENVBLOCK 654 class EnvBlockSym : public SymbolRecord { 655 public: EnvBlockSym(SymbolRecordKind Kind)656 explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} EnvBlockSym(uint32_t RecordOffset)657 EnvBlockSym(uint32_t RecordOffset) 658 : SymbolRecord(SymbolRecordKind::EnvBlockSym), 659 RecordOffset(RecordOffset) {} 660 661 std::vector<StringRef> Fields; 662 663 uint32_t RecordOffset; 664 }; 665 666 // S_EXPORT 667 class ExportSym : public SymbolRecord { 668 public: ExportSym(SymbolRecordKind Kind)669 explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ExportSym(uint32_t RecordOffset)670 ExportSym(uint32_t RecordOffset) 671 : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {} 672 673 uint16_t Ordinal; 674 ExportFlags Flags; 675 StringRef Name; 676 677 uint32_t RecordOffset; 678 }; 679 680 // S_FILESTATIC 681 class FileStaticSym : public SymbolRecord { 682 public: FileStaticSym(SymbolRecordKind Kind)683 explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} FileStaticSym(uint32_t RecordOffset)684 FileStaticSym(uint32_t RecordOffset) 685 : SymbolRecord(SymbolRecordKind::FileStaticSym), 686 RecordOffset(RecordOffset) {} 687 688 TypeIndex Index; 689 uint32_t ModFilenameOffset; 690 LocalSymFlags Flags; 691 StringRef Name; 692 693 uint32_t RecordOffset; 694 }; 695 696 // S_COMPILE2 697 class Compile2Sym : public SymbolRecord { 698 public: Compile2Sym(SymbolRecordKind Kind)699 explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} Compile2Sym(uint32_t RecordOffset)700 Compile2Sym(uint32_t RecordOffset) 701 : SymbolRecord(SymbolRecordKind::Compile2Sym), 702 RecordOffset(RecordOffset) {} 703 704 CompileSym2Flags Flags; 705 CPUType Machine; 706 uint16_t VersionFrontendMajor; 707 uint16_t VersionFrontendMinor; 708 uint16_t VersionFrontendBuild; 709 uint16_t VersionBackendMajor; 710 uint16_t VersionBackendMinor; 711 uint16_t VersionBackendBuild; 712 StringRef Version; 713 std::vector<StringRef> ExtraStrings; 714 getLanguage()715 uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; } getFlags()716 uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; } 717 718 uint32_t RecordOffset; 719 }; 720 721 // S_COMPILE3 722 class Compile3Sym : public SymbolRecord { 723 public: Compile3Sym()724 Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {} Compile3Sym(SymbolRecordKind Kind)725 explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} Compile3Sym(uint32_t RecordOffset)726 Compile3Sym(uint32_t RecordOffset) 727 : SymbolRecord(SymbolRecordKind::Compile3Sym), 728 RecordOffset(RecordOffset) {} 729 730 CompileSym3Flags Flags; 731 CPUType Machine; 732 uint16_t VersionFrontendMajor; 733 uint16_t VersionFrontendMinor; 734 uint16_t VersionFrontendBuild; 735 uint16_t VersionFrontendQFE; 736 uint16_t VersionBackendMajor; 737 uint16_t VersionBackendMinor; 738 uint16_t VersionBackendBuild; 739 uint16_t VersionBackendQFE; 740 StringRef Version; 741 setLanguage(SourceLanguage Lang)742 void setLanguage(SourceLanguage Lang) { 743 Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang)); 744 } 745 getLanguage()746 SourceLanguage getLanguage() const { 747 return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF); 748 } getFlags()749 CompileSym3Flags getFlags() const { 750 return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF); 751 } 752 hasOptimizations()753 bool hasOptimizations() const { 754 return CompileSym3Flags::None != 755 (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG)); 756 } 757 758 uint32_t RecordOffset; 759 }; 760 761 // S_FRAMEPROC 762 class FrameProcSym : public SymbolRecord { 763 public: FrameProcSym(SymbolRecordKind Kind)764 explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} FrameProcSym(uint32_t RecordOffset)765 explicit FrameProcSym(uint32_t RecordOffset) 766 : SymbolRecord(SymbolRecordKind::FrameProcSym), 767 RecordOffset(RecordOffset) {} 768 769 uint32_t TotalFrameBytes; 770 uint32_t PaddingFrameBytes; 771 uint32_t OffsetToPadding; 772 uint32_t BytesOfCalleeSavedRegisters; 773 uint32_t OffsetOfExceptionHandler; 774 uint16_t SectionIdOfExceptionHandler; 775 FrameProcedureOptions Flags; 776 777 /// Extract the register this frame uses to refer to local variables. getLocalFramePtrReg(CPUType CPU)778 RegisterId getLocalFramePtrReg(CPUType CPU) const { 779 return decodeFramePtrReg( 780 EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU); 781 } 782 783 /// Extract the register this frame uses to refer to parameters. getParamFramePtrReg(CPUType CPU)784 RegisterId getParamFramePtrReg(CPUType CPU) const { 785 return decodeFramePtrReg( 786 EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU); 787 } 788 789 uint32_t RecordOffset; 790 791 private: 792 }; 793 794 // S_CALLSITEINFO 795 class CallSiteInfoSym : public SymbolRecord { 796 static constexpr uint32_t RelocationOffset = 4; 797 798 public: CallSiteInfoSym(SymbolRecordKind Kind)799 explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} CallSiteInfoSym(uint32_t RecordOffset)800 explicit CallSiteInfoSym(uint32_t RecordOffset) 801 : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {} 802 getRelocationOffset()803 uint32_t getRelocationOffset() const { 804 return RecordOffset + RelocationOffset; 805 } 806 807 uint32_t CodeOffset; 808 uint16_t Segment; 809 TypeIndex Type; 810 811 uint32_t RecordOffset; 812 }; 813 814 // S_HEAPALLOCSITE 815 class HeapAllocationSiteSym : public SymbolRecord { 816 static constexpr uint32_t RelocationOffset = 4; 817 818 public: HeapAllocationSiteSym(SymbolRecordKind Kind)819 explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} HeapAllocationSiteSym(uint32_t RecordOffset)820 explicit HeapAllocationSiteSym(uint32_t RecordOffset) 821 : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym), 822 RecordOffset(RecordOffset) {} 823 getRelocationOffset()824 uint32_t getRelocationOffset() const { 825 return RecordOffset + RelocationOffset; 826 } 827 828 uint32_t CodeOffset; 829 uint16_t Segment; 830 uint16_t CallInstructionSize; 831 TypeIndex Type; 832 833 uint32_t RecordOffset; 834 }; 835 836 // S_FRAMECOOKIE 837 class FrameCookieSym : public SymbolRecord { 838 static constexpr uint32_t RelocationOffset = 4; 839 840 public: FrameCookieSym(SymbolRecordKind Kind)841 explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} FrameCookieSym(uint32_t RecordOffset)842 explicit FrameCookieSym(uint32_t RecordOffset) 843 : SymbolRecord(SymbolRecordKind::FrameCookieSym) {} 844 getRelocationOffset()845 uint32_t getRelocationOffset() const { 846 return RecordOffset + RelocationOffset; 847 } 848 849 uint32_t CodeOffset; 850 uint16_t Register; 851 FrameCookieKind CookieKind; 852 uint8_t Flags; 853 854 uint32_t RecordOffset; 855 }; 856 857 // S_UDT, S_COBOLUDT 858 class UDTSym : public SymbolRecord { 859 public: UDTSym(SymbolRecordKind Kind)860 explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} UDTSym(uint32_t RecordOffset)861 explicit UDTSym(uint32_t RecordOffset) 862 : SymbolRecord(SymbolRecordKind::UDTSym) {} 863 864 TypeIndex Type; 865 StringRef Name; 866 867 uint32_t RecordOffset; 868 }; 869 870 // S_BUILDINFO 871 class BuildInfoSym : public SymbolRecord { 872 public: BuildInfoSym(SymbolRecordKind Kind)873 explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} BuildInfoSym(uint32_t RecordOffset)874 BuildInfoSym(uint32_t RecordOffset) 875 : SymbolRecord(SymbolRecordKind::BuildInfoSym), 876 RecordOffset(RecordOffset) {} 877 878 TypeIndex BuildId; 879 880 uint32_t RecordOffset; 881 }; 882 883 // S_BPREL32 884 class BPRelativeSym : public SymbolRecord { 885 public: BPRelativeSym(SymbolRecordKind Kind)886 explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} BPRelativeSym(uint32_t RecordOffset)887 explicit BPRelativeSym(uint32_t RecordOffset) 888 : SymbolRecord(SymbolRecordKind::BPRelativeSym), 889 RecordOffset(RecordOffset) {} 890 891 int32_t Offset; 892 TypeIndex Type; 893 StringRef Name; 894 895 uint32_t RecordOffset; 896 }; 897 898 // S_REGREL32 899 class RegRelativeSym : public SymbolRecord { 900 public: RegRelativeSym(SymbolRecordKind Kind)901 explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} RegRelativeSym(uint32_t RecordOffset)902 explicit RegRelativeSym(uint32_t RecordOffset) 903 : SymbolRecord(SymbolRecordKind::RegRelativeSym), 904 RecordOffset(RecordOffset) {} 905 906 uint32_t Offset; 907 TypeIndex Type; 908 RegisterId Register; 909 StringRef Name; 910 911 uint32_t RecordOffset; 912 }; 913 914 // S_CONSTANT, S_MANCONSTANT 915 class ConstantSym : public SymbolRecord { 916 public: ConstantSym(SymbolRecordKind Kind)917 explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ConstantSym(uint32_t RecordOffset)918 ConstantSym(uint32_t RecordOffset) 919 : SymbolRecord(SymbolRecordKind::ConstantSym), 920 RecordOffset(RecordOffset) {} 921 922 TypeIndex Type; 923 APSInt Value; 924 StringRef Name; 925 926 uint32_t RecordOffset; 927 }; 928 929 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA 930 class DataSym : public SymbolRecord { 931 static constexpr uint32_t RelocationOffset = 8; 932 933 public: DataSym(SymbolRecordKind Kind)934 explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DataSym(uint32_t RecordOffset)935 DataSym(uint32_t RecordOffset) 936 : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {} 937 getRelocationOffset()938 uint32_t getRelocationOffset() const { 939 return RecordOffset + RelocationOffset; 940 } 941 942 TypeIndex Type; 943 uint32_t DataOffset; 944 uint16_t Segment; 945 StringRef Name; 946 947 uint32_t RecordOffset; 948 }; 949 950 // S_LTHREAD32, S_GTHREAD32 951 class ThreadLocalDataSym : public SymbolRecord { 952 static constexpr uint32_t RelocationOffset = 8; 953 954 public: ThreadLocalDataSym(SymbolRecordKind Kind)955 explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ThreadLocalDataSym(uint32_t RecordOffset)956 explicit ThreadLocalDataSym(uint32_t RecordOffset) 957 : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym), 958 RecordOffset(RecordOffset) {} 959 getRelocationOffset()960 uint32_t getRelocationOffset() const { 961 return RecordOffset + RelocationOffset; 962 } 963 964 TypeIndex Type; 965 uint32_t DataOffset; 966 uint16_t Segment; 967 StringRef Name; 968 969 uint32_t RecordOffset; 970 }; 971 972 // S_UNAMESPACE 973 class UsingNamespaceSym : public SymbolRecord { 974 public: UsingNamespaceSym(SymbolRecordKind Kind)975 explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} UsingNamespaceSym(uint32_t RecordOffset)976 explicit UsingNamespaceSym(uint32_t RecordOffset) 977 : SymbolRecord(SymbolRecordKind::RegRelativeSym), 978 RecordOffset(RecordOffset) {} 979 980 StringRef Name; 981 982 uint32_t RecordOffset; 983 }; 984 985 // S_ANNOTATION 986 987 using CVSymbol = CVRecord<SymbolKind>; 988 using CVSymbolArray = VarStreamArray<CVSymbol>; 989 990 Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream, 991 uint32_t Offset); 992 993 } // end namespace codeview 994 } // end namespace llvm 995 996 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H 997