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