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