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