1 //===-- PdbUtil.cpp -------------------------------------------------------===// 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/CVTypeVisitor.h" 16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 18 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 19 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 20 21 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" 22 #include "lldb/Symbol/Block.h" 23 #include "lldb/Utility/LLDBAssert.h" 24 #include "lldb/Utility/LLDBLog.h" 25 #include "lldb/lldb-enumerations.h" 26 27 using namespace lldb_private; 28 using namespace lldb_private::npdb; 29 using namespace llvm::codeview; 30 using namespace llvm::pdb; 31 32 static Variable::RangeList 33 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, 34 llvm::ArrayRef<LocalVariableAddrGap> gaps) { 35 lldb::addr_t start = 36 index.MakeVirtualAddress(range.ISectStart, range.OffsetStart); 37 lldb::addr_t end = start + range.Range; 38 39 Variable::RangeList result; 40 while (!gaps.empty()) { 41 const LocalVariableAddrGap &gap = gaps.front(); 42 43 lldb::addr_t size = gap.GapStartOffset - start; 44 result.Append(start, size); 45 start += gap.Range; 46 gaps = gaps.drop_front(); 47 } 48 49 result.Append(start, end - start); 50 return result; 51 } 52 53 namespace { 54 struct FindMembersSize : public TypeVisitorCallbacks { 55 FindMembersSize(std::vector<std::pair<RegisterId, uint32_t>> &members_info, 56 TpiStream &tpi) 57 : members_info(members_info), tpi(tpi) {} 58 std::vector<std::pair<RegisterId, uint32_t>> &members_info; 59 TpiStream &tpi; 60 llvm::Error visitKnownMember(CVMemberRecord &cvr, 61 DataMemberRecord &member) override { 62 members_info.emplace_back(llvm::codeview::RegisterId::NONE, 63 GetSizeOfType(member.Type, tpi)); 64 return llvm::Error::success(); 65 } 66 }; 67 } // namespace 68 69 CVTagRecord CVTagRecord::create(CVType type) { 70 assert(IsTagRecord(type) && "type is not a tag record!"); 71 switch (type.kind()) { 72 case LF_CLASS: 73 case LF_STRUCTURE: 74 case LF_INTERFACE: { 75 ClassRecord cr; 76 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr)); 77 return CVTagRecord(std::move(cr)); 78 } 79 case LF_UNION: { 80 UnionRecord ur; 81 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur)); 82 return CVTagRecord(std::move(ur)); 83 } 84 case LF_ENUM: { 85 EnumRecord er; 86 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er)); 87 return CVTagRecord(std::move(er)); 88 } 89 default: 90 llvm_unreachable("Unreachable!"); 91 } 92 } 93 94 CVTagRecord::CVTagRecord(ClassRecord &&c) 95 : cvclass(std::move(c)), 96 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {} 97 CVTagRecord::CVTagRecord(UnionRecord &&u) 98 : cvunion(std::move(u)), m_kind(Union) {} 99 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {} 100 101 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) { 102 switch (kind) { 103 case S_COMPILE3: 104 case S_OBJNAME: 105 return PDB_SymType::CompilandDetails; 106 case S_ENVBLOCK: 107 return PDB_SymType::CompilandEnv; 108 case S_THUNK32: 109 case S_TRAMPOLINE: 110 return PDB_SymType::Thunk; 111 case S_COFFGROUP: 112 return PDB_SymType::CoffGroup; 113 case S_EXPORT: 114 return PDB_SymType::Export; 115 case S_LPROC32: 116 case S_GPROC32: 117 case S_LPROC32_DPC: 118 return PDB_SymType::Function; 119 case S_PUB32: 120 return PDB_SymType::PublicSymbol; 121 case S_INLINESITE: 122 return PDB_SymType::InlineSite; 123 case S_LOCAL: 124 case S_BPREL32: 125 case S_REGREL32: 126 case S_MANCONSTANT: 127 case S_CONSTANT: 128 case S_LDATA32: 129 case S_GDATA32: 130 case S_LMANDATA: 131 case S_GMANDATA: 132 case S_LTHREAD32: 133 case S_GTHREAD32: 134 return PDB_SymType::Data; 135 case S_BLOCK32: 136 return PDB_SymType::Block; 137 case S_LABEL32: 138 return PDB_SymType::Label; 139 case S_CALLSITEINFO: 140 return PDB_SymType::CallSite; 141 case S_HEAPALLOCSITE: 142 return PDB_SymType::HeapAllocationSite; 143 case S_CALLEES: 144 return PDB_SymType::Callee; 145 case S_CALLERS: 146 return PDB_SymType::Caller; 147 default: 148 lldbassert(false && "Invalid symbol record kind!"); 149 } 150 return PDB_SymType::None; 151 } 152 153 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) { 154 switch (kind) { 155 case LF_ARRAY: 156 return PDB_SymType::ArrayType; 157 case LF_ARGLIST: 158 return PDB_SymType::FunctionSig; 159 case LF_BCLASS: 160 return PDB_SymType::BaseClass; 161 case LF_BINTERFACE: 162 return PDB_SymType::BaseInterface; 163 case LF_CLASS: 164 case LF_STRUCTURE: 165 case LF_INTERFACE: 166 case LF_UNION: 167 return PDB_SymType::UDT; 168 case LF_POINTER: 169 return PDB_SymType::PointerType; 170 case LF_ENUM: 171 return PDB_SymType::Enum; 172 case LF_PROCEDURE: 173 return PDB_SymType::FunctionSig; 174 case LF_BITFIELD: 175 return PDB_SymType::BuiltinType; 176 default: 177 lldbassert(false && "Invalid type record kind!"); 178 } 179 return PDB_SymType::None; 180 } 181 182 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) { 183 switch (sym.kind()) { 184 case S_GPROC32: 185 case S_LPROC32: 186 case S_GPROC32_ID: 187 case S_LPROC32_ID: 188 case S_LPROC32_DPC: 189 case S_LPROC32_DPC_ID: 190 case S_THUNK32: 191 case S_TRAMPOLINE: 192 case S_COFFGROUP: 193 case S_BLOCK32: 194 case S_LABEL32: 195 case S_CALLSITEINFO: 196 case S_HEAPALLOCSITE: 197 case S_LDATA32: 198 case S_GDATA32: 199 case S_LMANDATA: 200 case S_GMANDATA: 201 case S_LTHREAD32: 202 case S_GTHREAD32: 203 return true; 204 default: 205 return false; 206 } 207 } 208 209 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) { 210 switch (sym.kind()) { 211 case S_GPROC32: 212 case S_LPROC32: 213 case S_GPROC32_ID: 214 case S_LPROC32_ID: 215 case S_LPROC32_DPC: 216 case S_LPROC32_DPC_ID: 217 case S_THUNK32: 218 case S_TRAMPOLINE: 219 case S_COFFGROUP: 220 case S_BLOCK32: 221 return true; 222 default: 223 return false; 224 } 225 } 226 227 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) { 228 RecordT record(static_cast<SymbolRecordKind>(sym.kind())); 229 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); 230 return record; 231 } 232 233 template <typename RecordT> 234 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { 235 RecordT record = createRecord<RecordT>(sym); 236 return {record.Segment, record.CodeOffset}; 237 } 238 239 template <> 240 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) { 241 TrampolineSym record = createRecord<TrampolineSym>(sym); 242 return {record.ThunkSection, record.ThunkOffset}; 243 } 244 245 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) { 246 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 247 return {record.Segment, record.Offset}; 248 } 249 250 template <> 251 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) { 252 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 253 return {record.Segment, record.Offset}; 254 } 255 256 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) { 257 DataSym record = createRecord<DataSym>(sym); 258 return {record.Segment, record.DataOffset}; 259 } 260 261 template <> 262 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) { 263 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym); 264 return {record.Segment, record.DataOffset}; 265 } 266 267 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) { 268 switch (sym.kind()) { 269 case S_GPROC32: 270 case S_LPROC32: 271 case S_GPROC32_ID: 272 case S_LPROC32_ID: 273 case S_LPROC32_DPC: 274 case S_LPROC32_DPC_ID: 275 return ::GetSegmentAndOffset<ProcSym>(sym); 276 case S_THUNK32: 277 return ::GetSegmentAndOffset<Thunk32Sym>(sym); 278 break; 279 case S_TRAMPOLINE: 280 return ::GetSegmentAndOffset<TrampolineSym>(sym); 281 break; 282 case S_COFFGROUP: 283 return ::GetSegmentAndOffset<CoffGroupSym>(sym); 284 break; 285 case S_BLOCK32: 286 return ::GetSegmentAndOffset<BlockSym>(sym); 287 break; 288 case S_LABEL32: 289 return ::GetSegmentAndOffset<LabelSym>(sym); 290 break; 291 case S_CALLSITEINFO: 292 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym); 293 break; 294 case S_HEAPALLOCSITE: 295 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym); 296 break; 297 case S_LDATA32: 298 case S_GDATA32: 299 case S_LMANDATA: 300 case S_GMANDATA: 301 return ::GetSegmentAndOffset<DataSym>(sym); 302 break; 303 case S_LTHREAD32: 304 case S_GTHREAD32: 305 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym); 306 break; 307 default: 308 lldbassert(false && "Record does not have a segment/offset!"); 309 } 310 return {0, 0}; 311 } 312 313 template <typename RecordT> 314 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { 315 RecordT record = createRecord<RecordT>(sym); 316 return {record.Segment, record.CodeOffset, record.CodeSize}; 317 } 318 319 template <> 320 SegmentOffsetLength 321 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) { 322 TrampolineSym record = createRecord<TrampolineSym>(sym); 323 return {record.ThunkSection, record.ThunkOffset, record.Size}; 324 } 325 326 template <> 327 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) { 328 Thunk32Sym record = createRecord<Thunk32Sym>(sym); 329 return SegmentOffsetLength{record.Segment, record.Offset, record.Length}; 330 } 331 332 template <> 333 SegmentOffsetLength 334 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) { 335 CoffGroupSym record = createRecord<CoffGroupSym>(sym); 336 return SegmentOffsetLength{record.Segment, record.Offset, record.Size}; 337 } 338 339 SegmentOffsetLength 340 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) { 341 switch (sym.kind()) { 342 case S_GPROC32: 343 case S_LPROC32: 344 case S_GPROC32_ID: 345 case S_LPROC32_ID: 346 case S_LPROC32_DPC: 347 case S_LPROC32_DPC_ID: 348 return ::GetSegmentOffsetAndLength<ProcSym>(sym); 349 case S_THUNK32: 350 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym); 351 break; 352 case S_TRAMPOLINE: 353 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym); 354 break; 355 case S_COFFGROUP: 356 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym); 357 break; 358 case S_BLOCK32: 359 return ::GetSegmentOffsetAndLength<BlockSym>(sym); 360 break; 361 default: 362 lldbassert(false && "Record does not have a segment/offset/length triple!"); 363 } 364 return {0, 0, 0}; 365 } 366 367 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) { 368 ClassRecord cr; 369 UnionRecord ur; 370 EnumRecord er; 371 switch (cvt.kind()) { 372 case LF_CLASS: 373 case LF_STRUCTURE: 374 case LF_INTERFACE: 375 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 376 return cr.isForwardRef(); 377 case LF_UNION: 378 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 379 return ur.isForwardRef(); 380 case LF_ENUM: 381 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 382 return er.isForwardRef(); 383 default: 384 return false; 385 } 386 } 387 388 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) { 389 switch (cvt.kind()) { 390 case LF_CLASS: 391 case LF_STRUCTURE: 392 case LF_UNION: 393 case LF_ENUM: 394 return true; 395 default: 396 return false; 397 } 398 } 399 400 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) { 401 switch (cvt.kind()) { 402 case LF_CLASS: 403 case LF_STRUCTURE: 404 case LF_UNION: 405 return true; 406 default: 407 return false; 408 } 409 } 410 411 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id, 412 TpiStream &tpi) { 413 if (id.is_ipi || id.index.isSimple()) 414 return false; 415 return IsForwardRefUdt(tpi.getType(id.index)); 416 } 417 418 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) { 419 if (id.is_ipi || id.index.isSimple()) 420 return false; 421 return IsTagRecord(tpi.getType(id.index)); 422 } 423 424 lldb::AccessType 425 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) { 426 switch (access) { 427 case MemberAccess::Private: 428 return lldb::eAccessPrivate; 429 case MemberAccess::Protected: 430 return lldb::eAccessProtected; 431 case MemberAccess::Public: 432 return lldb::eAccessPublic; 433 case MemberAccess::None: 434 return lldb::eAccessNone; 435 } 436 llvm_unreachable("unreachable"); 437 } 438 439 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) { 440 switch (cvt.kind()) { 441 case LF_CLASS: 442 case LF_STRUCTURE: 443 case LF_INTERFACE: { 444 ClassRecord cr; 445 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 446 return cr.FieldList; 447 } 448 case LF_UNION: { 449 UnionRecord ur; 450 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 451 return ur.FieldList; 452 } 453 case LF_ENUM: { 454 EnumRecord er; 455 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 456 return er.FieldList; 457 } 458 default: 459 llvm_unreachable("Unreachable!"); 460 } 461 } 462 463 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) { 464 lldbassert(modifier.kind() == LF_MODIFIER); 465 ModifierRecord mr; 466 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr)); 467 return mr.ModifiedType; 468 } 469 470 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) { 471 return MSVCUndecoratedNameParser::DropScope(name); 472 } 473 474 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) { 475 VariableInfo result; 476 477 if (sym.kind() == S_REGREL32) { 478 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); 479 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); 480 result.type = reg.Type; 481 result.name = reg.Name; 482 return result; 483 } 484 485 if (sym.kind() == S_REGISTER) { 486 RegisterSym reg(SymbolRecordKind::RegisterSym); 487 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); 488 result.type = reg.Index; 489 result.name = reg.Name; 490 return result; 491 } 492 493 if (sym.kind() == S_LOCAL) { 494 LocalSym local(SymbolRecordKind::LocalSym); 495 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); 496 result.type = local.Type; 497 result.name = local.Name; 498 result.is_param = 499 ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None); 500 return result; 501 } 502 503 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) { 504 DataSym data(SymbolRecordKind::DataSym); 505 cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data)); 506 result.type = data.Type; 507 result.name = data.Name; 508 return result; 509 } 510 511 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) { 512 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym); 513 cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data)); 514 result.type = data.Type; 515 result.name = data.Name; 516 return result; 517 } 518 519 if (sym.kind() == S_CONSTANT) { 520 ConstantSym constant(SymbolRecordKind::ConstantSym); 521 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant)); 522 result.type = constant.Type; 523 result.name = constant.Name; 524 return result; 525 } 526 527 lldbassert(false && "Invalid variable record kind!"); 528 return {}; 529 } 530 531 static llvm::FixedStreamArray<FrameData>::Iterator 532 GetCorrespondingFrameData(lldb::addr_t load_addr, 533 const DebugFrameDataSubsectionRef &fpo_data, 534 const Variable::RangeList &ranges) { 535 lldbassert(!ranges.IsEmpty()); 536 537 // assume that all variable ranges correspond to one frame data 538 using RangeListEntry = Variable::RangeList::Entry; 539 const RangeListEntry &range = ranges.GetEntryRef(0); 540 541 auto it = fpo_data.begin(); 542 543 // start by searching first frame data range containing variable range 544 for (; it != fpo_data.end(); ++it) { 545 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); 546 547 if (fd_range.Contains(range)) { 548 break; 549 } 550 } 551 552 // then first most nested entry that still contains variable range 553 auto found = it; 554 for (; it != fpo_data.end(); ++it) { 555 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); 556 557 if (!fd_range.Contains(range)) { 558 break; 559 } 560 found = it; 561 } 562 563 return found; 564 } 565 566 static bool GetFrameDataProgram(PdbIndex &index, 567 const Variable::RangeList &ranges, 568 llvm::StringRef &out_program) { 569 const DebugFrameDataSubsectionRef &new_fpo_data = 570 index.dbi().getNewFpoRecords(); 571 572 auto frame_data_it = 573 GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges); 574 if (frame_data_it == new_fpo_data.end()) 575 return false; 576 577 PDBStringTable &strings = cantFail(index.pdb().getStringTable()); 578 out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc)); 579 return true; 580 } 581 582 static RegisterId GetBaseFrameRegister(PdbIndex &index, 583 PdbCompilandSymId frame_proc_id, 584 bool is_parameter) { 585 CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id); 586 lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC); 587 588 FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym); 589 cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs, 590 frame_proc)); 591 592 CPUType cpu_type = index.compilands() 593 .GetCompiland(frame_proc_id.modi) 594 ->m_compile_opts->Machine; 595 596 return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type) 597 : frame_proc.getLocalFramePtrReg(cpu_type); 598 } 599 600 VariableInfo lldb_private::npdb::GetVariableLocationInfo( 601 PdbIndex &index, PdbCompilandSymId var_id, Block &block, 602 lldb::ModuleSP module) { 603 604 CVSymbol sym = index.ReadSymbolRecord(var_id); 605 606 VariableInfo result = GetVariableNameInfo(sym); 607 608 if (sym.kind() == S_REGREL32) { 609 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); 610 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); 611 result.location = 612 MakeRegRelLocationExpression(reg.Register, reg.Offset, module); 613 result.ranges.emplace(); 614 return result; 615 } 616 617 if (sym.kind() == S_REGISTER) { 618 RegisterSym reg(SymbolRecordKind::RegisterSym); 619 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); 620 result.location = MakeEnregisteredLocationExpression(reg.Register, module); 621 result.ranges.emplace(); 622 return result; 623 } 624 625 if (sym.kind() == S_LOCAL) { 626 LocalSym local(SymbolRecordKind::LocalSym); 627 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); 628 629 PdbCompilandSymId loc_specifier_id(var_id.modi, 630 var_id.offset + sym.RecordData.size()); 631 CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); 632 switch(loc_specifier_cvs.kind()) { 633 case S_DEFRANGE_FRAMEPOINTER_REL: { 634 DefRangeFramePointerRelSym loc( 635 SymbolRecordKind::DefRangeFramePointerRelSym); 636 cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( 637 loc_specifier_cvs, loc)); 638 639 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); 640 641 // TODO: may be better to pass function scope and not lookup it every 642 // time? find nearest parent function block 643 Block *cur = █ 644 while (cur->GetParent()) { 645 cur = cur->GetParent(); 646 } 647 PdbCompilandSymId func_scope_id = 648 PdbSymUid(cur->GetID()).asCompilandSym(); 649 CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); 650 lldbassert(func_block_cvs.kind() == S_GPROC32 || 651 func_block_cvs.kind() == S_LPROC32); 652 653 PdbCompilandSymId frame_proc_id( 654 func_scope_id.modi, func_scope_id.offset + func_block_cvs.length()); 655 656 RegisterId base_reg = 657 GetBaseFrameRegister(index, frame_proc_id, result.is_param); 658 659 if (base_reg == RegisterId::VFRAME) { 660 llvm::StringRef program; 661 if (GetFrameDataProgram(index, ranges, program)) { 662 result.location = 663 MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module); 664 result.ranges = std::move(ranges); 665 } else { 666 // invalid variable 667 } 668 } else { 669 result.location = 670 MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); 671 result.ranges = std::move(ranges); 672 } 673 break; 674 } 675 case S_DEFRANGE_REGISTER_REL: { 676 DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym); 677 cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>( 678 loc_specifier_cvs, loc)); 679 680 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); 681 682 RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; 683 684 if (base_reg == RegisterId::VFRAME) { 685 llvm::StringRef program; 686 if (GetFrameDataProgram(index, ranges, program)) { 687 result.location = MakeVFrameRelLocationExpression( 688 program, loc.Hdr.BasePointerOffset, module); 689 result.ranges = std::move(ranges); 690 } else { 691 // invalid variable 692 } 693 } else { 694 result.location = MakeRegRelLocationExpression( 695 base_reg, loc.Hdr.BasePointerOffset, module); 696 result.ranges = std::move(ranges); 697 } 698 break; 699 } 700 case S_DEFRANGE_REGISTER: { 701 DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym); 702 cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>( 703 loc_specifier_cvs, loc)); 704 705 RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; 706 result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); 707 result.location = MakeEnregisteredLocationExpression(base_reg, module); 708 break; 709 } 710 case S_DEFRANGE_SUBFIELD_REGISTER: { 711 CVType class_cvt = index.tpi().getType(result.type); 712 ClassRecord class_record = CVTagRecord::create(class_cvt).asClass(); 713 CVType field_list = index.tpi().getType(class_record.FieldList); 714 std::vector<std::pair<RegisterId, uint32_t>> members_info; 715 FindMembersSize find_members_size(members_info, index.tpi()); 716 if (llvm::Error err = 717 visitMemberRecordStream(field_list.data(), find_members_size)) 718 llvm::consumeError(std::move(err)); 719 720 std::vector<Variable::RangeList> range_lists; 721 uint32_t cur_offset = 0; 722 size_t member_idx = 0; 723 // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by 724 // S_DEFRANGE_SUBFIELD_REGISTER, need to verify. 725 while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER && 726 member_idx < members_info.size()) { 727 DefRangeSubfieldRegisterSym loc( 728 SymbolRecordKind::DefRangeSubfieldRegisterSym); 729 cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>( 730 loc_specifier_cvs, loc)); 731 732 if (result.ranges) { 733 result.ranges = Variable::RangeList::GetOverlaps( 734 *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps)); 735 } else { 736 result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); 737 result.ranges->Sort(); 738 } 739 740 // Some fields maybe optimized away and have no 741 // S_DEFRANGE_SUBFIELD_REGISTER to describe them. Skip them. 742 while (loc.Hdr.OffsetInParent != cur_offset) { 743 cur_offset += members_info[member_idx].second; 744 ++member_idx; 745 } 746 if (member_idx < members_info.size()) { 747 members_info[member_idx].first = 748 (RegisterId)(uint16_t)loc.Hdr.Register; 749 cur_offset += members_info[member_idx].second; 750 ++member_idx; 751 } 752 // Go to next S_DEFRANGE_SUBFIELD_REGISTER. 753 loc_specifier_id = PdbCompilandSymId( 754 loc_specifier_id.modi, 755 loc_specifier_id.offset + loc_specifier_cvs.RecordData.size()); 756 loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); 757 } 758 auto member_info_ref = llvm::makeArrayRef(members_info); 759 result.location = 760 MakeEnregisteredLocationExpressionForClass(member_info_ref, module); 761 break; 762 } 763 default: 764 // FIXME: Handle other kinds. LLVM only generates the 4 types of records 765 // above. 766 break; 767 } 768 return result; 769 } 770 llvm_unreachable("Symbol is not a local variable!"); 771 return result; 772 } 773 774 lldb::BasicType 775 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { 776 switch (kind) { 777 case SimpleTypeKind::Boolean128: 778 case SimpleTypeKind::Boolean16: 779 case SimpleTypeKind::Boolean32: 780 case SimpleTypeKind::Boolean64: 781 case SimpleTypeKind::Boolean8: 782 return lldb::eBasicTypeBool; 783 case SimpleTypeKind::Byte: 784 case SimpleTypeKind::UnsignedCharacter: 785 return lldb::eBasicTypeUnsignedChar; 786 case SimpleTypeKind::NarrowCharacter: 787 return lldb::eBasicTypeChar; 788 case SimpleTypeKind::SignedCharacter: 789 case SimpleTypeKind::SByte: 790 return lldb::eBasicTypeSignedChar; 791 case SimpleTypeKind::Character16: 792 return lldb::eBasicTypeChar16; 793 case SimpleTypeKind::Character32: 794 return lldb::eBasicTypeChar32; 795 case SimpleTypeKind::Character8: 796 return lldb::eBasicTypeChar8; 797 case SimpleTypeKind::Complex80: 798 return lldb::eBasicTypeLongDoubleComplex; 799 case SimpleTypeKind::Complex64: 800 return lldb::eBasicTypeDoubleComplex; 801 case SimpleTypeKind::Complex32: 802 return lldb::eBasicTypeFloatComplex; 803 case SimpleTypeKind::Float128: 804 case SimpleTypeKind::Float80: 805 return lldb::eBasicTypeLongDouble; 806 case SimpleTypeKind::Float64: 807 return lldb::eBasicTypeDouble; 808 case SimpleTypeKind::Float32: 809 return lldb::eBasicTypeFloat; 810 case SimpleTypeKind::Float16: 811 return lldb::eBasicTypeHalf; 812 case SimpleTypeKind::Int128: 813 return lldb::eBasicTypeInt128; 814 case SimpleTypeKind::Int64: 815 case SimpleTypeKind::Int64Quad: 816 return lldb::eBasicTypeLongLong; 817 case SimpleTypeKind::Int32: 818 return lldb::eBasicTypeInt; 819 case SimpleTypeKind::Int16: 820 case SimpleTypeKind::Int16Short: 821 return lldb::eBasicTypeShort; 822 case SimpleTypeKind::UInt128: 823 return lldb::eBasicTypeUnsignedInt128; 824 case SimpleTypeKind::UInt64: 825 case SimpleTypeKind::UInt64Quad: 826 return lldb::eBasicTypeUnsignedLongLong; 827 case SimpleTypeKind::HResult: 828 case SimpleTypeKind::UInt32: 829 return lldb::eBasicTypeUnsignedInt; 830 case SimpleTypeKind::UInt16: 831 case SimpleTypeKind::UInt16Short: 832 return lldb::eBasicTypeUnsignedShort; 833 case SimpleTypeKind::Int32Long: 834 return lldb::eBasicTypeLong; 835 case SimpleTypeKind::UInt32Long: 836 return lldb::eBasicTypeUnsignedLong; 837 case SimpleTypeKind::Void: 838 return lldb::eBasicTypeVoid; 839 case SimpleTypeKind::WideCharacter: 840 return lldb::eBasicTypeWChar; 841 default: 842 return lldb::eBasicTypeInvalid; 843 } 844 } 845 846 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { 847 switch (kind) { 848 case SimpleTypeKind::Boolean128: 849 case SimpleTypeKind::Int128: 850 case SimpleTypeKind::UInt128: 851 case SimpleTypeKind::Float128: 852 return 16; 853 case SimpleTypeKind::Complex80: 854 case SimpleTypeKind::Float80: 855 return 10; 856 case SimpleTypeKind::Boolean64: 857 case SimpleTypeKind::Complex64: 858 case SimpleTypeKind::UInt64: 859 case SimpleTypeKind::UInt64Quad: 860 case SimpleTypeKind::Float64: 861 case SimpleTypeKind::Int64: 862 case SimpleTypeKind::Int64Quad: 863 return 8; 864 case SimpleTypeKind::Boolean32: 865 case SimpleTypeKind::Character32: 866 case SimpleTypeKind::Complex32: 867 case SimpleTypeKind::Float32: 868 case SimpleTypeKind::Int32: 869 case SimpleTypeKind::Int32Long: 870 case SimpleTypeKind::UInt32Long: 871 case SimpleTypeKind::HResult: 872 case SimpleTypeKind::UInt32: 873 return 4; 874 case SimpleTypeKind::Boolean16: 875 case SimpleTypeKind::Character16: 876 case SimpleTypeKind::Float16: 877 case SimpleTypeKind::Int16: 878 case SimpleTypeKind::Int16Short: 879 case SimpleTypeKind::UInt16: 880 case SimpleTypeKind::UInt16Short: 881 case SimpleTypeKind::WideCharacter: 882 return 2; 883 case SimpleTypeKind::Boolean8: 884 case SimpleTypeKind::Byte: 885 case SimpleTypeKind::UnsignedCharacter: 886 case SimpleTypeKind::NarrowCharacter: 887 case SimpleTypeKind::SignedCharacter: 888 case SimpleTypeKind::SByte: 889 case SimpleTypeKind::Character8: 890 return 1; 891 case SimpleTypeKind::Void: 892 default: 893 return 0; 894 } 895 } 896 897 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id, 898 TpiStream &tpi) { 899 if (id.index.isSimple()) 900 return id; 901 902 CVType cvt = tpi.getType(id.index); 903 904 // Only tag records have a best and a worst record. 905 if (!IsTagRecord(cvt)) 906 return id; 907 908 // Tag records that are not forward decls are full decls, hence they are the 909 // best. 910 if (!IsForwardRefUdt(cvt)) 911 return id; 912 913 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index)); 914 } 915 916 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) { 917 RecordType record; 918 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record)); 919 return record.getSize(); 920 } 921 922 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id, 923 llvm::pdb::TpiStream &tpi) { 924 if (id.index.isSimple()) { 925 switch (id.index.getSimpleMode()) { 926 case SimpleTypeMode::Direct: 927 return GetTypeSizeForSimpleKind(id.index.getSimpleKind()); 928 case SimpleTypeMode::NearPointer32: 929 case SimpleTypeMode::FarPointer32: 930 return 4; 931 case SimpleTypeMode::NearPointer64: 932 return 8; 933 case SimpleTypeMode::NearPointer128: 934 return 16; 935 default: 936 break; 937 } 938 return 0; 939 } 940 941 TypeIndex index = id.index; 942 if (IsForwardRefUdt(index, tpi)) 943 index = llvm::cantFail(tpi.findFullDeclForForwardRef(index)); 944 945 CVType cvt = tpi.getType(index); 946 switch (cvt.kind()) { 947 case LF_MODIFIER: 948 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi); 949 case LF_ENUM: { 950 EnumRecord record; 951 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record)); 952 return GetSizeOfType({record.UnderlyingType}, tpi); 953 } 954 case LF_POINTER: 955 return GetSizeOfTypeInternal<PointerRecord>(cvt); 956 case LF_ARRAY: 957 return GetSizeOfTypeInternal<ArrayRecord>(cvt); 958 case LF_CLASS: 959 case LF_STRUCTURE: 960 case LF_INTERFACE: 961 return GetSizeOfTypeInternal<ClassRecord>(cvt); 962 case LF_UNION: 963 return GetSizeOfTypeInternal<UnionRecord>(cvt); 964 default: 965 break; 966 } 967 return 0; 968 } 969