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