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