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