1146 lines · cpp
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-exception6//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 "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"23#include "lldb/Symbol/Block.h"24#include "lldb/Utility/LLDBAssert.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/lldb-enumerations.h"27 28using namespace lldb_private;29using namespace lldb_private::npdb;30using namespace llvm::codeview;31using namespace llvm::pdb;32 33// The returned range list is guaranteed to be sorted and no overlaps between34// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.35static Variable::RangeList36MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,37 llvm::ArrayRef<LocalVariableAddrGap> gaps) {38 lldb::addr_t start =39 index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);40 if (start == LLDB_INVALID_ADDRESS)41 return {};42 lldb::addr_t end = start + range.Range;43 44 Variable::RangeList result;45 while (!gaps.empty()) {46 const LocalVariableAddrGap &gap = gaps.front();47 lldb::addr_t gap_start = start + gap.GapStartOffset;48 result.Append(start, gap_start - start);49 start = gap_start + gap.Range;50 gaps = gaps.drop_front();51 }52 53 result.Append(start, end - start);54 return result;55}56 57namespace {58struct MemberLocations {59 std::map<uint64_t, MemberValLocation> offset_to_location;60 DWARFExpression expr;61 bool is_dwarf = false;62 63 MemberLocations() = default;64 MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}65 MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {66 insert(offset, member_loc);67 }68 69 void insert(uint64_t offset, const MemberValLocation &member_loc) {70 offset_to_location[offset] = member_loc;71 }72 73 struct Comparator {74 public:75 bool operator()(const MemberLocations &, const MemberLocations &) const {76 return false;77 }78 };79};80 81// A range map with address ranges to a map of pair of offset and locaitons.82typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,83 MemberLocations::Comparator>84 RangeMap;85 86void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,87 MemberValLocation member_loc,88 const Variable::RangeList &ranges) {89 RangeMap new_location_map;90 auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,91 RangeMap::Entry *entry) {92 RangeMap::Entry overlap_region = {base, end - base, entry->data};93 overlap_region.data.insert(offset, member_loc);94 new_location_map.Append(overlap_region);95 };96 97 for (const auto &range : ranges) {98 lldb::addr_t base = range.GetRangeBase();99 lldb::addr_t end = range.GetRangeEnd();100 uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);101 while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {102 if (base >= end || entry->base >= end)103 break;104 if (entry->data.is_dwarf)105 base = entry->GetRangeEnd();106 else {107 lldb::addr_t entry_end = entry->GetRangeEnd();108 if (base > entry->base) {109 if (end < entry_end)110 new_location_map.Append({end, entry_end - end, entry->data});111 add_overlap_region(base, end < entry_end ? end : entry_end, entry);112 entry->SetRangeEnd(base);113 } else if (base < entry->base) {114 new_location_map.Append(115 {base, entry->base - base, {offset, member_loc}});116 if (entry_end == end)117 entry->data.insert(offset, member_loc);118 else {119 add_overlap_region(entry->base, end, entry);120 entry->ShrinkFront(end - entry->base);121 }122 } else {123 if (end < entry_end) {124 new_location_map.Append({end, entry_end, entry->data});125 entry->SetRangeEnd(end);126 }127 entry->data.insert(offset, member_loc);128 }129 base = entry_end;130 }131 ++base_idx;132 }133 if (base >= end)134 continue;135 new_location_map.Append({base, end - base, {offset, member_loc}});136 }137 for (const auto &entry : new_location_map)138 location_map.Append(entry);139 if (!new_location_map.IsEmpty())140 location_map.Sort();141}142 143void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,144 const Variable::RangeList &ranges) {145 if (!expr.IsValid())146 return;147 RangeMap new_location_map;148 for (const auto &range : ranges) {149 lldb::addr_t base = range.GetRangeBase();150 lldb::addr_t end = range.GetRangeEnd();151 uint32_t base_idx = location_map.FindEntryIndexThatContains(base);152 uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);153 // range is within an entry.154 if (base_idx == end_idx && base_idx != UINT32_MAX) {155 auto *entry = location_map.GetMutableEntryAtIndex(base_idx);156 if (base > entry->base) {157 new_location_map.Append({entry->base, base - entry->base, entry->data});158 entry->ShrinkFront(base - entry->base);159 }160 if (end == entry->GetRangeEnd())161 entry->data = expr;162 else {163 entry->ShrinkFront(end - base);164 new_location_map.Append({base, end - base, expr});165 }166 continue;167 }168 base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);169 if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {170 if (entry->Contains(base) && entry->base != base) {171 entry->SetRangeEnd(base);172 ++base_idx;173 }174 }175 end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);176 if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {177 if (entry->Contains(end - 1)) {178 if (entry->GetRangeEnd() == end)179 ++end_idx;180 else181 entry->ShrinkFront(end - entry->base);182 }183 }184 185 if (end_idx == UINT32_MAX)186 end_idx = location_map.GetSize();187 // Erase existing ranges covered by new range.188 location_map.Erase(base_idx, end_idx);189 new_location_map.Append({base, end - base, expr});190 }191 192 for (const auto &entry : new_location_map)193 location_map.Append(entry);194 location_map.Sort();195}196} // namespace197 198CVTagRecord CVTagRecord::create(CVType type) {199 assert(IsTagRecord(type) && "type is not a tag record!");200 switch (type.kind()) {201 case LF_CLASS:202 case LF_STRUCTURE:203 case LF_INTERFACE: {204 ClassRecord cr;205 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));206 return CVTagRecord(std::move(cr));207 }208 case LF_UNION: {209 UnionRecord ur;210 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));211 return CVTagRecord(std::move(ur));212 }213 case LF_ENUM: {214 EnumRecord er;215 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));216 return CVTagRecord(std::move(er));217 }218 default:219 llvm_unreachable("Unreachable!");220 }221}222 223CVTagRecord::CVTagRecord(ClassRecord &&c)224 : cvclass(std::move(c)),225 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}226CVTagRecord::CVTagRecord(UnionRecord &&u)227 : cvunion(std::move(u)), m_kind(Union) {}228CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}229 230PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {231 switch (kind) {232 case S_COMPILE3:233 case S_OBJNAME:234 return PDB_SymType::CompilandDetails;235 case S_ENVBLOCK:236 return PDB_SymType::CompilandEnv;237 case S_THUNK32:238 case S_TRAMPOLINE:239 return PDB_SymType::Thunk;240 case S_COFFGROUP:241 return PDB_SymType::CoffGroup;242 case S_EXPORT:243 return PDB_SymType::Export;244 case S_LPROC32:245 case S_GPROC32:246 case S_LPROC32_DPC:247 return PDB_SymType::Function;248 case S_PUB32:249 return PDB_SymType::PublicSymbol;250 case S_INLINESITE:251 return PDB_SymType::InlineSite;252 case S_LOCAL:253 case S_BPREL32:254 case S_REGREL32:255 case S_MANCONSTANT:256 case S_CONSTANT:257 case S_LDATA32:258 case S_GDATA32:259 case S_LMANDATA:260 case S_GMANDATA:261 case S_LTHREAD32:262 case S_GTHREAD32:263 return PDB_SymType::Data;264 case S_BLOCK32:265 return PDB_SymType::Block;266 case S_LABEL32:267 return PDB_SymType::Label;268 case S_CALLSITEINFO:269 return PDB_SymType::CallSite;270 case S_HEAPALLOCSITE:271 return PDB_SymType::HeapAllocationSite;272 case S_CALLEES:273 return PDB_SymType::Callee;274 case S_CALLERS:275 return PDB_SymType::Caller;276 default:277 lldbassert(false && "Invalid symbol record kind!");278 }279 return PDB_SymType::None;280}281 282PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {283 switch (kind) {284 case LF_ARRAY:285 return PDB_SymType::ArrayType;286 case LF_ARGLIST:287 return PDB_SymType::FunctionSig;288 case LF_BCLASS:289 return PDB_SymType::BaseClass;290 case LF_BINTERFACE:291 return PDB_SymType::BaseInterface;292 case LF_CLASS:293 case LF_STRUCTURE:294 case LF_INTERFACE:295 case LF_UNION:296 return PDB_SymType::UDT;297 case LF_POINTER:298 return PDB_SymType::PointerType;299 case LF_ENUM:300 return PDB_SymType::Enum;301 case LF_PROCEDURE:302 return PDB_SymType::FunctionSig;303 case LF_BITFIELD:304 return PDB_SymType::BuiltinType;305 default:306 lldbassert(false && "Invalid type record kind!");307 }308 return PDB_SymType::None;309}310 311bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {312 switch (sym.kind()) {313 case S_GPROC32:314 case S_LPROC32:315 case S_GPROC32_ID:316 case S_LPROC32_ID:317 case S_LPROC32_DPC:318 case S_LPROC32_DPC_ID:319 case S_THUNK32:320 case S_TRAMPOLINE:321 case S_COFFGROUP:322 case S_BLOCK32:323 case S_LABEL32:324 case S_CALLSITEINFO:325 case S_HEAPALLOCSITE:326 case S_LDATA32:327 case S_GDATA32:328 case S_LMANDATA:329 case S_GMANDATA:330 case S_LTHREAD32:331 case S_GTHREAD32:332 return true;333 default:334 return false;335 }336}337 338bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {339 switch (sym.kind()) {340 case S_GPROC32:341 case S_LPROC32:342 case S_GPROC32_ID:343 case S_LPROC32_ID:344 case S_LPROC32_DPC:345 case S_LPROC32_DPC_ID:346 case S_THUNK32:347 case S_TRAMPOLINE:348 case S_COFFGROUP:349 case S_BLOCK32:350 return true;351 default:352 return false;353 }354}355 356template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {357 RecordT record(static_cast<SymbolRecordKind>(sym.kind()));358 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));359 return record;360}361 362template <typename RecordT>363static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {364 RecordT record = createRecord<RecordT>(sym);365 return {record.Segment, record.CodeOffset};366}367 368template <>369SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {370 TrampolineSym record = createRecord<TrampolineSym>(sym);371 return {record.ThunkSection, record.ThunkOffset};372}373 374template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {375 Thunk32Sym record = createRecord<Thunk32Sym>(sym);376 return {record.Segment, record.Offset};377}378 379template <>380SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {381 CoffGroupSym record = createRecord<CoffGroupSym>(sym);382 return {record.Segment, record.Offset};383}384 385template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {386 DataSym record = createRecord<DataSym>(sym);387 return {record.Segment, record.DataOffset};388}389 390template <>391SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {392 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);393 return {record.Segment, record.DataOffset};394}395 396SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {397 switch (sym.kind()) {398 case S_GPROC32:399 case S_LPROC32:400 case S_GPROC32_ID:401 case S_LPROC32_ID:402 case S_LPROC32_DPC:403 case S_LPROC32_DPC_ID:404 return ::GetSegmentAndOffset<ProcSym>(sym);405 case S_THUNK32:406 return ::GetSegmentAndOffset<Thunk32Sym>(sym);407 break;408 case S_TRAMPOLINE:409 return ::GetSegmentAndOffset<TrampolineSym>(sym);410 break;411 case S_COFFGROUP:412 return ::GetSegmentAndOffset<CoffGroupSym>(sym);413 break;414 case S_BLOCK32:415 return ::GetSegmentAndOffset<BlockSym>(sym);416 break;417 case S_LABEL32:418 return ::GetSegmentAndOffset<LabelSym>(sym);419 break;420 case S_CALLSITEINFO:421 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);422 break;423 case S_HEAPALLOCSITE:424 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);425 break;426 case S_LDATA32:427 case S_GDATA32:428 case S_LMANDATA:429 case S_GMANDATA:430 return ::GetSegmentAndOffset<DataSym>(sym);431 break;432 case S_LTHREAD32:433 case S_GTHREAD32:434 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);435 break;436 default:437 lldbassert(false && "Record does not have a segment/offset!");438 }439 return {0, 0};440}441 442template <typename RecordT>443SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {444 RecordT record = createRecord<RecordT>(sym);445 return {record.Segment, record.CodeOffset, record.CodeSize};446}447 448template <>449SegmentOffsetLength450GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {451 TrampolineSym record = createRecord<TrampolineSym>(sym);452 return {record.ThunkSection, record.ThunkOffset, record.Size};453}454 455template <>456SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {457 Thunk32Sym record = createRecord<Thunk32Sym>(sym);458 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};459}460 461template <>462SegmentOffsetLength463GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {464 CoffGroupSym record = createRecord<CoffGroupSym>(sym);465 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};466}467 468SegmentOffsetLength469lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {470 switch (sym.kind()) {471 case S_GPROC32:472 case S_LPROC32:473 case S_GPROC32_ID:474 case S_LPROC32_ID:475 case S_LPROC32_DPC:476 case S_LPROC32_DPC_ID:477 return ::GetSegmentOffsetAndLength<ProcSym>(sym);478 case S_THUNK32:479 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);480 break;481 case S_TRAMPOLINE:482 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);483 break;484 case S_COFFGROUP:485 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);486 break;487 case S_BLOCK32:488 return ::GetSegmentOffsetAndLength<BlockSym>(sym);489 break;490 default:491 lldbassert(false && "Record does not have a segment/offset/length triple!");492 }493 return {0, 0, 0};494}495 496bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {497 ClassRecord cr;498 UnionRecord ur;499 EnumRecord er;500 switch (cvt.kind()) {501 case LF_CLASS:502 case LF_STRUCTURE:503 case LF_INTERFACE:504 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));505 return cr.isForwardRef();506 case LF_UNION:507 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));508 return ur.isForwardRef();509 case LF_ENUM:510 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));511 return er.isForwardRef();512 default:513 return false;514 }515}516 517bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {518 switch (cvt.kind()) {519 case LF_CLASS:520 case LF_STRUCTURE:521 case LF_UNION:522 case LF_ENUM:523 return true;524 default:525 return false;526 }527}528 529bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {530 switch (cvt.kind()) {531 case LF_CLASS:532 case LF_STRUCTURE:533 case LF_UNION:534 return true;535 default:536 return false;537 }538}539 540bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,541 TpiStream &tpi) {542 if (id.is_ipi || id.index.isSimple())543 return false;544 return IsForwardRefUdt(tpi.getType(id.index));545}546 547bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {548 if (id.is_ipi || id.index.isSimple())549 return false;550 return IsTagRecord(tpi.getType(id.index));551}552 553lldb::AccessType554lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {555 switch (access) {556 case MemberAccess::Private:557 return lldb::eAccessPrivate;558 case MemberAccess::Protected:559 return lldb::eAccessProtected;560 case MemberAccess::Public:561 return lldb::eAccessPublic;562 case MemberAccess::None:563 return lldb::eAccessNone;564 }565 llvm_unreachable("unreachable");566}567 568TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {569 switch (cvt.kind()) {570 case LF_CLASS:571 case LF_STRUCTURE:572 case LF_INTERFACE: {573 ClassRecord cr;574 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));575 return cr.FieldList;576 }577 case LF_UNION: {578 UnionRecord ur;579 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));580 return ur.FieldList;581 }582 case LF_ENUM: {583 EnumRecord er;584 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));585 return er.FieldList;586 }587 default:588 llvm_unreachable("Unreachable!");589 }590}591 592TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {593 lldbassert(modifier.kind() == LF_MODIFIER);594 ModifierRecord mr;595 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));596 return mr.ModifiedType;597}598 599llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {600 return MSVCUndecoratedNameParser::DropScope(name);601}602 603VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {604 VariableInfo result = {};605 606 if (sym.kind() == S_REGREL32) {607 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);608 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));609 result.type = reg.Type;610 result.name = reg.Name;611 return result;612 }613 614 if (sym.kind() == S_REGISTER) {615 RegisterSym reg(SymbolRecordKind::RegisterSym);616 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));617 result.type = reg.Index;618 result.name = reg.Name;619 return result;620 }621 622 if (sym.kind() == S_LOCAL) {623 LocalSym local(SymbolRecordKind::LocalSym);624 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));625 result.type = local.Type;626 result.name = local.Name;627 result.is_param =628 ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);629 return result;630 }631 632 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {633 DataSym data(SymbolRecordKind::DataSym);634 cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));635 result.type = data.Type;636 result.name = data.Name;637 return result;638 }639 640 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {641 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);642 cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));643 result.type = data.Type;644 result.name = data.Name;645 return result;646 }647 648 if (sym.kind() == S_CONSTANT) {649 ConstantSym constant(SymbolRecordKind::ConstantSym);650 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));651 result.type = constant.Type;652 result.name = constant.Name;653 return result;654 }655 656 lldbassert(false && "Invalid variable record kind!");657 return {};658}659 660static llvm::FixedStreamArray<FrameData>::Iterator661GetCorrespondingFrameData(lldb::addr_t load_addr,662 const DebugFrameDataSubsectionRef &fpo_data,663 const Variable::RangeList &ranges) {664 lldbassert(!ranges.IsEmpty());665 666 // assume that all variable ranges correspond to one frame data667 using RangeListEntry = Variable::RangeList::Entry;668 const RangeListEntry &range = ranges.GetEntryRef(0);669 670 auto it = fpo_data.begin();671 672 // start by searching first frame data range containing variable range673 for (; it != fpo_data.end(); ++it) {674 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);675 676 if (fd_range.Contains(range)) {677 break;678 }679 }680 681 // then first most nested entry that still contains variable range682 auto found = it;683 for (; it != fpo_data.end(); ++it) {684 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);685 686 if (!fd_range.Contains(range)) {687 break;688 }689 found = it;690 }691 692 return found;693}694 695static bool GetFrameDataProgram(PdbIndex &index,696 const Variable::RangeList &ranges,697 llvm::StringRef &out_program) {698 const DebugFrameDataSubsectionRef &new_fpo_data =699 index.dbi().getNewFpoRecords();700 701 auto frame_data_it =702 GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);703 if (frame_data_it == new_fpo_data.end())704 return false;705 706 auto strings = index.pdb().getStringTable();707 if (!strings) {708 consumeError(strings.takeError());709 return false;710 }711 out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));712 return true;713}714 715static RegisterId GetBaseFrameRegister(PdbIndex &index,716 PdbCompilandSymId frame_proc_id,717 bool is_parameter) {718 CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);719 if (frame_proc_cvs.kind() != S_FRAMEPROC)720 return RegisterId::NONE;721 722 FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);723 cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,724 frame_proc));725 726 CPUType cpu_type = index.compilands()727 .GetCompiland(frame_proc_id.modi)728 ->m_compile_opts->Machine;729 730 return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)731 : frame_proc.getLocalFramePtrReg(cpu_type);732}733 734VariableInfo lldb_private::npdb::GetVariableLocationInfo(735 PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,736 lldb::ModuleSP module) {737 738 CVSymbol sym = index.ReadSymbolRecord(var_id);739 740 VariableInfo result = GetVariableNameInfo(sym);741 742 if (sym.kind() == S_REGREL32) {743 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);744 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));745 result.location = DWARFExpressionList(746 module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),747 nullptr);748 return result;749 }750 751 if (sym.kind() == S_REGISTER) {752 RegisterSym reg(SymbolRecordKind::RegisterSym);753 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));754 result.location = DWARFExpressionList(755 module, MakeEnregisteredLocationExpression(reg.Register, module),756 nullptr);757 return result;758 }759 760 if (sym.kind() == S_LOCAL) {761 LocalSym local(SymbolRecordKind::LocalSym);762 if (llvm::Error error =763 SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {764 llvm::consumeError(std::move(error));765 return result;766 }767 768 PdbCompilandSymId loc_specifier_id(var_id.modi,769 var_id.offset + sym.RecordData.size());770 CVSymbol loc_specifier_cvs;771 // Only used for S_DEFRANGE_FRAMEPOINTER_REL.772 RegisterId base_reg = RegisterId::NONE;773 size_t type_size = GetSizeOfType(result.type, index.tpi());774 // A map from offset of a field in parent to size of the field.775 std::map<uint64_t, size_t> offset_to_size;776 777 // When overlaps happens, always prefer the one that doesn't split the value778 // into multiple locations and the location parsed first is perfered.779 RangeMap location_map;780 781 // Iterate through all location records after S_LOCAL. They describe the782 // value of this variable at different locations.783 bool finished = false;784 while (!finished) {785 loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);786 switch (loc_specifier_cvs.kind()) {787 case S_DEFRANGE_FRAMEPOINTER_REL: {788 DefRangeFramePointerRelSym loc(789 SymbolRecordKind::DefRangeFramePointerRelSym);790 if (llvm::Error error =791 SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(792 loc_specifier_cvs, loc)) {793 llvm::consumeError(std::move(error));794 return result;795 }796 Variable::RangeList raw_ranges =797 MakeRangeList(index, loc.Range, loc.Gaps);798 if (base_reg == RegisterId::NONE) {799 PdbCompilandSymId func_scope_id =800 PdbSymUid(func_block.GetID()).asCompilandSym();801 CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);802 lldbassert(func_block_cvs.kind() == S_GPROC32 ||803 func_block_cvs.kind() == S_LPROC32);804 PdbCompilandSymId frame_proc_id(func_scope_id.modi,805 func_scope_id.offset +806 func_block_cvs.length());807 base_reg =808 GetBaseFrameRegister(index, frame_proc_id, result.is_param);809 if (base_reg == RegisterId::NONE)810 break;811 }812 DWARFExpression expr;813 if (base_reg == RegisterId::VFRAME) {814 llvm::StringRef program;815 if (GetFrameDataProgram(index, raw_ranges, program))816 expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,817 module);818 else {819 // invalid variable820 }821 } else822 expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);823 AddDwarfRange(location_map, expr, raw_ranges);824 break;825 }826 case S_DEFRANGE_REGISTER: {827 DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);828 if (llvm::Error error =829 SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(830 loc_specifier_cvs, loc)) {831 llvm::consumeError(std::move(error));832 return result;833 }834 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;835 Variable::RangeList raw_ranges =836 MakeRangeList(index, loc.Range, loc.Gaps);837 DWARFExpression expr =838 MakeEnregisteredLocationExpression(reg_id, module);839 AddDwarfRange(location_map, expr, raw_ranges);840 break;841 }842 case S_DEFRANGE_REGISTER_REL: {843 DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);844 if (llvm::Error error =845 SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(846 loc_specifier_cvs, loc)) {847 llvm::consumeError(std::move(error));848 return result;849 }850 Variable::RangeList raw_ranges =851 MakeRangeList(index, loc.Range, loc.Gaps);852 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;853 DWARFExpression expr;854 if (reg_id == RegisterId::VFRAME) {855 llvm::StringRef program;856 if (GetFrameDataProgram(index, raw_ranges, program))857 expr = MakeVFrameRelLocationExpression(858 program, loc.Hdr.BasePointerOffset, module);859 else {860 // invalid variable861 }862 } else {863 expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,864 module);865 }866 // FIXME: If it's UDT, we need to know the size of the value in byte.867 if (!loc.hasSpilledUDTMember())868 AddDwarfRange(location_map, expr, raw_ranges);869 break;870 }871 case S_DEFRANGE_SUBFIELD_REGISTER: {872 DefRangeSubfieldRegisterSym loc(873 SymbolRecordKind::DefRangeSubfieldRegisterSym);874 if (llvm::Error error =875 SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(876 loc_specifier_cvs, loc)) {877 llvm::consumeError(std::move(error));878 return result;879 }880 881 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);882 uint32_t reg_size =883 GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);884 if (reg_size == 0)885 break;886 offset_to_size[loc.Hdr.OffsetInParent] = reg_size;887 AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,888 {loc.Hdr.Register, 0, true}, ranges);889 break;890 }891 // FIXME: Handle other kinds. LLVM only generates the 4 types of records892 // above. MSVC generates other location types.893 case S_DEFRANGE:894 case S_DEFRANGE_SUBFIELD:895 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:896 break;897 default:898 finished = true;899 break;900 }901 loc_specifier_id = PdbCompilandSymId(902 loc_specifier_id.modi,903 loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());904 }905 for (const auto &entry : location_map) {906 DWARFExpression dwarf_expr =907 entry.data.is_dwarf ? entry.data.expr908 : MakeEnregisteredLocationExpressionForComposite(909 entry.data.offset_to_location,910 offset_to_size, type_size, module);911 912 result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),913 dwarf_expr);914 }915 return result;916 }917 llvm_unreachable("Symbol is not a local variable!");918 return result;919}920 921lldb::BasicType922lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {923 switch (kind) {924 case SimpleTypeKind::Boolean128:925 case SimpleTypeKind::Boolean16:926 case SimpleTypeKind::Boolean32:927 case SimpleTypeKind::Boolean64:928 case SimpleTypeKind::Boolean8:929 return lldb::eBasicTypeBool;930 case SimpleTypeKind::Byte:931 case SimpleTypeKind::UnsignedCharacter:932 return lldb::eBasicTypeUnsignedChar;933 case SimpleTypeKind::NarrowCharacter:934 return lldb::eBasicTypeChar;935 case SimpleTypeKind::SignedCharacter:936 case SimpleTypeKind::SByte:937 return lldb::eBasicTypeSignedChar;938 case SimpleTypeKind::Character16:939 return lldb::eBasicTypeChar16;940 case SimpleTypeKind::Character32:941 return lldb::eBasicTypeChar32;942 case SimpleTypeKind::Character8:943 return lldb::eBasicTypeChar8;944 case SimpleTypeKind::Complex80:945 return lldb::eBasicTypeLongDoubleComplex;946 case SimpleTypeKind::Complex64:947 return lldb::eBasicTypeDoubleComplex;948 case SimpleTypeKind::Complex32:949 case SimpleTypeKind::Complex32PartialPrecision:950 return lldb::eBasicTypeFloatComplex;951 case SimpleTypeKind::Float80:952 return lldb::eBasicTypeLongDouble;953 case SimpleTypeKind::Float128:954 return lldb::eBasicTypeFloat128;955 case SimpleTypeKind::Float64:956 return lldb::eBasicTypeDouble;957 case SimpleTypeKind::Float32:958 case SimpleTypeKind::Float32PartialPrecision:959 return lldb::eBasicTypeFloat;960 case SimpleTypeKind::Float16:961 return lldb::eBasicTypeHalf;962 case SimpleTypeKind::Int128:963 case SimpleTypeKind::Int128Oct:964 return lldb::eBasicTypeInt128;965 case SimpleTypeKind::Int64:966 case SimpleTypeKind::Int64Quad:967 return lldb::eBasicTypeLongLong;968 case SimpleTypeKind::Int32:969 return lldb::eBasicTypeInt;970 case SimpleTypeKind::Int16:971 case SimpleTypeKind::Int16Short:972 return lldb::eBasicTypeShort;973 case SimpleTypeKind::UInt128:974 case SimpleTypeKind::UInt128Oct:975 return lldb::eBasicTypeUnsignedInt128;976 case SimpleTypeKind::UInt64:977 case SimpleTypeKind::UInt64Quad:978 return lldb::eBasicTypeUnsignedLongLong;979 case SimpleTypeKind::HResult:980 case SimpleTypeKind::UInt32:981 return lldb::eBasicTypeUnsignedInt;982 case SimpleTypeKind::UInt16:983 case SimpleTypeKind::UInt16Short:984 return lldb::eBasicTypeUnsignedShort;985 case SimpleTypeKind::Int32Long:986 return lldb::eBasicTypeLong;987 case SimpleTypeKind::UInt32Long:988 return lldb::eBasicTypeUnsignedLong;989 case SimpleTypeKind::Void:990 return lldb::eBasicTypeVoid;991 case SimpleTypeKind::WideCharacter:992 return lldb::eBasicTypeWChar;993 994 // Not supported.995 case SimpleTypeKind::Float48:996 case SimpleTypeKind::Complex16:997 case SimpleTypeKind::Complex48:998 case SimpleTypeKind::Complex128:999 case SimpleTypeKind::NotTranslated:1000 case SimpleTypeKind::None:1001 return lldb::eBasicTypeInvalid;1002 }1003 return lldb::eBasicTypeInvalid;1004}1005 1006size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {1007 switch (kind) {1008 case SimpleTypeKind::Boolean128:1009 case SimpleTypeKind::Complex128:1010 case SimpleTypeKind::Int128:1011 case SimpleTypeKind::Int128Oct:1012 case SimpleTypeKind::UInt128:1013 case SimpleTypeKind::UInt128Oct:1014 case SimpleTypeKind::Float128:1015 return 16;1016 case SimpleTypeKind::Complex80:1017 case SimpleTypeKind::Float80:1018 return 10;1019 case SimpleTypeKind::Boolean64:1020 case SimpleTypeKind::Complex64:1021 case SimpleTypeKind::UInt64:1022 case SimpleTypeKind::UInt64Quad:1023 case SimpleTypeKind::Float64:1024 case SimpleTypeKind::Int64:1025 case SimpleTypeKind::Int64Quad:1026 return 8;1027 case SimpleTypeKind::Complex48:1028 case SimpleTypeKind::Float48:1029 return 6;1030 case SimpleTypeKind::Boolean32:1031 case SimpleTypeKind::Character32:1032 case SimpleTypeKind::Complex32:1033 case SimpleTypeKind::Complex32PartialPrecision:1034 case SimpleTypeKind::Float32:1035 case SimpleTypeKind::Float32PartialPrecision:1036 case SimpleTypeKind::Int32:1037 case SimpleTypeKind::Int32Long:1038 case SimpleTypeKind::UInt32Long:1039 case SimpleTypeKind::HResult:1040 case SimpleTypeKind::UInt32:1041 return 4;1042 case SimpleTypeKind::Boolean16:1043 case SimpleTypeKind::Character16:1044 case SimpleTypeKind::Complex16:1045 case SimpleTypeKind::Float16:1046 case SimpleTypeKind::Int16:1047 case SimpleTypeKind::Int16Short:1048 case SimpleTypeKind::UInt16:1049 case SimpleTypeKind::UInt16Short:1050 case SimpleTypeKind::WideCharacter:1051 return 2;1052 case SimpleTypeKind::Boolean8:1053 case SimpleTypeKind::Byte:1054 case SimpleTypeKind::UnsignedCharacter:1055 case SimpleTypeKind::NarrowCharacter:1056 case SimpleTypeKind::SignedCharacter:1057 case SimpleTypeKind::SByte:1058 case SimpleTypeKind::Character8:1059 return 1;1060 1061 case SimpleTypeKind::Void:1062 case SimpleTypeKind::None:1063 case SimpleTypeKind::NotTranslated:1064 return 0;1065 }1066 return 0;1067}1068 1069PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,1070 TpiStream &tpi) {1071 if (id.index.isSimple())1072 return id;1073 1074 CVType cvt = tpi.getType(id.index);1075 1076 // Only tag records have a best and a worst record.1077 if (!IsTagRecord(cvt))1078 return id;1079 1080 // Tag records that are not forward decls are full decls, hence they are the1081 // best.1082 if (!IsForwardRefUdt(cvt))1083 return id;1084 1085 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));1086}1087 1088template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {1089 RecordType record;1090 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));1091 return record.getSize();1092}1093 1094size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,1095 llvm::pdb::TpiStream &tpi) {1096 if (id.index.isSimple()) {1097 switch (id.index.getSimpleMode()) {1098 case SimpleTypeMode::Direct:1099 return GetTypeSizeForSimpleKind(id.index.getSimpleKind());1100 case SimpleTypeMode::NearPointer32:1101 case SimpleTypeMode::FarPointer32:1102 return 4;1103 case SimpleTypeMode::NearPointer64:1104 return 8;1105 case SimpleTypeMode::NearPointer128:1106 return 16;1107 default:1108 break;1109 }1110 return 0;1111 }1112 1113 TypeIndex index = id.index;1114 if (IsForwardRefUdt(index, tpi))1115 index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));1116 1117 CVType cvt = tpi.getType(index);1118 switch (cvt.kind()) {1119 case LF_MODIFIER:1120 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);1121 case LF_ENUM: {1122 EnumRecord record;1123 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));1124 return GetSizeOfType({record.UnderlyingType}, tpi);1125 }1126 case LF_POINTER:1127 return GetSizeOfTypeInternal<PointerRecord>(cvt);1128 case LF_ARRAY:1129 return GetSizeOfTypeInternal<ArrayRecord>(cvt);1130 case LF_CLASS:1131 case LF_STRUCTURE:1132 case LF_INTERFACE:1133 return GetSizeOfTypeInternal<ClassRecord>(cvt);1134 case LF_UNION:1135 return GetSizeOfTypeInternal<UnionRecord>(cvt);1136 case LF_BITFIELD: {1137 BitFieldRecord record;1138 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));1139 return GetSizeOfType({record.Type}, tpi);1140 }1141 default:1142 break;1143 }1144 return 0;1145}1146