1 //===-- PdbUtil.cpp -------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "DWARFLocationExpression.h"
13 #include "PdbSymUid.h"
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"
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"
28 using namespace lldb_private
;
29 using namespace lldb_private::npdb
;
30 using namespace llvm::codeview
;
31 using namespace llvm::pdb
;
33 // The returned range list is guaranteed to be sorted and no overlaps between
34 // adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
35 static Variable::RangeList
36 MakeRangeList(const PdbIndex
&index
, const LocalVariableAddrRange
&range
,
37 llvm::ArrayRef
<LocalVariableAddrGap
> gaps
) {
39 index
.MakeVirtualAddress(range
.ISectStart
, range
.OffsetStart
);
40 if (start
== LLDB_INVALID_ADDRESS
)
42 lldb::addr_t end
= start
+ range
.Range
;
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();
53 result
.Append(start
, end
- start
);
58 struct MemberLocations
{
59 std::map
<uint64_t, MemberValLocation
> offset_to_location
;
61 bool is_dwarf
= false;
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
);
69 void insert(uint64_t offset
, const MemberValLocation
&member_loc
) {
70 offset_to_location
[offset
] = member_loc
;
75 bool operator()(const MemberLocations
&, const MemberLocations
&) const {
81 // A range map with address ranges to a map of pair of offset and locaitons.
82 typedef RangeDataVector
<lldb::addr_t
, lldb::addr_t
, MemberLocations
, 0,
83 MemberLocations::Comparator
>
86 void 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
);
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
)
104 if (entry
->data
.is_dwarf
)
105 base
= entry
->GetRangeEnd();
107 lldb::addr_t entry_end
= entry
->GetRangeEnd();
108 if (base
> entry
->base
) {
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
);
119 add_overlap_region(entry
->base
, end
, entry
);
120 entry
->ShrinkFront(end
- entry
->base
);
123 if (end
< entry_end
) {
124 new_location_map
.Append({end
, entry_end
, entry
->data
});
125 entry
->SetRangeEnd(end
);
127 entry
->data
.insert(offset
, member_loc
);
135 new_location_map
.Append({base
, end
- base
, {offset
, member_loc
}});
137 for (const auto &entry
: new_location_map
)
138 location_map
.Append(entry
);
139 if (!new_location_map
.IsEmpty())
143 void AddDwarfRange(RangeMap
&location_map
, const DWARFExpression
&expr
,
144 const Variable::RangeList
&ranges
) {
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
);
160 if (end
== entry
->GetRangeEnd())
163 entry
->ShrinkFront(end
- base
);
164 new_location_map
.Append({base
, end
- base
, expr
});
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
);
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
)
181 entry
->ShrinkFront(end
- entry
->base
);
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
});
192 for (const auto &entry
: new_location_map
)
193 location_map
.Append(entry
);
198 CVTagRecord
CVTagRecord::create(CVType type
) {
199 assert(IsTagRecord(type
) && "type is not a tag record!");
200 switch (type
.kind()) {
205 llvm::cantFail(TypeDeserializer::deserializeAs
<ClassRecord
>(type
, cr
));
206 return CVTagRecord(std::move(cr
));
210 llvm::cantFail(TypeDeserializer::deserializeAs
<UnionRecord
>(type
, ur
));
211 return CVTagRecord(std::move(ur
));
215 llvm::cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(type
, er
));
216 return CVTagRecord(std::move(er
));
219 llvm_unreachable("Unreachable!");
223 CVTagRecord::CVTagRecord(ClassRecord
&&c
)
224 : cvclass(std::move(c
)),
225 m_kind(cvclass
.Kind
== TypeRecordKind::Struct
? Struct
: Class
) {}
226 CVTagRecord::CVTagRecord(UnionRecord
&&u
)
227 : cvunion(std::move(u
)), m_kind(Union
) {}
228 CVTagRecord::CVTagRecord(EnumRecord
&&e
) : cvenum(std::move(e
)), m_kind(Enum
) {}
230 PDB_SymType
lldb_private::npdb::CVSymToPDBSym(SymbolKind kind
) {
234 return PDB_SymType::CompilandDetails
;
236 return PDB_SymType::CompilandEnv
;
239 return PDB_SymType::Thunk
;
241 return PDB_SymType::CoffGroup
;
243 return PDB_SymType::Export
;
247 return PDB_SymType::Function
;
249 return PDB_SymType::PublicSymbol
;
251 return PDB_SymType::InlineSite
;
263 return PDB_SymType::Data
;
265 return PDB_SymType::Block
;
267 return PDB_SymType::Label
;
269 return PDB_SymType::CallSite
;
270 case S_HEAPALLOCSITE
:
271 return PDB_SymType::HeapAllocationSite
;
273 return PDB_SymType::Callee
;
275 return PDB_SymType::Caller
;
277 lldbassert(false && "Invalid symbol record kind!");
279 return PDB_SymType::None
;
282 PDB_SymType
lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind
) {
285 return PDB_SymType::ArrayType
;
287 return PDB_SymType::FunctionSig
;
289 return PDB_SymType::BaseClass
;
291 return PDB_SymType::BaseInterface
;
296 return PDB_SymType::UDT
;
298 return PDB_SymType::PointerType
;
300 return PDB_SymType::Enum
;
302 return PDB_SymType::FunctionSig
;
304 return PDB_SymType::BuiltinType
;
306 lldbassert(false && "Invalid type record kind!");
308 return PDB_SymType::None
;
311 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol
&sym
) {
312 switch (sym
.kind()) {
318 case S_LPROC32_DPC_ID
:
325 case S_HEAPALLOCSITE
:
338 bool lldb_private::npdb::SymbolIsCode(const CVSymbol
&sym
) {
339 switch (sym
.kind()) {
345 case S_LPROC32_DPC_ID
:
356 template <typename RecordT
> RecordT
createRecord(const CVSymbol
&sym
) {
357 RecordT
record(static_cast<SymbolRecordKind
>(sym
.kind()));
358 cantFail(SymbolDeserializer::deserializeAs
<RecordT
>(sym
, record
));
362 template <typename RecordT
>
363 static SegmentOffset
GetSegmentAndOffset(const CVSymbol
&sym
) {
364 RecordT record
= createRecord
<RecordT
>(sym
);
365 return {record
.Segment
, record
.CodeOffset
};
369 SegmentOffset GetSegmentAndOffset
<TrampolineSym
>(const CVSymbol
&sym
) {
370 TrampolineSym record
= createRecord
<TrampolineSym
>(sym
);
371 return {record
.ThunkSection
, record
.ThunkOffset
};
374 template <> SegmentOffset GetSegmentAndOffset
<Thunk32Sym
>(const CVSymbol
&sym
) {
375 Thunk32Sym record
= createRecord
<Thunk32Sym
>(sym
);
376 return {record
.Segment
, record
.Offset
};
380 SegmentOffset GetSegmentAndOffset
<CoffGroupSym
>(const CVSymbol
&sym
) {
381 CoffGroupSym record
= createRecord
<CoffGroupSym
>(sym
);
382 return {record
.Segment
, record
.Offset
};
385 template <> SegmentOffset GetSegmentAndOffset
<DataSym
>(const CVSymbol
&sym
) {
386 DataSym record
= createRecord
<DataSym
>(sym
);
387 return {record
.Segment
, record
.DataOffset
};
391 SegmentOffset GetSegmentAndOffset
<ThreadLocalDataSym
>(const CVSymbol
&sym
) {
392 ThreadLocalDataSym record
= createRecord
<ThreadLocalDataSym
>(sym
);
393 return {record
.Segment
, record
.DataOffset
};
396 SegmentOffset
lldb_private::npdb::GetSegmentAndOffset(const CVSymbol
&sym
) {
397 switch (sym
.kind()) {
403 case S_LPROC32_DPC_ID
:
404 return ::GetSegmentAndOffset
<ProcSym
>(sym
);
406 return ::GetSegmentAndOffset
<Thunk32Sym
>(sym
);
409 return ::GetSegmentAndOffset
<TrampolineSym
>(sym
);
412 return ::GetSegmentAndOffset
<CoffGroupSym
>(sym
);
415 return ::GetSegmentAndOffset
<BlockSym
>(sym
);
418 return ::GetSegmentAndOffset
<LabelSym
>(sym
);
421 return ::GetSegmentAndOffset
<CallSiteInfoSym
>(sym
);
423 case S_HEAPALLOCSITE
:
424 return ::GetSegmentAndOffset
<HeapAllocationSiteSym
>(sym
);
430 return ::GetSegmentAndOffset
<DataSym
>(sym
);
434 return ::GetSegmentAndOffset
<ThreadLocalDataSym
>(sym
);
437 lldbassert(false && "Record does not have a segment/offset!");
442 template <typename RecordT
>
443 SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol
&sym
) {
444 RecordT record
= createRecord
<RecordT
>(sym
);
445 return {record
.Segment
, record
.CodeOffset
, record
.CodeSize
};
450 GetSegmentOffsetAndLength
<TrampolineSym
>(const CVSymbol
&sym
) {
451 TrampolineSym record
= createRecord
<TrampolineSym
>(sym
);
452 return {record
.ThunkSection
, record
.ThunkOffset
, record
.Size
};
456 SegmentOffsetLength GetSegmentOffsetAndLength
<Thunk32Sym
>(const CVSymbol
&sym
) {
457 Thunk32Sym record
= createRecord
<Thunk32Sym
>(sym
);
458 return SegmentOffsetLength
{record
.Segment
, record
.Offset
, record
.Length
};
463 GetSegmentOffsetAndLength
<CoffGroupSym
>(const CVSymbol
&sym
) {
464 CoffGroupSym record
= createRecord
<CoffGroupSym
>(sym
);
465 return SegmentOffsetLength
{record
.Segment
, record
.Offset
, record
.Size
};
469 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol
&sym
) {
470 switch (sym
.kind()) {
476 case S_LPROC32_DPC_ID
:
477 return ::GetSegmentOffsetAndLength
<ProcSym
>(sym
);
479 return ::GetSegmentOffsetAndLength
<Thunk32Sym
>(sym
);
482 return ::GetSegmentOffsetAndLength
<TrampolineSym
>(sym
);
485 return ::GetSegmentOffsetAndLength
<CoffGroupSym
>(sym
);
488 return ::GetSegmentOffsetAndLength
<BlockSym
>(sym
);
491 lldbassert(false && "Record does not have a segment/offset/length triple!");
496 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt
) {
500 switch (cvt
.kind()) {
504 llvm::cantFail(TypeDeserializer::deserializeAs
<ClassRecord
>(cvt
, cr
));
505 return cr
.isForwardRef();
507 llvm::cantFail(TypeDeserializer::deserializeAs
<UnionRecord
>(cvt
, ur
));
508 return ur
.isForwardRef();
510 llvm::cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(cvt
, er
));
511 return er
.isForwardRef();
517 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt
) {
518 switch (cvt
.kind()) {
529 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt
) {
530 switch (cvt
.kind()) {
540 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId
&id
,
542 if (id
.is_ipi
|| id
.index
.isSimple())
544 return IsForwardRefUdt(tpi
.getType(id
.index
));
547 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId
&id
, TpiStream
&tpi
) {
548 if (id
.is_ipi
|| id
.index
.isSimple())
550 return IsTagRecord(tpi
.getType(id
.index
));
554 lldb_private::npdb::TranslateMemberAccess(MemberAccess 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
;
565 llvm_unreachable("unreachable");
568 TypeIndex
lldb_private::npdb::GetFieldListIndex(CVType cvt
) {
569 switch (cvt
.kind()) {
574 cantFail(TypeDeserializer::deserializeAs
<ClassRecord
>(cvt
, cr
));
579 cantFail(TypeDeserializer::deserializeAs
<UnionRecord
>(cvt
, ur
));
584 cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(cvt
, er
));
588 llvm_unreachable("Unreachable!");
592 TypeIndex
lldb_private::npdb::LookThroughModifierRecord(CVType modifier
) {
593 lldbassert(modifier
.kind() == LF_MODIFIER
);
595 llvm::cantFail(TypeDeserializer::deserializeAs
<ModifierRecord
>(modifier
, mr
));
596 return mr
.ModifiedType
;
599 llvm::StringRef
lldb_private::npdb::DropNameScope(llvm::StringRef name
) {
600 return MSVCUndecoratedNameParser::DropScope(name
);
603 VariableInfo
lldb_private::npdb::GetVariableNameInfo(CVSymbol sym
) {
604 VariableInfo result
= {};
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
;
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
;
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
;
628 ((local
.Flags
& LocalSymFlags::IsParameter
) != LocalSymFlags::None
);
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
;
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
;
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
;
656 lldbassert(false && "Invalid variable record kind!");
660 static llvm::FixedStreamArray
<FrameData
>::Iterator
661 GetCorrespondingFrameData(lldb::addr_t load_addr
,
662 const DebugFrameDataSubsectionRef
&fpo_data
,
663 const Variable::RangeList
&ranges
) {
664 lldbassert(!ranges
.IsEmpty());
666 // assume that all variable ranges correspond to one frame data
667 using RangeListEntry
= Variable::RangeList::Entry
;
668 const RangeListEntry
&range
= ranges
.GetEntryRef(0);
670 auto it
= fpo_data
.begin();
672 // start by searching first frame data range containing variable range
673 for (; it
!= fpo_data
.end(); ++it
) {
674 RangeListEntry
fd_range(load_addr
+ it
->RvaStart
, it
->CodeSize
);
676 if (fd_range
.Contains(range
)) {
681 // then first most nested entry that still contains variable range
683 for (; it
!= fpo_data
.end(); ++it
) {
684 RangeListEntry
fd_range(load_addr
+ it
->RvaStart
, it
->CodeSize
);
686 if (!fd_range
.Contains(range
)) {
695 static bool GetFrameDataProgram(PdbIndex
&index
,
696 const Variable::RangeList
&ranges
,
697 llvm::StringRef
&out_program
) {
698 const DebugFrameDataSubsectionRef
&new_fpo_data
=
699 index
.dbi().getNewFpoRecords();
702 GetCorrespondingFrameData(index
.GetLoadAddress(), new_fpo_data
, ranges
);
703 if (frame_data_it
== new_fpo_data
.end())
706 auto strings
= index
.pdb().getStringTable();
708 consumeError(strings
.takeError());
711 out_program
= cantFail(strings
->getStringForID(frame_data_it
->FrameFunc
));
715 static RegisterId
GetBaseFrameRegister(PdbIndex
&index
,
716 PdbCompilandSymId frame_proc_id
,
718 CVSymbol frame_proc_cvs
= index
.ReadSymbolRecord(frame_proc_id
);
719 if (frame_proc_cvs
.kind() != S_FRAMEPROC
)
720 return RegisterId::NONE
;
722 FrameProcSym
frame_proc(SymbolRecordKind::FrameProcSym
);
723 cantFail(SymbolDeserializer::deserializeAs
<FrameProcSym
>(frame_proc_cvs
,
726 CPUType cpu_type
= index
.compilands()
727 .GetCompiland(frame_proc_id
.modi
)
728 ->m_compile_opts
->Machine
;
730 return is_parameter
? frame_proc
.getParamFramePtrReg(cpu_type
)
731 : frame_proc
.getLocalFramePtrReg(cpu_type
);
734 VariableInfo
lldb_private::npdb::GetVariableLocationInfo(
735 PdbIndex
&index
, PdbCompilandSymId var_id
, Block
&func_block
,
736 lldb::ModuleSP module
) {
738 CVSymbol sym
= index
.ReadSymbolRecord(var_id
);
740 VariableInfo result
= GetVariableNameInfo(sym
);
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
),
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
),
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
));
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
;
777 // When overlaps happens, always prefer the one that doesn't split the value
778 // into multiple locations and the location parsed first is perfered.
779 RangeMap location_map
;
781 // Iterate through all location records after S_LOCAL. They describe the
782 // value of this variable at different locations.
783 bool finished
= false;
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
));
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());
808 GetBaseFrameRegister(index
, frame_proc_id
, result
.is_param
);
809 if (base_reg
== RegisterId::NONE
)
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
,
822 expr
= MakeRegRelLocationExpression(base_reg
, loc
.Hdr
.Offset
, module
);
823 AddDwarfRange(location_map
, expr
, raw_ranges
);
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
));
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
);
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
));
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
);
863 expr
= MakeRegRelLocationExpression(reg_id
, loc
.Hdr
.BasePointerOffset
,
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
);
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
));
881 Variable::RangeList ranges
= MakeRangeList(index
, loc
.Range
, loc
.Gaps
);
883 GetRegisterSize((RegisterId
)(uint16_t)loc
.Hdr
.Register
);
886 offset_to_size
[loc
.Hdr
.OffsetInParent
] = reg_size
;
887 AddMemberLocationRanges(location_map
, loc
.Hdr
.OffsetInParent
,
888 {loc
.Hdr
.Register
, 0, true}, ranges
);
891 // FIXME: Handle other kinds. LLVM only generates the 4 types of records
892 // above. MSVC generates other location types.
894 case S_DEFRANGE_SUBFIELD
:
895 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
901 loc_specifier_id
= PdbCompilandSymId(
902 loc_specifier_id
.modi
,
903 loc_specifier_id
.offset
+ loc_specifier_cvs
.RecordData
.size());
905 for (const auto &entry
: location_map
) {
906 DWARFExpression dwarf_expr
=
907 entry
.data
.is_dwarf
? entry
.data
.expr
908 : MakeEnregisteredLocationExpressionForComposite(
909 entry
.data
.offset_to_location
,
910 offset_to_size
, type_size
, module
);
912 result
.location
.AddExpression(entry
.GetRangeBase(), entry
.GetRangeEnd(),
917 llvm_unreachable("Symbol is not a local variable!");
922 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind 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 return lldb::eBasicTypeFloatComplex
;
950 case SimpleTypeKind::Float128
:
951 case SimpleTypeKind::Float80
:
952 return lldb::eBasicTypeLongDouble
;
953 case SimpleTypeKind::Float64
:
954 return lldb::eBasicTypeDouble
;
955 case SimpleTypeKind::Float32
:
956 return lldb::eBasicTypeFloat
;
957 case SimpleTypeKind::Float16
:
958 return lldb::eBasicTypeHalf
;
959 case SimpleTypeKind::Int128
:
960 return lldb::eBasicTypeInt128
;
961 case SimpleTypeKind::Int64
:
962 case SimpleTypeKind::Int64Quad
:
963 return lldb::eBasicTypeLongLong
;
964 case SimpleTypeKind::Int32
:
965 return lldb::eBasicTypeInt
;
966 case SimpleTypeKind::Int16
:
967 case SimpleTypeKind::Int16Short
:
968 return lldb::eBasicTypeShort
;
969 case SimpleTypeKind::UInt128
:
970 return lldb::eBasicTypeUnsignedInt128
;
971 case SimpleTypeKind::UInt64
:
972 case SimpleTypeKind::UInt64Quad
:
973 return lldb::eBasicTypeUnsignedLongLong
;
974 case SimpleTypeKind::HResult
:
975 case SimpleTypeKind::UInt32
:
976 return lldb::eBasicTypeUnsignedInt
;
977 case SimpleTypeKind::UInt16
:
978 case SimpleTypeKind::UInt16Short
:
979 return lldb::eBasicTypeUnsignedShort
;
980 case SimpleTypeKind::Int32Long
:
981 return lldb::eBasicTypeLong
;
982 case SimpleTypeKind::UInt32Long
:
983 return lldb::eBasicTypeUnsignedLong
;
984 case SimpleTypeKind::Void
:
985 return lldb::eBasicTypeVoid
;
986 case SimpleTypeKind::WideCharacter
:
987 return lldb::eBasicTypeWChar
;
989 return lldb::eBasicTypeInvalid
;
993 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind
) {
995 case SimpleTypeKind::Boolean128
:
996 case SimpleTypeKind::Int128
:
997 case SimpleTypeKind::UInt128
:
998 case SimpleTypeKind::Float128
:
1000 case SimpleTypeKind::Complex80
:
1001 case SimpleTypeKind::Float80
:
1003 case SimpleTypeKind::Boolean64
:
1004 case SimpleTypeKind::Complex64
:
1005 case SimpleTypeKind::UInt64
:
1006 case SimpleTypeKind::UInt64Quad
:
1007 case SimpleTypeKind::Float64
:
1008 case SimpleTypeKind::Int64
:
1009 case SimpleTypeKind::Int64Quad
:
1011 case SimpleTypeKind::Boolean32
:
1012 case SimpleTypeKind::Character32
:
1013 case SimpleTypeKind::Complex32
:
1014 case SimpleTypeKind::Float32
:
1015 case SimpleTypeKind::Int32
:
1016 case SimpleTypeKind::Int32Long
:
1017 case SimpleTypeKind::UInt32Long
:
1018 case SimpleTypeKind::HResult
:
1019 case SimpleTypeKind::UInt32
:
1021 case SimpleTypeKind::Boolean16
:
1022 case SimpleTypeKind::Character16
:
1023 case SimpleTypeKind::Float16
:
1024 case SimpleTypeKind::Int16
:
1025 case SimpleTypeKind::Int16Short
:
1026 case SimpleTypeKind::UInt16
:
1027 case SimpleTypeKind::UInt16Short
:
1028 case SimpleTypeKind::WideCharacter
:
1030 case SimpleTypeKind::Boolean8
:
1031 case SimpleTypeKind::Byte
:
1032 case SimpleTypeKind::UnsignedCharacter
:
1033 case SimpleTypeKind::NarrowCharacter
:
1034 case SimpleTypeKind::SignedCharacter
:
1035 case SimpleTypeKind::SByte
:
1036 case SimpleTypeKind::Character8
:
1038 case SimpleTypeKind::Void
:
1044 PdbTypeSymId
lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id
,
1046 if (id
.index
.isSimple())
1049 CVType cvt
= tpi
.getType(id
.index
);
1051 // Only tag records have a best and a worst record.
1052 if (!IsTagRecord(cvt
))
1055 // Tag records that are not forward decls are full decls, hence they are the
1057 if (!IsForwardRefUdt(cvt
))
1060 return llvm::cantFail(tpi
.findFullDeclForForwardRef(id
.index
));
1063 template <typename RecordType
> static size_t GetSizeOfTypeInternal(CVType cvt
) {
1065 llvm::cantFail(TypeDeserializer::deserializeAs
<RecordType
>(cvt
, record
));
1066 return record
.getSize();
1069 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id
,
1070 llvm::pdb::TpiStream
&tpi
) {
1071 if (id
.index
.isSimple()) {
1072 switch (id
.index
.getSimpleMode()) {
1073 case SimpleTypeMode::Direct
:
1074 return GetTypeSizeForSimpleKind(id
.index
.getSimpleKind());
1075 case SimpleTypeMode::NearPointer32
:
1076 case SimpleTypeMode::FarPointer32
:
1078 case SimpleTypeMode::NearPointer64
:
1080 case SimpleTypeMode::NearPointer128
:
1088 TypeIndex index
= id
.index
;
1089 if (IsForwardRefUdt(index
, tpi
))
1090 index
= llvm::cantFail(tpi
.findFullDeclForForwardRef(index
));
1092 CVType cvt
= tpi
.getType(index
);
1093 switch (cvt
.kind()) {
1095 return GetSizeOfType({LookThroughModifierRecord(cvt
)}, tpi
);
1098 llvm::cantFail(TypeDeserializer::deserializeAs
<EnumRecord
>(cvt
, record
));
1099 return GetSizeOfType({record
.UnderlyingType
}, tpi
);
1102 return GetSizeOfTypeInternal
<PointerRecord
>(cvt
);
1104 return GetSizeOfTypeInternal
<ArrayRecord
>(cvt
);
1108 return GetSizeOfTypeInternal
<ClassRecord
>(cvt
);
1110 return GetSizeOfTypeInternal
<UnionRecord
>(cvt
);
1112 BitFieldRecord record
;
1113 llvm::cantFail(TypeDeserializer::deserializeAs
<BitFieldRecord
>(cvt
, record
));
1114 return GetSizeOfType({record
.Type
}, tpi
);