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 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) { 492 DataSym data(SymbolRecordKind::DataSym); 493 cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data)); 494 result.type = data.Type; 495 result.name = data.Name; 496 return result; 497 } 498 499 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) { 500 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym); 501 cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data)); 502 result.type = data.Type; 503 result.name = data.Name; 504 return result; 505 } 506 507 if (sym.kind() == S_CONSTANT) { 508 ConstantSym constant(SymbolRecordKind::ConstantSym); 509 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant)); 510 result.type = constant.Type; 511 result.name = constant.Name; 512 return result; 513 } 514 515 lldbassert(false && "Invalid variable record kind!"); 516 return {}; 517 } 518 519 VariableInfo lldb_private::npdb::GetVariableLocationInfo( 520 PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) { 521 522 CVSymbol sym = index.ReadSymbolRecord(var_id); 523 524 VariableInfo result = GetVariableNameInfo(sym); 525 526 if (sym.kind() == S_REGREL32) { 527 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); 528 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); 529 result.location = 530 MakeRegRelLocationExpression(reg.Register, reg.Offset, module); 531 result.ranges.emplace(); 532 return result; 533 } 534 535 if (sym.kind() == S_REGISTER) { 536 RegisterSym reg(SymbolRecordKind::RegisterSym); 537 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); 538 result.location = MakeEnregisteredLocationExpression(reg.Register, module); 539 result.ranges.emplace(); 540 return result; 541 } 542 543 if (sym.kind() == S_LOCAL) { 544 LocalSym local(SymbolRecordKind::LocalSym); 545 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); 546 547 PdbCompilandSymId loc_specifier_id(var_id.modi, 548 var_id.offset + sym.RecordData.size()); 549 CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); 550 if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) { 551 DefRangeFramePointerRelSym loc( 552 SymbolRecordKind::DefRangeFramePointerRelSym); 553 cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( 554 loc_specifier_cvs, loc)); 555 // FIXME: The register needs to come from the S_FRAMEPROC symbol. 556 result.location = 557 MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module); 558 result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); 559 } else { 560 // FIXME: Handle other kinds 561 llvm::APSInt value; 562 value = 42; 563 result.location = MakeConstantLocationExpression( 564 TypeIndex::Int32(), index.tpi(), value, module); 565 } 566 return result; 567 } 568 llvm_unreachable("Symbol is not a local variable!"); 569 return result; 570 } 571 572 lldb::BasicType 573 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { 574 switch (kind) { 575 case SimpleTypeKind::Boolean128: 576 case SimpleTypeKind::Boolean16: 577 case SimpleTypeKind::Boolean32: 578 case SimpleTypeKind::Boolean64: 579 case SimpleTypeKind::Boolean8: 580 return lldb::eBasicTypeBool; 581 case SimpleTypeKind::Byte: 582 case SimpleTypeKind::UnsignedCharacter: 583 return lldb::eBasicTypeUnsignedChar; 584 case SimpleTypeKind::NarrowCharacter: 585 return lldb::eBasicTypeChar; 586 case SimpleTypeKind::SignedCharacter: 587 case SimpleTypeKind::SByte: 588 return lldb::eBasicTypeSignedChar; 589 case SimpleTypeKind::Character16: 590 return lldb::eBasicTypeChar16; 591 case SimpleTypeKind::Character32: 592 return lldb::eBasicTypeChar32; 593 case SimpleTypeKind::Complex80: 594 return lldb::eBasicTypeLongDoubleComplex; 595 case SimpleTypeKind::Complex64: 596 return lldb::eBasicTypeDoubleComplex; 597 case SimpleTypeKind::Complex32: 598 return lldb::eBasicTypeFloatComplex; 599 case SimpleTypeKind::Float128: 600 case SimpleTypeKind::Float80: 601 return lldb::eBasicTypeLongDouble; 602 case SimpleTypeKind::Float64: 603 return lldb::eBasicTypeDouble; 604 case SimpleTypeKind::Float32: 605 return lldb::eBasicTypeFloat; 606 case SimpleTypeKind::Float16: 607 return lldb::eBasicTypeHalf; 608 case SimpleTypeKind::Int128: 609 return lldb::eBasicTypeInt128; 610 case SimpleTypeKind::Int64: 611 case SimpleTypeKind::Int64Quad: 612 return lldb::eBasicTypeLongLong; 613 case SimpleTypeKind::Int32: 614 return lldb::eBasicTypeInt; 615 case SimpleTypeKind::Int16: 616 case SimpleTypeKind::Int16Short: 617 return lldb::eBasicTypeShort; 618 case SimpleTypeKind::UInt128: 619 return lldb::eBasicTypeUnsignedInt128; 620 case SimpleTypeKind::UInt64: 621 case SimpleTypeKind::UInt64Quad: 622 return lldb::eBasicTypeUnsignedLongLong; 623 case SimpleTypeKind::HResult: 624 case SimpleTypeKind::UInt32: 625 return lldb::eBasicTypeUnsignedInt; 626 case SimpleTypeKind::UInt16: 627 case SimpleTypeKind::UInt16Short: 628 return lldb::eBasicTypeUnsignedShort; 629 case SimpleTypeKind::Int32Long: 630 return lldb::eBasicTypeLong; 631 case SimpleTypeKind::UInt32Long: 632 return lldb::eBasicTypeUnsignedLong; 633 case SimpleTypeKind::Void: 634 return lldb::eBasicTypeVoid; 635 case SimpleTypeKind::WideCharacter: 636 return lldb::eBasicTypeWChar; 637 default: 638 return lldb::eBasicTypeInvalid; 639 } 640 } 641 642 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { 643 switch (kind) { 644 case SimpleTypeKind::Boolean128: 645 case SimpleTypeKind::Int128: 646 case SimpleTypeKind::UInt128: 647 case SimpleTypeKind::Float128: 648 return 16; 649 case SimpleTypeKind::Complex80: 650 case SimpleTypeKind::Float80: 651 return 10; 652 case SimpleTypeKind::Boolean64: 653 case SimpleTypeKind::Complex64: 654 case SimpleTypeKind::UInt64: 655 case SimpleTypeKind::UInt64Quad: 656 case SimpleTypeKind::Float64: 657 case SimpleTypeKind::Int64: 658 case SimpleTypeKind::Int64Quad: 659 return 8; 660 case SimpleTypeKind::Boolean32: 661 case SimpleTypeKind::Character32: 662 case SimpleTypeKind::Complex32: 663 case SimpleTypeKind::Float32: 664 case SimpleTypeKind::Int32: 665 case SimpleTypeKind::Int32Long: 666 case SimpleTypeKind::UInt32Long: 667 case SimpleTypeKind::HResult: 668 case SimpleTypeKind::UInt32: 669 return 4; 670 case SimpleTypeKind::Boolean16: 671 case SimpleTypeKind::Character16: 672 case SimpleTypeKind::Float16: 673 case SimpleTypeKind::Int16: 674 case SimpleTypeKind::Int16Short: 675 case SimpleTypeKind::UInt16: 676 case SimpleTypeKind::UInt16Short: 677 case SimpleTypeKind::WideCharacter: 678 return 2; 679 case SimpleTypeKind::Boolean8: 680 case SimpleTypeKind::Byte: 681 case SimpleTypeKind::UnsignedCharacter: 682 case SimpleTypeKind::NarrowCharacter: 683 case SimpleTypeKind::SignedCharacter: 684 case SimpleTypeKind::SByte: 685 return 1; 686 case SimpleTypeKind::Void: 687 default: 688 return 0; 689 } 690 } 691 692 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id, 693 TpiStream &tpi) { 694 if (id.index.isSimple()) 695 return id; 696 697 CVType cvt = tpi.getType(id.index); 698 699 // Only tag records have a best and a worst record. 700 if (!IsTagRecord(cvt)) 701 return id; 702 703 // Tag records that are not forward decls are full decls, hence they are the 704 // best. 705 if (!IsForwardRefUdt(cvt)) 706 return id; 707 708 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index)); 709 } 710 711 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) { 712 RecordType record; 713 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record)); 714 return record.getSize(); 715 } 716 717 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id, 718 llvm::pdb::TpiStream &tpi) { 719 if (id.index.isSimple()) { 720 switch (id.index.getSimpleMode()) { 721 case SimpleTypeMode::Direct: 722 return GetTypeSizeForSimpleKind(id.index.getSimpleKind()); 723 case SimpleTypeMode::NearPointer32: 724 case SimpleTypeMode::FarPointer32: 725 return 4; 726 case SimpleTypeMode::NearPointer64: 727 return 8; 728 case SimpleTypeMode::NearPointer128: 729 return 16; 730 default: 731 break; 732 } 733 return 0; 734 } 735 736 TypeIndex index = id.index; 737 if (IsForwardRefUdt(index, tpi)) 738 index = llvm::cantFail(tpi.findFullDeclForForwardRef(index)); 739 740 CVType cvt = tpi.getType(index); 741 switch (cvt.kind()) { 742 case LF_MODIFIER: 743 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi); 744 case LF_ENUM: { 745 EnumRecord record; 746 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record)); 747 return GetSizeOfType({record.UnderlyingType}, tpi); 748 } 749 case LF_POINTER: 750 return GetSizeOfTypeInternal<PointerRecord>(cvt); 751 case LF_ARRAY: 752 return GetSizeOfTypeInternal<ArrayRecord>(cvt); 753 case LF_CLASS: 754 case LF_STRUCTURE: 755 case LF_INTERFACE: 756 return GetSizeOfTypeInternal<ClassRecord>(cvt); 757 case LF_UNION: 758 return GetSizeOfTypeInternal<UnionRecord>(cvt); 759 default: 760 break; 761 } 762 return 0; 763 } 764