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