1 //===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "PdbUtil.h" 11 12 #include "DWARFLocationExpression.h" 13 #include "PdbIndex.h" 14 #include "PdbSymUid.h" 15 16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 18 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 19 20 #include "lldb/Utility/LLDBAssert.h" 21 22 #include "lldb/lldb-enumerations.h" 23 24 using namespace lldb_private; 25 using namespace lldb_private::npdb; 26 using namespace llvm::codeview; 27 using namespace llvm::pdb; 28 29 static Variable::RangeList 30 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, 31 llvm::ArrayRef<LocalVariableAddrGap> gaps) { 32 lldb::addr_t start = 33 index.MakeVirtualAddress(range.ISectStart, range.OffsetStart); 34 lldb::addr_t end = start + range.Range; 35 36 Variable::RangeList result; 37 while (!gaps.empty()) { 38 const LocalVariableAddrGap &gap = gaps.front(); 39 40 lldb::addr_t size = gap.GapStartOffset - start; 41 result.Append(start, size); 42 start += gap.Range; 43 gaps = gaps.drop_front(); 44 } 45 46 result.Append(start, end); 47 return result; 48 } 49 50 CVTagRecord CVTagRecord::create(CVType type) { 51 assert(IsTagRecord(type) && "type is not a tag record!"); 52 switch (type.kind()) { 53 case LF_CLASS: 54 case LF_STRUCTURE: 55 case LF_INTERFACE: { 56 ClassRecord cr; 57 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr)); 58 return CVTagRecord(std::move(cr)); 59 } 60 case LF_UNION: { 61 UnionRecord ur; 62 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur)); 63 return CVTagRecord(std::move(ur)); 64 } 65 case LF_ENUM: { 66 EnumRecord er; 67 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er)); 68 return CVTagRecord(std::move(er)); 69 } 70 default: 71 llvm_unreachable("Unreachable!"); 72 } 73 } 74 75 CVTagRecord::CVTagRecord(ClassRecord &&c) 76 : cvclass(std::move(c)), 77 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {} 78 CVTagRecord::CVTagRecord(UnionRecord &&u) 79 : cvunion(std::move(u)), m_kind(Union) {} 80 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {} 81 82 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) { 83 switch (kind) { 84 case S_COMPILE3: 85 case S_OBJNAME: 86 return PDB_SymType::CompilandDetails; 87 case S_ENVBLOCK: 88 return PDB_SymType::CompilandEnv; 89 case S_THUNK32: 90 case S_TRAMPOLINE: 91 return PDB_SymType::Thunk; 92 case S_COFFGROUP: 93 return PDB_SymType::CoffGroup; 94 case S_EXPORT: 95 return PDB_SymType::Export; 96 case S_LPROC32: 97 case S_GPROC32: 98 case S_LPROC32_DPC: 99 return PDB_SymType::Function; 100 case S_PUB32: 101 return PDB_SymType::PublicSymbol; 102 case S_INLINESITE: 103 return PDB_SymType::InlineSite; 104 case S_LOCAL: 105 case S_BPREL32: 106 case S_REGREL32: 107 case S_MANCONSTANT: 108 case S_CONSTANT: 109 case S_LDATA32: 110 case S_GDATA32: 111 case S_LMANDATA: 112 case S_GMANDATA: 113 case S_LTHREAD32: 114 case S_GTHREAD32: 115 return PDB_SymType::Data; 116 case S_BLOCK32: 117 return PDB_SymType::Block; 118 case S_LABEL32: 119 return PDB_SymType::Label; 120 case S_CALLSITEINFO: 121 return PDB_SymType::CallSite; 122 case S_HEAPALLOCSITE: 123 return PDB_SymType::HeapAllocationSite; 124 case S_CALLEES: 125 return PDB_SymType::Callee; 126 case S_CALLERS: 127 return PDB_SymType::Caller; 128 default: 129 lldbassert(false && "Invalid symbol record kind!"); 130 } 131 return PDB_SymType::None; 132 } 133 134 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) { 135 switch (kind) { 136 case LF_ARRAY: 137 return PDB_SymType::ArrayType; 138 case LF_ARGLIST: 139 return PDB_SymType::FunctionSig; 140 case LF_BCLASS: 141 return PDB_SymType::BaseClass; 142 case LF_BINTERFACE: 143 return PDB_SymType::BaseInterface; 144 case LF_CLASS: 145 case LF_STRUCTURE: 146 case LF_INTERFACE: 147 case LF_UNION: 148 return PDB_SymType::UDT; 149 case LF_POINTER: 150 return PDB_SymType::PointerType; 151 case LF_ENUM: 152 return PDB_SymType::Enum; 153 case LF_PROCEDURE: 154 return PDB_SymType::FunctionSig; 155 case LF_BITFIELD: 156 return PDB_SymType::BuiltinType; 157 default: 158 lldbassert(false && "Invalid type record kind!"); 159 } 160 return PDB_SymType::None; 161 } 162 163 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) { 164 switch (sym.kind()) { 165 case S_GPROC32: 166 case S_LPROC32: 167 case S_GPROC32_ID: 168 case S_LPROC32_ID: 169 case S_LPROC32_DPC: 170 case S_LPROC32_DPC_ID: 171 case S_THUNK32: 172 case S_TRAMPOLINE: 173 case S_COFFGROUP: 174 case S_BLOCK32: 175 case S_LABEL32: 176 case S_CALLSITEINFO: 177 case S_HEAPALLOCSITE: 178 case S_LDATA32: 179 case S_GDATA32: 180 case S_LMANDATA: 181 case S_GMANDATA: 182 case S_LTHREAD32: 183 case S_GTHREAD32: 184 return true; 185 default: 186 return false; 187 } 188 } 189 190 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) { 191 switch (sym.kind()) { 192 case S_GPROC32: 193 case S_LPROC32: 194 case S_GPROC32_ID: 195 case S_LPROC32_ID: 196 case S_LPROC32_DPC: 197 case S_LPROC32_DPC_ID: 198 case S_THUNK32: 199 case S_TRAMPOLINE: 200 case S_COFFGROUP: 201 case S_BLOCK32: 202 return true; 203 default: 204 return false; 205 } 206 } 207 208 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) { 209 RecordT record(static_cast<SymbolRecordKind>(sym.kind())); 210 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); 211 return record; 212 } 213 214 template <typename RecordT> 215 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { 216 RecordT record = createRecord<RecordT>(sym); 217 return {record.Segment, record.CodeOffset}; 218 } 219 220 template <> 221 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) { 222 TrampolineSym record = createRecord<TrampolineSym>(sym); 223 return {record.ThunkSection, record.ThunkOffset}; 224 } 225 226 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) { 227 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 228 return {record.Segment, record.Offset}; 229 } 230 231 template <> 232 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) { 233 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 234 return {record.Segment, record.Offset}; 235 } 236 237 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) { 238 DataSym record = createRecord<DataSym>(sym); 239 return {record.Segment, record.DataOffset}; 240 } 241 242 template <> 243 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) { 244 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym); 245 return {record.Segment, record.DataOffset}; 246 } 247 248 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) { 249 switch (sym.kind()) { 250 case S_GPROC32: 251 case S_LPROC32: 252 case S_GPROC32_ID: 253 case S_LPROC32_ID: 254 case S_LPROC32_DPC: 255 case S_LPROC32_DPC_ID: 256 return ::GetSegmentAndOffset<ProcSym>(sym); 257 case S_THUNK32: 258 return ::GetSegmentAndOffset<Thunk32Sym>(sym); 259 break; 260 case S_TRAMPOLINE: 261 return ::GetSegmentAndOffset<TrampolineSym>(sym); 262 break; 263 case S_COFFGROUP: 264 return ::GetSegmentAndOffset<CoffGroupSym>(sym); 265 break; 266 case S_BLOCK32: 267 return ::GetSegmentAndOffset<BlockSym>(sym); 268 break; 269 case S_LABEL32: 270 return ::GetSegmentAndOffset<LabelSym>(sym); 271 break; 272 case S_CALLSITEINFO: 273 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym); 274 break; 275 case S_HEAPALLOCSITE: 276 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym); 277 break; 278 case S_LDATA32: 279 case S_GDATA32: 280 case S_LMANDATA: 281 case S_GMANDATA: 282 return ::GetSegmentAndOffset<DataSym>(sym); 283 break; 284 case S_LTHREAD32: 285 case S_GTHREAD32: 286 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym); 287 break; 288 default: 289 lldbassert(false && "Record does not have a segment/offset!"); 290 } 291 return {0, 0}; 292 } 293 294 template <typename RecordT> 295 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { 296 RecordT record = createRecord<RecordT>(sym); 297 return {record.Segment, record.CodeOffset, record.CodeSize}; 298 } 299 300 template <> 301 SegmentOffsetLength 302 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) { 303 TrampolineSym record = createRecord<TrampolineSym>(sym); 304 return {record.ThunkSection, record.ThunkOffset, record.Size}; 305 } 306 307 template <> 308 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) { 309 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 310 return SegmentOffsetLength{record.Segment, record.Offset, record.Length}; 311 } 312 313 template <> 314 SegmentOffsetLength 315 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) { 316 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 317 return SegmentOffsetLength{record.Segment, record.Offset, record.Size}; 318 } 319 320 SegmentOffsetLength 321 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) { 322 switch (sym.kind()) { 323 case S_GPROC32: 324 case S_LPROC32: 325 case S_GPROC32_ID: 326 case S_LPROC32_ID: 327 case S_LPROC32_DPC: 328 case S_LPROC32_DPC_ID: 329 return ::GetSegmentOffsetAndLength<ProcSym>(sym); 330 case S_THUNK32: 331 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym); 332 break; 333 case S_TRAMPOLINE: 334 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym); 335 break; 336 case S_COFFGROUP: 337 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym); 338 break; 339 case S_BLOCK32: 340 return ::GetSegmentOffsetAndLength<BlockSym>(sym); 341 break; 342 default: 343 lldbassert(false && "Record does not have a segment/offset/length triple!"); 344 } 345 return {0, 0, 0}; 346 } 347 348 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) { 349 ClassRecord cr; 350 UnionRecord ur; 351 EnumRecord er; 352 switch (cvt.kind()) { 353 case LF_CLASS: 354 case LF_STRUCTURE: 355 case LF_INTERFACE: 356 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 357 return cr.isForwardRef(); 358 case LF_UNION: 359 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 360 return ur.isForwardRef(); 361 case LF_ENUM: 362 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 363 return er.isForwardRef(); 364 default: 365 return false; 366 } 367 } 368 369 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) { 370 switch (cvt.kind()) { 371 case LF_CLASS: 372 case LF_STRUCTURE: 373 case LF_UNION: 374 case LF_ENUM: 375 return true; 376 default: 377 return false; 378 } 379 } 380 381 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) { 382 switch (cvt.kind()) { 383 case LF_CLASS: 384 case LF_STRUCTURE: 385 case LF_UNION: 386 return true; 387 default: 388 return false; 389 } 390 } 391 392 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id, 393 TpiStream &tpi) { 394 if (id.is_ipi || id.index.isSimple()) 395 return false; 396 return IsForwardRefUdt(tpi.getType(id.index)); 397 } 398 399 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) { 400 if (id.is_ipi || id.index.isSimple()) 401 return false; 402 return IsTagRecord(tpi.getType(id.index)); 403 } 404 405 lldb::AccessType 406 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) { 407 switch (access) { 408 case MemberAccess::Private: 409 return lldb::eAccessPrivate; 410 case MemberAccess::Protected: 411 return lldb::eAccessProtected; 412 case MemberAccess::Public: 413 return lldb::eAccessPublic; 414 case MemberAccess::None: 415 return lldb::eAccessNone; 416 } 417 llvm_unreachable("unreachable"); 418 } 419 420 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) { 421 switch (cvt.kind()) { 422 case LF_CLASS: 423 case LF_STRUCTURE: 424 case LF_INTERFACE: { 425 ClassRecord cr; 426 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 427 return cr.FieldList; 428 } 429 case LF_UNION: { 430 UnionRecord ur; 431 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 432 return ur.FieldList; 433 } 434 case LF_ENUM: { 435 EnumRecord er; 436 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 437 return er.FieldList; 438 } 439 default: 440 llvm_unreachable("Unreachable!"); 441 } 442 } 443 444 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) { 445 lldbassert(modifier.kind() == LF_MODIFIER); 446 ModifierRecord mr; 447 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr)); 448 return mr.ModifiedType; 449 } 450 451 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) { 452 // Not all PDB names can be parsed with CPlusPlusNameParser. 453 // E.g. it fails on names containing `anonymous namespace'. 454 // So we simply drop everything before '::' 455 456 auto offset = name.rfind("::"); 457 if (offset == llvm::StringRef::npos) 458 return name; 459 assert(offset + 2 <= name.size()); 460 461 return name.substr(offset + 2); 462 } 463 464 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) { 465 VariableInfo result; 466 467 if (sym.kind() == S_REGREL32) { 468 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); 469 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); 470 result.type = reg.Type; 471 result.name = reg.Name; 472 return result; 473 } 474 475 if (sym.kind() == S_REGISTER) { 476 RegisterSym reg(SymbolRecordKind::RegisterSym); 477 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); 478 result.type = reg.Index; 479 result.name = reg.Name; 480 return result; 481 } 482 483 if (sym.kind() == S_LOCAL) { 484 LocalSym local(SymbolRecordKind::LocalSym); 485 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); 486 result.type = local.Type; 487 result.name = local.Name; 488 return result; 489 } 490 491 lldbassert(false && "Invalid variable record kind!"); 492 return {}; 493 } 494 495 VariableInfo lldb_private::npdb::GetVariableLocationInfo( 496 PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) { 497 498 CVSymbol sym = index.ReadSymbolRecord(var_id); 499 500 VariableInfo result = GetVariableNameInfo(sym); 501 502 if (sym.kind() == S_REGREL32) { 503 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); 504 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); 505 result.location = 506 MakeRegRelLocationExpression(reg.Register, reg.Offset, module); 507 result.ranges.emplace(); 508 return result; 509 } 510 511 if (sym.kind() == S_REGISTER) { 512 RegisterSym reg(SymbolRecordKind::RegisterSym); 513 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); 514 result.location = MakeEnregisteredLocationExpression(reg.Register, module); 515 result.ranges.emplace(); 516 return result; 517 } 518 519 if (sym.kind() == S_LOCAL) { 520 LocalSym local(SymbolRecordKind::LocalSym); 521 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); 522 523 PdbCompilandSymId loc_specifier_id(var_id.modi, 524 var_id.offset + sym.RecordData.size()); 525 CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); 526 if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) { 527 DefRangeFramePointerRelSym loc( 528 SymbolRecordKind::DefRangeFramePointerRelSym); 529 cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( 530 loc_specifier_cvs, loc)); 531 // FIXME: The register needs to come from the S_FRAMEPROC symbol. 532 result.location = 533 MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module); 534 result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); 535 } else { 536 // FIXME: Handle other kinds 537 llvm::APSInt value; 538 value = 42; 539 result.location = MakeConstantLocationExpression( 540 TypeIndex::Int32(), index.tpi(), value, module); 541 } 542 return result; 543 } 544 llvm_unreachable("Symbol is not a local variable!"); 545 return result; 546 } 547 548 lldb::BasicType 549 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { 550 switch (kind) { 551 case SimpleTypeKind::Boolean128: 552 case SimpleTypeKind::Boolean16: 553 case SimpleTypeKind::Boolean32: 554 case SimpleTypeKind::Boolean64: 555 case SimpleTypeKind::Boolean8: 556 return lldb::eBasicTypeBool; 557 case SimpleTypeKind::Byte: 558 case SimpleTypeKind::UnsignedCharacter: 559 return lldb::eBasicTypeUnsignedChar; 560 case SimpleTypeKind::NarrowCharacter: 561 return lldb::eBasicTypeChar; 562 case SimpleTypeKind::SignedCharacter: 563 case SimpleTypeKind::SByte: 564 return lldb::eBasicTypeSignedChar; 565 case SimpleTypeKind::Character16: 566 return lldb::eBasicTypeChar16; 567 case SimpleTypeKind::Character32: 568 return lldb::eBasicTypeChar32; 569 case SimpleTypeKind::Complex80: 570 return lldb::eBasicTypeLongDoubleComplex; 571 case SimpleTypeKind::Complex64: 572 return lldb::eBasicTypeDoubleComplex; 573 case SimpleTypeKind::Complex32: 574 return lldb::eBasicTypeFloatComplex; 575 case SimpleTypeKind::Float128: 576 case SimpleTypeKind::Float80: 577 return lldb::eBasicTypeLongDouble; 578 case SimpleTypeKind::Float64: 579 return lldb::eBasicTypeDouble; 580 case SimpleTypeKind::Float32: 581 return lldb::eBasicTypeFloat; 582 case SimpleTypeKind::Float16: 583 return lldb::eBasicTypeHalf; 584 case SimpleTypeKind::Int128: 585 return lldb::eBasicTypeInt128; 586 case SimpleTypeKind::Int64: 587 case SimpleTypeKind::Int64Quad: 588 return lldb::eBasicTypeLongLong; 589 case SimpleTypeKind::Int32: 590 return lldb::eBasicTypeInt; 591 case SimpleTypeKind::Int16: 592 case SimpleTypeKind::Int16Short: 593 return lldb::eBasicTypeShort; 594 case SimpleTypeKind::UInt128: 595 return lldb::eBasicTypeUnsignedInt128; 596 case SimpleTypeKind::UInt64: 597 case SimpleTypeKind::UInt64Quad: 598 return lldb::eBasicTypeUnsignedLongLong; 599 case SimpleTypeKind::HResult: 600 case SimpleTypeKind::UInt32: 601 return lldb::eBasicTypeUnsignedInt; 602 case SimpleTypeKind::UInt16: 603 case SimpleTypeKind::UInt16Short: 604 return lldb::eBasicTypeUnsignedShort; 605 case SimpleTypeKind::Int32Long: 606 return lldb::eBasicTypeLong; 607 case SimpleTypeKind::UInt32Long: 608 return lldb::eBasicTypeUnsignedLong; 609 case SimpleTypeKind::Void: 610 return lldb::eBasicTypeVoid; 611 case SimpleTypeKind::WideCharacter: 612 return lldb::eBasicTypeWChar; 613 default: 614 return lldb::eBasicTypeInvalid; 615 } 616 } 617 618 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { 619 switch (kind) { 620 case SimpleTypeKind::Boolean128: 621 case SimpleTypeKind::Int128: 622 case SimpleTypeKind::UInt128: 623 case SimpleTypeKind::Float128: 624 return 16; 625 case SimpleTypeKind::Complex80: 626 case SimpleTypeKind::Float80: 627 return 10; 628 case SimpleTypeKind::Boolean64: 629 case SimpleTypeKind::Complex64: 630 case SimpleTypeKind::UInt64: 631 case SimpleTypeKind::UInt64Quad: 632 case SimpleTypeKind::Float64: 633 case SimpleTypeKind::Int64: 634 case SimpleTypeKind::Int64Quad: 635 return 8; 636 case SimpleTypeKind::Boolean32: 637 case SimpleTypeKind::Character32: 638 case SimpleTypeKind::Complex32: 639 case SimpleTypeKind::Float32: 640 case SimpleTypeKind::Int32: 641 case SimpleTypeKind::Int32Long: 642 case SimpleTypeKind::UInt32Long: 643 case SimpleTypeKind::HResult: 644 case SimpleTypeKind::UInt32: 645 return 4; 646 case SimpleTypeKind::Boolean16: 647 case SimpleTypeKind::Character16: 648 case SimpleTypeKind::Float16: 649 case SimpleTypeKind::Int16: 650 case SimpleTypeKind::Int16Short: 651 case SimpleTypeKind::UInt16: 652 case SimpleTypeKind::UInt16Short: 653 case SimpleTypeKind::WideCharacter: 654 return 2; 655 case SimpleTypeKind::Boolean8: 656 case SimpleTypeKind::Byte: 657 case SimpleTypeKind::UnsignedCharacter: 658 case SimpleTypeKind::NarrowCharacter: 659 case SimpleTypeKind::SignedCharacter: 660 case SimpleTypeKind::SByte: 661 return 1; 662 case SimpleTypeKind::Void: 663 default: 664 return 0; 665 } 666 } 667 668 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id, 669 TpiStream &tpi) { 670 if (id.index.isSimple()) 671 return id; 672 673 CVType cvt = tpi.getType(id.index); 674 675 // Only tag records have a best and a worst record. 676 if (!IsTagRecord(cvt)) 677 return id; 678 679 // Tag records that are not forward decls are full decls, hence they are the 680 // best. 681 if (!IsForwardRefUdt(cvt)) 682 return id; 683 684 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index)); 685 } 686 687 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) { 688 RecordType record; 689 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record)); 690 return record.getSize(); 691 } 692 693 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id, 694 llvm::pdb::TpiStream &tpi) { 695 if (id.index.isSimple()) { 696 switch (id.index.getSimpleMode()) { 697 case SimpleTypeMode::Direct: 698 return GetTypeSizeForSimpleKind(id.index.getSimpleKind()); 699 case SimpleTypeMode::NearPointer32: 700 case SimpleTypeMode::FarPointer32: 701 return 4; 702 case SimpleTypeMode::NearPointer64: 703 return 8; 704 case SimpleTypeMode::NearPointer128: 705 return 16; 706 default: 707 break; 708 } 709 return 0; 710 } 711 712 CVType cvt = tpi.getType(id.index); 713 switch (cvt.kind()) { 714 case LF_MODIFIER: 715 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi); 716 case LF_ENUM: { 717 EnumRecord record; 718 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record)); 719 return GetSizeOfType({record.UnderlyingType}, tpi); 720 } 721 case LF_POINTER: 722 return GetSizeOfTypeInternal<PointerRecord>(cvt); 723 case LF_ARRAY: 724 return GetSizeOfTypeInternal<ArrayRecord>(cvt); 725 case LF_CLASS: 726 case LF_STRUCTURE: 727 case LF_INTERFACE: 728 return GetSizeOfTypeInternal<ClassRecord>(cvt); 729 case LF_UNION: 730 return GetSizeOfTypeInternal<UnionRecord>(cvt); 731 default: 732 break; 733 } 734 return 0; 735 } 736