1dda28197Spatrick //===-- PdbUtil.cpp -------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "PdbUtil.h"
10061da546Spatrick
11061da546Spatrick #include "DWARFLocationExpression.h"
12061da546Spatrick #include "PdbIndex.h"
13061da546Spatrick #include "PdbSymUid.h"
14061da546Spatrick
15*f6aab3d8Srobert #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16061da546Spatrick #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17061da546Spatrick #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18061da546Spatrick #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
19061da546Spatrick #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20061da546Spatrick
21061da546Spatrick #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22*f6aab3d8Srobert #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
23061da546Spatrick #include "lldb/Symbol/Block.h"
24061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
25*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
26061da546Spatrick #include "lldb/lldb-enumerations.h"
27061da546Spatrick
28061da546Spatrick using namespace lldb_private;
29061da546Spatrick using namespace lldb_private::npdb;
30061da546Spatrick using namespace llvm::codeview;
31061da546Spatrick using namespace llvm::pdb;
32061da546Spatrick
33*f6aab3d8Srobert // The returned range list is guaranteed to be sorted and no overlaps between
34*f6aab3d8Srobert // adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
35061da546Spatrick static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)36061da546Spatrick MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
37061da546Spatrick llvm::ArrayRef<LocalVariableAddrGap> gaps) {
38061da546Spatrick lldb::addr_t start =
39061da546Spatrick index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
40*f6aab3d8Srobert if (start == LLDB_INVALID_ADDRESS)
41*f6aab3d8Srobert return {};
42061da546Spatrick lldb::addr_t end = start + range.Range;
43061da546Spatrick
44061da546Spatrick Variable::RangeList result;
45061da546Spatrick while (!gaps.empty()) {
46061da546Spatrick const LocalVariableAddrGap &gap = gaps.front();
47*f6aab3d8Srobert lldb::addr_t gap_start = start + gap.GapStartOffset;
48*f6aab3d8Srobert result.Append(start, gap_start - start);
49*f6aab3d8Srobert start = gap_start + gap.Range;
50061da546Spatrick gaps = gaps.drop_front();
51061da546Spatrick }
52061da546Spatrick
53061da546Spatrick result.Append(start, end - start);
54061da546Spatrick return result;
55061da546Spatrick }
56061da546Spatrick
57*f6aab3d8Srobert namespace {
58*f6aab3d8Srobert struct MemberLocations {
59*f6aab3d8Srobert std::map<uint64_t, MemberValLocation> offset_to_location;
60*f6aab3d8Srobert DWARFExpression expr;
61*f6aab3d8Srobert bool is_dwarf = false;
62*f6aab3d8Srobert
63*f6aab3d8Srobert MemberLocations() = default;
MemberLocations__anond275737a0111::MemberLocations64*f6aab3d8Srobert MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
MemberLocations__anond275737a0111::MemberLocations65*f6aab3d8Srobert MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
66*f6aab3d8Srobert insert(offset, member_loc);
67*f6aab3d8Srobert }
68*f6aab3d8Srobert
insert__anond275737a0111::MemberLocations69*f6aab3d8Srobert void insert(uint64_t offset, const MemberValLocation &member_loc) {
70*f6aab3d8Srobert offset_to_location[offset] = member_loc;
71*f6aab3d8Srobert }
72*f6aab3d8Srobert
73*f6aab3d8Srobert struct Comparator {
74*f6aab3d8Srobert public:
operator ()__anond275737a0111::MemberLocations::Comparator75*f6aab3d8Srobert bool operator()(const MemberLocations &, const MemberLocations &) const {
76*f6aab3d8Srobert return false;
77*f6aab3d8Srobert }
78*f6aab3d8Srobert };
79*f6aab3d8Srobert };
80*f6aab3d8Srobert
81*f6aab3d8Srobert // A range map with address ranges to a map of pair of offset and locaitons.
82*f6aab3d8Srobert typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
83*f6aab3d8Srobert MemberLocations::Comparator>
84*f6aab3d8Srobert RangeMap;
85*f6aab3d8Srobert
AddMemberLocationRanges(RangeMap & location_map,uint64_t offset,MemberValLocation member_loc,const Variable::RangeList & ranges)86*f6aab3d8Srobert void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
87*f6aab3d8Srobert MemberValLocation member_loc,
88*f6aab3d8Srobert const Variable::RangeList &ranges) {
89*f6aab3d8Srobert RangeMap new_location_map;
90*f6aab3d8Srobert auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
91*f6aab3d8Srobert RangeMap::Entry *entry) {
92*f6aab3d8Srobert RangeMap::Entry overlap_region = {base, end - base, entry->data};
93*f6aab3d8Srobert overlap_region.data.insert(offset, member_loc);
94*f6aab3d8Srobert new_location_map.Append(overlap_region);
95*f6aab3d8Srobert };
96*f6aab3d8Srobert
97*f6aab3d8Srobert for (const auto &range : ranges) {
98*f6aab3d8Srobert lldb::addr_t base = range.GetRangeBase();
99*f6aab3d8Srobert lldb::addr_t end = range.GetRangeEnd();
100*f6aab3d8Srobert uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
101*f6aab3d8Srobert while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
102*f6aab3d8Srobert if (base >= end || entry->base >= end)
103*f6aab3d8Srobert break;
104*f6aab3d8Srobert if (entry->data.is_dwarf)
105*f6aab3d8Srobert base = entry->GetRangeEnd();
106*f6aab3d8Srobert else {
107*f6aab3d8Srobert lldb::addr_t entry_end = entry->GetRangeEnd();
108*f6aab3d8Srobert if (base > entry->base) {
109*f6aab3d8Srobert if (end < entry_end)
110*f6aab3d8Srobert new_location_map.Append({end, entry_end - end, entry->data});
111*f6aab3d8Srobert add_overlap_region(base, end < entry_end ? end : entry_end, entry);
112*f6aab3d8Srobert entry->SetRangeEnd(base);
113*f6aab3d8Srobert } else if (base < entry->base) {
114*f6aab3d8Srobert new_location_map.Append(
115*f6aab3d8Srobert {base, entry->base - base, {offset, member_loc}});
116*f6aab3d8Srobert if (entry_end == end)
117*f6aab3d8Srobert entry->data.insert(offset, member_loc);
118*f6aab3d8Srobert else {
119*f6aab3d8Srobert add_overlap_region(entry->base, end, entry);
120*f6aab3d8Srobert entry->ShrinkFront(end - entry->base);
121*f6aab3d8Srobert }
122*f6aab3d8Srobert } else {
123*f6aab3d8Srobert if (end < entry_end) {
124*f6aab3d8Srobert new_location_map.Append({end, entry_end, entry->data});
125*f6aab3d8Srobert entry->SetRangeEnd(end);
126*f6aab3d8Srobert }
127*f6aab3d8Srobert entry->data.insert(offset, member_loc);
128*f6aab3d8Srobert }
129*f6aab3d8Srobert base = entry_end;
130*f6aab3d8Srobert }
131*f6aab3d8Srobert ++base_idx;
132*f6aab3d8Srobert }
133*f6aab3d8Srobert if (base >= end)
134*f6aab3d8Srobert continue;
135*f6aab3d8Srobert new_location_map.Append({base, end - base, {offset, member_loc}});
136*f6aab3d8Srobert }
137*f6aab3d8Srobert for (const auto &entry : new_location_map)
138*f6aab3d8Srobert location_map.Append(entry);
139*f6aab3d8Srobert if (!new_location_map.IsEmpty())
140*f6aab3d8Srobert location_map.Sort();
141*f6aab3d8Srobert }
142*f6aab3d8Srobert
AddDwarfRange(RangeMap & location_map,const DWARFExpression & expr,const Variable::RangeList & ranges)143*f6aab3d8Srobert void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
144*f6aab3d8Srobert const Variable::RangeList &ranges) {
145*f6aab3d8Srobert if (!expr.IsValid())
146*f6aab3d8Srobert return;
147*f6aab3d8Srobert RangeMap new_location_map;
148*f6aab3d8Srobert for (const auto &range : ranges) {
149*f6aab3d8Srobert lldb::addr_t base = range.GetRangeBase();
150*f6aab3d8Srobert lldb::addr_t end = range.GetRangeEnd();
151*f6aab3d8Srobert uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
152*f6aab3d8Srobert uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
153*f6aab3d8Srobert // range is within an entry.
154*f6aab3d8Srobert if (base_idx == end_idx && base_idx != UINT32_MAX) {
155*f6aab3d8Srobert auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
156*f6aab3d8Srobert if (base > entry->base) {
157*f6aab3d8Srobert new_location_map.Append({entry->base, base - entry->base, entry->data});
158*f6aab3d8Srobert entry->ShrinkFront(base - entry->base);
159*f6aab3d8Srobert }
160*f6aab3d8Srobert if (end == entry->GetRangeEnd())
161*f6aab3d8Srobert entry->data = expr;
162*f6aab3d8Srobert else {
163*f6aab3d8Srobert entry->ShrinkFront(end - base);
164*f6aab3d8Srobert new_location_map.Append({base, end - base, expr});
165*f6aab3d8Srobert }
166*f6aab3d8Srobert continue;
167*f6aab3d8Srobert }
168*f6aab3d8Srobert base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
169*f6aab3d8Srobert if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
170*f6aab3d8Srobert if (entry->Contains(base) && entry->base != base) {
171*f6aab3d8Srobert entry->SetRangeEnd(base);
172*f6aab3d8Srobert ++base_idx;
173*f6aab3d8Srobert }
174*f6aab3d8Srobert }
175*f6aab3d8Srobert end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
176*f6aab3d8Srobert if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
177*f6aab3d8Srobert if (entry->Contains(end - 1)) {
178*f6aab3d8Srobert if (entry->GetRangeEnd() == end)
179*f6aab3d8Srobert ++end_idx;
180*f6aab3d8Srobert else
181*f6aab3d8Srobert entry->ShrinkFront(end - entry->base);
182*f6aab3d8Srobert }
183*f6aab3d8Srobert }
184*f6aab3d8Srobert
185*f6aab3d8Srobert if (end_idx == UINT32_MAX)
186*f6aab3d8Srobert end_idx = location_map.GetSize();
187*f6aab3d8Srobert // Erase existing ranges covered by new range.
188*f6aab3d8Srobert location_map.Erase(base_idx, end_idx);
189*f6aab3d8Srobert new_location_map.Append({base, end - base, expr});
190*f6aab3d8Srobert }
191*f6aab3d8Srobert
192*f6aab3d8Srobert for (const auto &entry : new_location_map)
193*f6aab3d8Srobert location_map.Append(entry);
194*f6aab3d8Srobert location_map.Sort();
195*f6aab3d8Srobert }
196*f6aab3d8Srobert } // namespace
197*f6aab3d8Srobert
create(CVType type)198061da546Spatrick CVTagRecord CVTagRecord::create(CVType type) {
199061da546Spatrick assert(IsTagRecord(type) && "type is not a tag record!");
200061da546Spatrick switch (type.kind()) {
201061da546Spatrick case LF_CLASS:
202061da546Spatrick case LF_STRUCTURE:
203061da546Spatrick case LF_INTERFACE: {
204061da546Spatrick ClassRecord cr;
205061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
206061da546Spatrick return CVTagRecord(std::move(cr));
207061da546Spatrick }
208061da546Spatrick case LF_UNION: {
209061da546Spatrick UnionRecord ur;
210061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
211061da546Spatrick return CVTagRecord(std::move(ur));
212061da546Spatrick }
213061da546Spatrick case LF_ENUM: {
214061da546Spatrick EnumRecord er;
215061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
216061da546Spatrick return CVTagRecord(std::move(er));
217061da546Spatrick }
218061da546Spatrick default:
219061da546Spatrick llvm_unreachable("Unreachable!");
220061da546Spatrick }
221061da546Spatrick }
222061da546Spatrick
CVTagRecord(ClassRecord && c)223061da546Spatrick CVTagRecord::CVTagRecord(ClassRecord &&c)
224061da546Spatrick : cvclass(std::move(c)),
225061da546Spatrick m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)226061da546Spatrick CVTagRecord::CVTagRecord(UnionRecord &&u)
227061da546Spatrick : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)228061da546Spatrick CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
229061da546Spatrick
CVSymToPDBSym(SymbolKind kind)230061da546Spatrick PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
231061da546Spatrick switch (kind) {
232061da546Spatrick case S_COMPILE3:
233061da546Spatrick case S_OBJNAME:
234061da546Spatrick return PDB_SymType::CompilandDetails;
235061da546Spatrick case S_ENVBLOCK:
236061da546Spatrick return PDB_SymType::CompilandEnv;
237061da546Spatrick case S_THUNK32:
238061da546Spatrick case S_TRAMPOLINE:
239061da546Spatrick return PDB_SymType::Thunk;
240061da546Spatrick case S_COFFGROUP:
241061da546Spatrick return PDB_SymType::CoffGroup;
242061da546Spatrick case S_EXPORT:
243061da546Spatrick return PDB_SymType::Export;
244061da546Spatrick case S_LPROC32:
245061da546Spatrick case S_GPROC32:
246061da546Spatrick case S_LPROC32_DPC:
247061da546Spatrick return PDB_SymType::Function;
248061da546Spatrick case S_PUB32:
249061da546Spatrick return PDB_SymType::PublicSymbol;
250061da546Spatrick case S_INLINESITE:
251061da546Spatrick return PDB_SymType::InlineSite;
252061da546Spatrick case S_LOCAL:
253061da546Spatrick case S_BPREL32:
254061da546Spatrick case S_REGREL32:
255061da546Spatrick case S_MANCONSTANT:
256061da546Spatrick case S_CONSTANT:
257061da546Spatrick case S_LDATA32:
258061da546Spatrick case S_GDATA32:
259061da546Spatrick case S_LMANDATA:
260061da546Spatrick case S_GMANDATA:
261061da546Spatrick case S_LTHREAD32:
262061da546Spatrick case S_GTHREAD32:
263061da546Spatrick return PDB_SymType::Data;
264061da546Spatrick case S_BLOCK32:
265061da546Spatrick return PDB_SymType::Block;
266061da546Spatrick case S_LABEL32:
267061da546Spatrick return PDB_SymType::Label;
268061da546Spatrick case S_CALLSITEINFO:
269061da546Spatrick return PDB_SymType::CallSite;
270061da546Spatrick case S_HEAPALLOCSITE:
271061da546Spatrick return PDB_SymType::HeapAllocationSite;
272061da546Spatrick case S_CALLEES:
273061da546Spatrick return PDB_SymType::Callee;
274061da546Spatrick case S_CALLERS:
275061da546Spatrick return PDB_SymType::Caller;
276061da546Spatrick default:
277061da546Spatrick lldbassert(false && "Invalid symbol record kind!");
278061da546Spatrick }
279061da546Spatrick return PDB_SymType::None;
280061da546Spatrick }
281061da546Spatrick
CVTypeToPDBType(TypeLeafKind kind)282061da546Spatrick PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
283061da546Spatrick switch (kind) {
284061da546Spatrick case LF_ARRAY:
285061da546Spatrick return PDB_SymType::ArrayType;
286061da546Spatrick case LF_ARGLIST:
287061da546Spatrick return PDB_SymType::FunctionSig;
288061da546Spatrick case LF_BCLASS:
289061da546Spatrick return PDB_SymType::BaseClass;
290061da546Spatrick case LF_BINTERFACE:
291061da546Spatrick return PDB_SymType::BaseInterface;
292061da546Spatrick case LF_CLASS:
293061da546Spatrick case LF_STRUCTURE:
294061da546Spatrick case LF_INTERFACE:
295061da546Spatrick case LF_UNION:
296061da546Spatrick return PDB_SymType::UDT;
297061da546Spatrick case LF_POINTER:
298061da546Spatrick return PDB_SymType::PointerType;
299061da546Spatrick case LF_ENUM:
300061da546Spatrick return PDB_SymType::Enum;
301061da546Spatrick case LF_PROCEDURE:
302061da546Spatrick return PDB_SymType::FunctionSig;
303061da546Spatrick case LF_BITFIELD:
304061da546Spatrick return PDB_SymType::BuiltinType;
305061da546Spatrick default:
306061da546Spatrick lldbassert(false && "Invalid type record kind!");
307061da546Spatrick }
308061da546Spatrick return PDB_SymType::None;
309061da546Spatrick }
310061da546Spatrick
SymbolHasAddress(const CVSymbol & sym)311061da546Spatrick bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
312061da546Spatrick switch (sym.kind()) {
313061da546Spatrick case S_GPROC32:
314061da546Spatrick case S_LPROC32:
315061da546Spatrick case S_GPROC32_ID:
316061da546Spatrick case S_LPROC32_ID:
317061da546Spatrick case S_LPROC32_DPC:
318061da546Spatrick case S_LPROC32_DPC_ID:
319061da546Spatrick case S_THUNK32:
320061da546Spatrick case S_TRAMPOLINE:
321061da546Spatrick case S_COFFGROUP:
322061da546Spatrick case S_BLOCK32:
323061da546Spatrick case S_LABEL32:
324061da546Spatrick case S_CALLSITEINFO:
325061da546Spatrick case S_HEAPALLOCSITE:
326061da546Spatrick case S_LDATA32:
327061da546Spatrick case S_GDATA32:
328061da546Spatrick case S_LMANDATA:
329061da546Spatrick case S_GMANDATA:
330061da546Spatrick case S_LTHREAD32:
331061da546Spatrick case S_GTHREAD32:
332061da546Spatrick return true;
333061da546Spatrick default:
334061da546Spatrick return false;
335061da546Spatrick }
336061da546Spatrick }
337061da546Spatrick
SymbolIsCode(const CVSymbol & sym)338061da546Spatrick bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
339061da546Spatrick switch (sym.kind()) {
340061da546Spatrick case S_GPROC32:
341061da546Spatrick case S_LPROC32:
342061da546Spatrick case S_GPROC32_ID:
343061da546Spatrick case S_LPROC32_ID:
344061da546Spatrick case S_LPROC32_DPC:
345061da546Spatrick case S_LPROC32_DPC_ID:
346061da546Spatrick case S_THUNK32:
347061da546Spatrick case S_TRAMPOLINE:
348061da546Spatrick case S_COFFGROUP:
349061da546Spatrick case S_BLOCK32:
350061da546Spatrick return true;
351061da546Spatrick default:
352061da546Spatrick return false;
353061da546Spatrick }
354061da546Spatrick }
355061da546Spatrick
createRecord(const CVSymbol & sym)356061da546Spatrick template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
357061da546Spatrick RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
358061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
359061da546Spatrick return record;
360061da546Spatrick }
361061da546Spatrick
362061da546Spatrick template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)363061da546Spatrick static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
364061da546Spatrick RecordT record = createRecord<RecordT>(sym);
365061da546Spatrick return {record.Segment, record.CodeOffset};
366061da546Spatrick }
367061da546Spatrick
368061da546Spatrick template <>
GetSegmentAndOffset(const CVSymbol & sym)369061da546Spatrick SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
370061da546Spatrick TrampolineSym record = createRecord<TrampolineSym>(sym);
371061da546Spatrick return {record.ThunkSection, record.ThunkOffset};
372061da546Spatrick }
373061da546Spatrick
GetSegmentAndOffset(const CVSymbol & sym)374061da546Spatrick template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
375061da546Spatrick Thunk32Sym record = createRecord<Thunk32Sym>(sym);
376061da546Spatrick return {record.Segment, record.Offset};
377061da546Spatrick }
378061da546Spatrick
379061da546Spatrick template <>
GetSegmentAndOffset(const CVSymbol & sym)380061da546Spatrick SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
381061da546Spatrick CoffGroupSym record = createRecord<CoffGroupSym>(sym);
382061da546Spatrick return {record.Segment, record.Offset};
383061da546Spatrick }
384061da546Spatrick
GetSegmentAndOffset(const CVSymbol & sym)385061da546Spatrick template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
386061da546Spatrick DataSym record = createRecord<DataSym>(sym);
387061da546Spatrick return {record.Segment, record.DataOffset};
388061da546Spatrick }
389061da546Spatrick
390061da546Spatrick template <>
GetSegmentAndOffset(const CVSymbol & sym)391061da546Spatrick SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
392061da546Spatrick ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
393061da546Spatrick return {record.Segment, record.DataOffset};
394061da546Spatrick }
395061da546Spatrick
GetSegmentAndOffset(const CVSymbol & sym)396061da546Spatrick SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
397061da546Spatrick switch (sym.kind()) {
398061da546Spatrick case S_GPROC32:
399061da546Spatrick case S_LPROC32:
400061da546Spatrick case S_GPROC32_ID:
401061da546Spatrick case S_LPROC32_ID:
402061da546Spatrick case S_LPROC32_DPC:
403061da546Spatrick case S_LPROC32_DPC_ID:
404061da546Spatrick return ::GetSegmentAndOffset<ProcSym>(sym);
405061da546Spatrick case S_THUNK32:
406061da546Spatrick return ::GetSegmentAndOffset<Thunk32Sym>(sym);
407061da546Spatrick break;
408061da546Spatrick case S_TRAMPOLINE:
409061da546Spatrick return ::GetSegmentAndOffset<TrampolineSym>(sym);
410061da546Spatrick break;
411061da546Spatrick case S_COFFGROUP:
412061da546Spatrick return ::GetSegmentAndOffset<CoffGroupSym>(sym);
413061da546Spatrick break;
414061da546Spatrick case S_BLOCK32:
415061da546Spatrick return ::GetSegmentAndOffset<BlockSym>(sym);
416061da546Spatrick break;
417061da546Spatrick case S_LABEL32:
418061da546Spatrick return ::GetSegmentAndOffset<LabelSym>(sym);
419061da546Spatrick break;
420061da546Spatrick case S_CALLSITEINFO:
421061da546Spatrick return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
422061da546Spatrick break;
423061da546Spatrick case S_HEAPALLOCSITE:
424061da546Spatrick return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
425061da546Spatrick break;
426061da546Spatrick case S_LDATA32:
427061da546Spatrick case S_GDATA32:
428061da546Spatrick case S_LMANDATA:
429061da546Spatrick case S_GMANDATA:
430061da546Spatrick return ::GetSegmentAndOffset<DataSym>(sym);
431061da546Spatrick break;
432061da546Spatrick case S_LTHREAD32:
433061da546Spatrick case S_GTHREAD32:
434061da546Spatrick return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
435061da546Spatrick break;
436061da546Spatrick default:
437061da546Spatrick lldbassert(false && "Record does not have a segment/offset!");
438061da546Spatrick }
439061da546Spatrick return {0, 0};
440061da546Spatrick }
441061da546Spatrick
442061da546Spatrick template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)443061da546Spatrick SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
444061da546Spatrick RecordT record = createRecord<RecordT>(sym);
445061da546Spatrick return {record.Segment, record.CodeOffset, record.CodeSize};
446061da546Spatrick }
447061da546Spatrick
448061da546Spatrick template <>
449061da546Spatrick SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)450061da546Spatrick GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
451061da546Spatrick TrampolineSym record = createRecord<TrampolineSym>(sym);
452061da546Spatrick return {record.ThunkSection, record.ThunkOffset, record.Size};
453061da546Spatrick }
454061da546Spatrick
455061da546Spatrick template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)456061da546Spatrick SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
457061da546Spatrick Thunk32Sym record = createRecord<Thunk32Sym>(sym);
458061da546Spatrick return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
459061da546Spatrick }
460061da546Spatrick
461061da546Spatrick template <>
462061da546Spatrick SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)463061da546Spatrick GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
464061da546Spatrick CoffGroupSym record = createRecord<CoffGroupSym>(sym);
465061da546Spatrick return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
466061da546Spatrick }
467061da546Spatrick
468061da546Spatrick SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)469061da546Spatrick lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
470061da546Spatrick switch (sym.kind()) {
471061da546Spatrick case S_GPROC32:
472061da546Spatrick case S_LPROC32:
473061da546Spatrick case S_GPROC32_ID:
474061da546Spatrick case S_LPROC32_ID:
475061da546Spatrick case S_LPROC32_DPC:
476061da546Spatrick case S_LPROC32_DPC_ID:
477061da546Spatrick return ::GetSegmentOffsetAndLength<ProcSym>(sym);
478061da546Spatrick case S_THUNK32:
479061da546Spatrick return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
480061da546Spatrick break;
481061da546Spatrick case S_TRAMPOLINE:
482061da546Spatrick return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
483061da546Spatrick break;
484061da546Spatrick case S_COFFGROUP:
485061da546Spatrick return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
486061da546Spatrick break;
487061da546Spatrick case S_BLOCK32:
488061da546Spatrick return ::GetSegmentOffsetAndLength<BlockSym>(sym);
489061da546Spatrick break;
490061da546Spatrick default:
491061da546Spatrick lldbassert(false && "Record does not have a segment/offset/length triple!");
492061da546Spatrick }
493061da546Spatrick return {0, 0, 0};
494061da546Spatrick }
495061da546Spatrick
IsForwardRefUdt(CVType cvt)496061da546Spatrick bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
497061da546Spatrick ClassRecord cr;
498061da546Spatrick UnionRecord ur;
499061da546Spatrick EnumRecord er;
500061da546Spatrick switch (cvt.kind()) {
501061da546Spatrick case LF_CLASS:
502061da546Spatrick case LF_STRUCTURE:
503061da546Spatrick case LF_INTERFACE:
504061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
505061da546Spatrick return cr.isForwardRef();
506061da546Spatrick case LF_UNION:
507061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
508061da546Spatrick return ur.isForwardRef();
509061da546Spatrick case LF_ENUM:
510061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
511061da546Spatrick return er.isForwardRef();
512061da546Spatrick default:
513061da546Spatrick return false;
514061da546Spatrick }
515061da546Spatrick }
516061da546Spatrick
IsTagRecord(llvm::codeview::CVType cvt)517061da546Spatrick bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
518061da546Spatrick switch (cvt.kind()) {
519061da546Spatrick case LF_CLASS:
520061da546Spatrick case LF_STRUCTURE:
521061da546Spatrick case LF_UNION:
522061da546Spatrick case LF_ENUM:
523061da546Spatrick return true;
524061da546Spatrick default:
525061da546Spatrick return false;
526061da546Spatrick }
527061da546Spatrick }
528061da546Spatrick
IsClassStructUnion(llvm::codeview::CVType cvt)529061da546Spatrick bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
530061da546Spatrick switch (cvt.kind()) {
531061da546Spatrick case LF_CLASS:
532061da546Spatrick case LF_STRUCTURE:
533061da546Spatrick case LF_UNION:
534061da546Spatrick return true;
535061da546Spatrick default:
536061da546Spatrick return false;
537061da546Spatrick }
538061da546Spatrick }
539061da546Spatrick
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)540061da546Spatrick bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
541061da546Spatrick TpiStream &tpi) {
542061da546Spatrick if (id.is_ipi || id.index.isSimple())
543061da546Spatrick return false;
544061da546Spatrick return IsForwardRefUdt(tpi.getType(id.index));
545061da546Spatrick }
546061da546Spatrick
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)547061da546Spatrick bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
548061da546Spatrick if (id.is_ipi || id.index.isSimple())
549061da546Spatrick return false;
550061da546Spatrick return IsTagRecord(tpi.getType(id.index));
551061da546Spatrick }
552061da546Spatrick
553061da546Spatrick lldb::AccessType
TranslateMemberAccess(MemberAccess access)554061da546Spatrick lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
555061da546Spatrick switch (access) {
556061da546Spatrick case MemberAccess::Private:
557061da546Spatrick return lldb::eAccessPrivate;
558061da546Spatrick case MemberAccess::Protected:
559061da546Spatrick return lldb::eAccessProtected;
560061da546Spatrick case MemberAccess::Public:
561061da546Spatrick return lldb::eAccessPublic;
562061da546Spatrick case MemberAccess::None:
563061da546Spatrick return lldb::eAccessNone;
564061da546Spatrick }
565061da546Spatrick llvm_unreachable("unreachable");
566061da546Spatrick }
567061da546Spatrick
GetFieldListIndex(CVType cvt)568061da546Spatrick TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
569061da546Spatrick switch (cvt.kind()) {
570061da546Spatrick case LF_CLASS:
571061da546Spatrick case LF_STRUCTURE:
572061da546Spatrick case LF_INTERFACE: {
573061da546Spatrick ClassRecord cr;
574061da546Spatrick cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
575061da546Spatrick return cr.FieldList;
576061da546Spatrick }
577061da546Spatrick case LF_UNION: {
578061da546Spatrick UnionRecord ur;
579061da546Spatrick cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
580061da546Spatrick return ur.FieldList;
581061da546Spatrick }
582061da546Spatrick case LF_ENUM: {
583061da546Spatrick EnumRecord er;
584061da546Spatrick cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
585061da546Spatrick return er.FieldList;
586061da546Spatrick }
587061da546Spatrick default:
588061da546Spatrick llvm_unreachable("Unreachable!");
589061da546Spatrick }
590061da546Spatrick }
591061da546Spatrick
LookThroughModifierRecord(CVType modifier)592061da546Spatrick TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
593061da546Spatrick lldbassert(modifier.kind() == LF_MODIFIER);
594061da546Spatrick ModifierRecord mr;
595061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
596061da546Spatrick return mr.ModifiedType;
597061da546Spatrick }
598061da546Spatrick
DropNameScope(llvm::StringRef name)599061da546Spatrick llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
600061da546Spatrick return MSVCUndecoratedNameParser::DropScope(name);
601061da546Spatrick }
602061da546Spatrick
GetVariableNameInfo(CVSymbol sym)603061da546Spatrick VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
604*f6aab3d8Srobert VariableInfo result = {};
605061da546Spatrick
606061da546Spatrick if (sym.kind() == S_REGREL32) {
607061da546Spatrick RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
608061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
609061da546Spatrick result.type = reg.Type;
610061da546Spatrick result.name = reg.Name;
611061da546Spatrick return result;
612061da546Spatrick }
613061da546Spatrick
614061da546Spatrick if (sym.kind() == S_REGISTER) {
615061da546Spatrick RegisterSym reg(SymbolRecordKind::RegisterSym);
616061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
617061da546Spatrick result.type = reg.Index;
618061da546Spatrick result.name = reg.Name;
619061da546Spatrick return result;
620061da546Spatrick }
621061da546Spatrick
622061da546Spatrick if (sym.kind() == S_LOCAL) {
623061da546Spatrick LocalSym local(SymbolRecordKind::LocalSym);
624061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
625061da546Spatrick result.type = local.Type;
626061da546Spatrick result.name = local.Name;
627*f6aab3d8Srobert result.is_param =
628*f6aab3d8Srobert ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
629061da546Spatrick return result;
630061da546Spatrick }
631061da546Spatrick
632061da546Spatrick if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
633061da546Spatrick DataSym data(SymbolRecordKind::DataSym);
634061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
635061da546Spatrick result.type = data.Type;
636061da546Spatrick result.name = data.Name;
637061da546Spatrick return result;
638061da546Spatrick }
639061da546Spatrick
640061da546Spatrick if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
641061da546Spatrick ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
642061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
643061da546Spatrick result.type = data.Type;
644061da546Spatrick result.name = data.Name;
645061da546Spatrick return result;
646061da546Spatrick }
647061da546Spatrick
648061da546Spatrick if (sym.kind() == S_CONSTANT) {
649061da546Spatrick ConstantSym constant(SymbolRecordKind::ConstantSym);
650061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
651061da546Spatrick result.type = constant.Type;
652061da546Spatrick result.name = constant.Name;
653061da546Spatrick return result;
654061da546Spatrick }
655061da546Spatrick
656061da546Spatrick lldbassert(false && "Invalid variable record kind!");
657061da546Spatrick return {};
658061da546Spatrick }
659061da546Spatrick
660061da546Spatrick static llvm::FixedStreamArray<FrameData>::Iterator
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)661061da546Spatrick GetCorrespondingFrameData(lldb::addr_t load_addr,
662061da546Spatrick const DebugFrameDataSubsectionRef &fpo_data,
663061da546Spatrick const Variable::RangeList &ranges) {
664061da546Spatrick lldbassert(!ranges.IsEmpty());
665061da546Spatrick
666061da546Spatrick // assume that all variable ranges correspond to one frame data
667061da546Spatrick using RangeListEntry = Variable::RangeList::Entry;
668061da546Spatrick const RangeListEntry &range = ranges.GetEntryRef(0);
669061da546Spatrick
670061da546Spatrick auto it = fpo_data.begin();
671061da546Spatrick
672061da546Spatrick // start by searching first frame data range containing variable range
673061da546Spatrick for (; it != fpo_data.end(); ++it) {
674061da546Spatrick RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
675061da546Spatrick
676061da546Spatrick if (fd_range.Contains(range)) {
677061da546Spatrick break;
678061da546Spatrick }
679061da546Spatrick }
680061da546Spatrick
681061da546Spatrick // then first most nested entry that still contains variable range
682061da546Spatrick auto found = it;
683061da546Spatrick for (; it != fpo_data.end(); ++it) {
684061da546Spatrick RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
685061da546Spatrick
686061da546Spatrick if (!fd_range.Contains(range)) {
687061da546Spatrick break;
688061da546Spatrick }
689061da546Spatrick found = it;
690061da546Spatrick }
691061da546Spatrick
692061da546Spatrick return found;
693061da546Spatrick }
694061da546Spatrick
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)695061da546Spatrick static bool GetFrameDataProgram(PdbIndex &index,
696061da546Spatrick const Variable::RangeList &ranges,
697061da546Spatrick llvm::StringRef &out_program) {
698061da546Spatrick const DebugFrameDataSubsectionRef &new_fpo_data =
699061da546Spatrick index.dbi().getNewFpoRecords();
700061da546Spatrick
701061da546Spatrick auto frame_data_it =
702061da546Spatrick GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
703061da546Spatrick if (frame_data_it == new_fpo_data.end())
704061da546Spatrick return false;
705061da546Spatrick
706061da546Spatrick PDBStringTable &strings = cantFail(index.pdb().getStringTable());
707061da546Spatrick out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
708061da546Spatrick return true;
709061da546Spatrick }
710061da546Spatrick
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)711061da546Spatrick static RegisterId GetBaseFrameRegister(PdbIndex &index,
712061da546Spatrick PdbCompilandSymId frame_proc_id,
713061da546Spatrick bool is_parameter) {
714061da546Spatrick CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
715*f6aab3d8Srobert if (frame_proc_cvs.kind() != S_FRAMEPROC)
716*f6aab3d8Srobert return RegisterId::NONE;
717061da546Spatrick
718061da546Spatrick FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
719061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
720061da546Spatrick frame_proc));
721061da546Spatrick
722061da546Spatrick CPUType cpu_type = index.compilands()
723061da546Spatrick .GetCompiland(frame_proc_id.modi)
724061da546Spatrick ->m_compile_opts->Machine;
725061da546Spatrick
726061da546Spatrick return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
727061da546Spatrick : frame_proc.getLocalFramePtrReg(cpu_type);
728061da546Spatrick }
729061da546Spatrick
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)730061da546Spatrick VariableInfo lldb_private::npdb::GetVariableLocationInfo(
731*f6aab3d8Srobert PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
732061da546Spatrick lldb::ModuleSP module) {
733061da546Spatrick
734061da546Spatrick CVSymbol sym = index.ReadSymbolRecord(var_id);
735061da546Spatrick
736061da546Spatrick VariableInfo result = GetVariableNameInfo(sym);
737061da546Spatrick
738061da546Spatrick if (sym.kind() == S_REGREL32) {
739061da546Spatrick RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
740061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
741*f6aab3d8Srobert result.location = DWARFExpressionList(
742*f6aab3d8Srobert module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
743*f6aab3d8Srobert nullptr);
744061da546Spatrick return result;
745061da546Spatrick }
746061da546Spatrick
747061da546Spatrick if (sym.kind() == S_REGISTER) {
748061da546Spatrick RegisterSym reg(SymbolRecordKind::RegisterSym);
749061da546Spatrick cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
750*f6aab3d8Srobert result.location = DWARFExpressionList(
751*f6aab3d8Srobert module, MakeEnregisteredLocationExpression(reg.Register, module),
752*f6aab3d8Srobert nullptr);
753061da546Spatrick return result;
754061da546Spatrick }
755061da546Spatrick
756061da546Spatrick if (sym.kind() == S_LOCAL) {
757061da546Spatrick LocalSym local(SymbolRecordKind::LocalSym);
758*f6aab3d8Srobert if (llvm::Error error =
759*f6aab3d8Srobert SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
760*f6aab3d8Srobert llvm::consumeError(std::move(error));
761*f6aab3d8Srobert return result;
762*f6aab3d8Srobert }
763061da546Spatrick
764061da546Spatrick PdbCompilandSymId loc_specifier_id(var_id.modi,
765061da546Spatrick var_id.offset + sym.RecordData.size());
766*f6aab3d8Srobert CVSymbol loc_specifier_cvs;
767*f6aab3d8Srobert // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
768*f6aab3d8Srobert RegisterId base_reg = RegisterId::NONE;
769*f6aab3d8Srobert size_t type_size = GetSizeOfType(result.type, index.tpi());
770*f6aab3d8Srobert // A map from offset of a field in parent to size of the field.
771*f6aab3d8Srobert std::map<uint64_t, size_t> offset_to_size;
772*f6aab3d8Srobert
773*f6aab3d8Srobert // When overlaps happens, always prefer the one that doesn't split the value
774*f6aab3d8Srobert // into multiple locations and the location parsed first is perfered.
775*f6aab3d8Srobert RangeMap location_map;
776*f6aab3d8Srobert
777*f6aab3d8Srobert // Iterate through all location records after S_LOCAL. They describe the
778*f6aab3d8Srobert // value of this variable at different locations.
779*f6aab3d8Srobert bool finished = false;
780*f6aab3d8Srobert while (!finished) {
781*f6aab3d8Srobert loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
782*f6aab3d8Srobert switch (loc_specifier_cvs.kind()) {
783*f6aab3d8Srobert case S_DEFRANGE_FRAMEPOINTER_REL: {
784061da546Spatrick DefRangeFramePointerRelSym loc(
785061da546Spatrick SymbolRecordKind::DefRangeFramePointerRelSym);
786*f6aab3d8Srobert if (llvm::Error error =
787*f6aab3d8Srobert SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
788*f6aab3d8Srobert loc_specifier_cvs, loc)) {
789*f6aab3d8Srobert llvm::consumeError(std::move(error));
790*f6aab3d8Srobert return result;
791061da546Spatrick }
792*f6aab3d8Srobert Variable::RangeList raw_ranges =
793*f6aab3d8Srobert MakeRangeList(index, loc.Range, loc.Gaps);
794*f6aab3d8Srobert if (base_reg == RegisterId::NONE) {
795061da546Spatrick PdbCompilandSymId func_scope_id =
796*f6aab3d8Srobert PdbSymUid(func_block.GetID()).asCompilandSym();
797061da546Spatrick CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
798061da546Spatrick lldbassert(func_block_cvs.kind() == S_GPROC32 ||
799061da546Spatrick func_block_cvs.kind() == S_LPROC32);
800*f6aab3d8Srobert PdbCompilandSymId frame_proc_id(func_scope_id.modi,
801*f6aab3d8Srobert func_scope_id.offset +
802*f6aab3d8Srobert func_block_cvs.length());
803*f6aab3d8Srobert base_reg =
804*f6aab3d8Srobert GetBaseFrameRegister(index, frame_proc_id, result.is_param);
805*f6aab3d8Srobert if (base_reg == RegisterId::NONE)
806*f6aab3d8Srobert break;
807*f6aab3d8Srobert }
808*f6aab3d8Srobert DWARFExpression expr;
809061da546Spatrick if (base_reg == RegisterId::VFRAME) {
810061da546Spatrick llvm::StringRef program;
811*f6aab3d8Srobert if (GetFrameDataProgram(index, raw_ranges, program))
812*f6aab3d8Srobert expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
813*f6aab3d8Srobert module);
814*f6aab3d8Srobert else {
815*f6aab3d8Srobert // invalid variable
816*f6aab3d8Srobert }
817*f6aab3d8Srobert } else
818*f6aab3d8Srobert expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
819*f6aab3d8Srobert AddDwarfRange(location_map, expr, raw_ranges);
820*f6aab3d8Srobert break;
821*f6aab3d8Srobert }
822*f6aab3d8Srobert case S_DEFRANGE_REGISTER: {
823*f6aab3d8Srobert DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
824*f6aab3d8Srobert if (llvm::Error error =
825*f6aab3d8Srobert SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
826*f6aab3d8Srobert loc_specifier_cvs, loc)) {
827*f6aab3d8Srobert llvm::consumeError(std::move(error));
828*f6aab3d8Srobert return result;
829*f6aab3d8Srobert }
830*f6aab3d8Srobert RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
831*f6aab3d8Srobert Variable::RangeList raw_ranges =
832*f6aab3d8Srobert MakeRangeList(index, loc.Range, loc.Gaps);
833*f6aab3d8Srobert DWARFExpression expr =
834*f6aab3d8Srobert MakeEnregisteredLocationExpression(reg_id, module);
835*f6aab3d8Srobert AddDwarfRange(location_map, expr, raw_ranges);
836*f6aab3d8Srobert break;
837*f6aab3d8Srobert }
838*f6aab3d8Srobert case S_DEFRANGE_REGISTER_REL: {
839*f6aab3d8Srobert DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
840*f6aab3d8Srobert if (llvm::Error error =
841*f6aab3d8Srobert SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
842*f6aab3d8Srobert loc_specifier_cvs, loc)) {
843*f6aab3d8Srobert llvm::consumeError(std::move(error));
844*f6aab3d8Srobert return result;
845*f6aab3d8Srobert }
846*f6aab3d8Srobert Variable::RangeList raw_ranges =
847*f6aab3d8Srobert MakeRangeList(index, loc.Range, loc.Gaps);
848*f6aab3d8Srobert RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
849*f6aab3d8Srobert DWARFExpression expr;
850*f6aab3d8Srobert if (reg_id == RegisterId::VFRAME) {
851*f6aab3d8Srobert llvm::StringRef program;
852*f6aab3d8Srobert if (GetFrameDataProgram(index, raw_ranges, program))
853*f6aab3d8Srobert expr = MakeVFrameRelLocationExpression(
854*f6aab3d8Srobert program, loc.Hdr.BasePointerOffset, module);
855*f6aab3d8Srobert else {
856061da546Spatrick // invalid variable
857061da546Spatrick }
858061da546Spatrick } else {
859*f6aab3d8Srobert expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
860*f6aab3d8Srobert module);
861061da546Spatrick }
862*f6aab3d8Srobert // FIXME: If it's UDT, we need to know the size of the value in byte.
863*f6aab3d8Srobert if (!loc.hasSpilledUDTMember())
864*f6aab3d8Srobert AddDwarfRange(location_map, expr, raw_ranges);
865*f6aab3d8Srobert break;
866*f6aab3d8Srobert }
867*f6aab3d8Srobert case S_DEFRANGE_SUBFIELD_REGISTER: {
868*f6aab3d8Srobert DefRangeSubfieldRegisterSym loc(
869*f6aab3d8Srobert SymbolRecordKind::DefRangeSubfieldRegisterSym);
870*f6aab3d8Srobert if (llvm::Error error =
871*f6aab3d8Srobert SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
872*f6aab3d8Srobert loc_specifier_cvs, loc)) {
873*f6aab3d8Srobert llvm::consumeError(std::move(error));
874*f6aab3d8Srobert return result;
875*f6aab3d8Srobert }
876061da546Spatrick
877061da546Spatrick Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
878*f6aab3d8Srobert uint32_t reg_size =
879*f6aab3d8Srobert GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
880*f6aab3d8Srobert if (reg_size == 0)
881*f6aab3d8Srobert break;
882*f6aab3d8Srobert offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
883*f6aab3d8Srobert AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
884*f6aab3d8Srobert {loc.Hdr.Register, 0, true}, ranges);
885*f6aab3d8Srobert break;
886061da546Spatrick }
887*f6aab3d8Srobert // FIXME: Handle other kinds. LLVM only generates the 4 types of records
888*f6aab3d8Srobert // above. MSVC generates other location types.
889*f6aab3d8Srobert case S_DEFRANGE:
890*f6aab3d8Srobert case S_DEFRANGE_SUBFIELD:
891*f6aab3d8Srobert case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
892*f6aab3d8Srobert break;
893*f6aab3d8Srobert default:
894*f6aab3d8Srobert finished = true;
895*f6aab3d8Srobert break;
896061da546Spatrick }
897*f6aab3d8Srobert loc_specifier_id = PdbCompilandSymId(
898*f6aab3d8Srobert loc_specifier_id.modi,
899*f6aab3d8Srobert loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
900061da546Spatrick }
901*f6aab3d8Srobert for (const auto &entry : location_map) {
902*f6aab3d8Srobert DWARFExpression dwarf_expr =
903*f6aab3d8Srobert entry.data.is_dwarf ? entry.data.expr
904*f6aab3d8Srobert : MakeEnregisteredLocationExpressionForComposite(
905*f6aab3d8Srobert entry.data.offset_to_location,
906*f6aab3d8Srobert offset_to_size, type_size, module);
907061da546Spatrick
908*f6aab3d8Srobert result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
909*f6aab3d8Srobert dwarf_expr);
910*f6aab3d8Srobert }
911061da546Spatrick return result;
912061da546Spatrick }
913061da546Spatrick llvm_unreachable("Symbol is not a local variable!");
914061da546Spatrick return result;
915061da546Spatrick }
916061da546Spatrick
917061da546Spatrick lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)918061da546Spatrick lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
919061da546Spatrick switch (kind) {
920061da546Spatrick case SimpleTypeKind::Boolean128:
921061da546Spatrick case SimpleTypeKind::Boolean16:
922061da546Spatrick case SimpleTypeKind::Boolean32:
923061da546Spatrick case SimpleTypeKind::Boolean64:
924061da546Spatrick case SimpleTypeKind::Boolean8:
925061da546Spatrick return lldb::eBasicTypeBool;
926061da546Spatrick case SimpleTypeKind::Byte:
927061da546Spatrick case SimpleTypeKind::UnsignedCharacter:
928061da546Spatrick return lldb::eBasicTypeUnsignedChar;
929061da546Spatrick case SimpleTypeKind::NarrowCharacter:
930061da546Spatrick return lldb::eBasicTypeChar;
931061da546Spatrick case SimpleTypeKind::SignedCharacter:
932061da546Spatrick case SimpleTypeKind::SByte:
933061da546Spatrick return lldb::eBasicTypeSignedChar;
934061da546Spatrick case SimpleTypeKind::Character16:
935061da546Spatrick return lldb::eBasicTypeChar16;
936061da546Spatrick case SimpleTypeKind::Character32:
937061da546Spatrick return lldb::eBasicTypeChar32;
938*f6aab3d8Srobert case SimpleTypeKind::Character8:
939*f6aab3d8Srobert return lldb::eBasicTypeChar8;
940061da546Spatrick case SimpleTypeKind::Complex80:
941061da546Spatrick return lldb::eBasicTypeLongDoubleComplex;
942061da546Spatrick case SimpleTypeKind::Complex64:
943061da546Spatrick return lldb::eBasicTypeDoubleComplex;
944061da546Spatrick case SimpleTypeKind::Complex32:
945061da546Spatrick return lldb::eBasicTypeFloatComplex;
946061da546Spatrick case SimpleTypeKind::Float128:
947061da546Spatrick case SimpleTypeKind::Float80:
948061da546Spatrick return lldb::eBasicTypeLongDouble;
949061da546Spatrick case SimpleTypeKind::Float64:
950061da546Spatrick return lldb::eBasicTypeDouble;
951061da546Spatrick case SimpleTypeKind::Float32:
952061da546Spatrick return lldb::eBasicTypeFloat;
953061da546Spatrick case SimpleTypeKind::Float16:
954061da546Spatrick return lldb::eBasicTypeHalf;
955061da546Spatrick case SimpleTypeKind::Int128:
956061da546Spatrick return lldb::eBasicTypeInt128;
957061da546Spatrick case SimpleTypeKind::Int64:
958061da546Spatrick case SimpleTypeKind::Int64Quad:
959061da546Spatrick return lldb::eBasicTypeLongLong;
960061da546Spatrick case SimpleTypeKind::Int32:
961061da546Spatrick return lldb::eBasicTypeInt;
962061da546Spatrick case SimpleTypeKind::Int16:
963061da546Spatrick case SimpleTypeKind::Int16Short:
964061da546Spatrick return lldb::eBasicTypeShort;
965061da546Spatrick case SimpleTypeKind::UInt128:
966061da546Spatrick return lldb::eBasicTypeUnsignedInt128;
967061da546Spatrick case SimpleTypeKind::UInt64:
968061da546Spatrick case SimpleTypeKind::UInt64Quad:
969061da546Spatrick return lldb::eBasicTypeUnsignedLongLong;
970061da546Spatrick case SimpleTypeKind::HResult:
971061da546Spatrick case SimpleTypeKind::UInt32:
972061da546Spatrick return lldb::eBasicTypeUnsignedInt;
973061da546Spatrick case SimpleTypeKind::UInt16:
974061da546Spatrick case SimpleTypeKind::UInt16Short:
975061da546Spatrick return lldb::eBasicTypeUnsignedShort;
976061da546Spatrick case SimpleTypeKind::Int32Long:
977061da546Spatrick return lldb::eBasicTypeLong;
978061da546Spatrick case SimpleTypeKind::UInt32Long:
979061da546Spatrick return lldb::eBasicTypeUnsignedLong;
980061da546Spatrick case SimpleTypeKind::Void:
981061da546Spatrick return lldb::eBasicTypeVoid;
982061da546Spatrick case SimpleTypeKind::WideCharacter:
983061da546Spatrick return lldb::eBasicTypeWChar;
984061da546Spatrick default:
985061da546Spatrick return lldb::eBasicTypeInvalid;
986061da546Spatrick }
987061da546Spatrick }
988061da546Spatrick
GetTypeSizeForSimpleKind(SimpleTypeKind kind)989061da546Spatrick size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
990061da546Spatrick switch (kind) {
991061da546Spatrick case SimpleTypeKind::Boolean128:
992061da546Spatrick case SimpleTypeKind::Int128:
993061da546Spatrick case SimpleTypeKind::UInt128:
994061da546Spatrick case SimpleTypeKind::Float128:
995061da546Spatrick return 16;
996061da546Spatrick case SimpleTypeKind::Complex80:
997061da546Spatrick case SimpleTypeKind::Float80:
998061da546Spatrick return 10;
999061da546Spatrick case SimpleTypeKind::Boolean64:
1000061da546Spatrick case SimpleTypeKind::Complex64:
1001061da546Spatrick case SimpleTypeKind::UInt64:
1002061da546Spatrick case SimpleTypeKind::UInt64Quad:
1003061da546Spatrick case SimpleTypeKind::Float64:
1004061da546Spatrick case SimpleTypeKind::Int64:
1005061da546Spatrick case SimpleTypeKind::Int64Quad:
1006061da546Spatrick return 8;
1007061da546Spatrick case SimpleTypeKind::Boolean32:
1008061da546Spatrick case SimpleTypeKind::Character32:
1009061da546Spatrick case SimpleTypeKind::Complex32:
1010061da546Spatrick case SimpleTypeKind::Float32:
1011061da546Spatrick case SimpleTypeKind::Int32:
1012061da546Spatrick case SimpleTypeKind::Int32Long:
1013061da546Spatrick case SimpleTypeKind::UInt32Long:
1014061da546Spatrick case SimpleTypeKind::HResult:
1015061da546Spatrick case SimpleTypeKind::UInt32:
1016061da546Spatrick return 4;
1017061da546Spatrick case SimpleTypeKind::Boolean16:
1018061da546Spatrick case SimpleTypeKind::Character16:
1019061da546Spatrick case SimpleTypeKind::Float16:
1020061da546Spatrick case SimpleTypeKind::Int16:
1021061da546Spatrick case SimpleTypeKind::Int16Short:
1022061da546Spatrick case SimpleTypeKind::UInt16:
1023061da546Spatrick case SimpleTypeKind::UInt16Short:
1024061da546Spatrick case SimpleTypeKind::WideCharacter:
1025061da546Spatrick return 2;
1026061da546Spatrick case SimpleTypeKind::Boolean8:
1027061da546Spatrick case SimpleTypeKind::Byte:
1028061da546Spatrick case SimpleTypeKind::UnsignedCharacter:
1029061da546Spatrick case SimpleTypeKind::NarrowCharacter:
1030061da546Spatrick case SimpleTypeKind::SignedCharacter:
1031061da546Spatrick case SimpleTypeKind::SByte:
1032*f6aab3d8Srobert case SimpleTypeKind::Character8:
1033061da546Spatrick return 1;
1034061da546Spatrick case SimpleTypeKind::Void:
1035061da546Spatrick default:
1036061da546Spatrick return 0;
1037061da546Spatrick }
1038061da546Spatrick }
1039061da546Spatrick
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)1040061da546Spatrick PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
1041061da546Spatrick TpiStream &tpi) {
1042061da546Spatrick if (id.index.isSimple())
1043061da546Spatrick return id;
1044061da546Spatrick
1045061da546Spatrick CVType cvt = tpi.getType(id.index);
1046061da546Spatrick
1047061da546Spatrick // Only tag records have a best and a worst record.
1048061da546Spatrick if (!IsTagRecord(cvt))
1049061da546Spatrick return id;
1050061da546Spatrick
1051061da546Spatrick // Tag records that are not forward decls are full decls, hence they are the
1052061da546Spatrick // best.
1053061da546Spatrick if (!IsForwardRefUdt(cvt))
1054061da546Spatrick return id;
1055061da546Spatrick
1056061da546Spatrick return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
1057061da546Spatrick }
1058061da546Spatrick
GetSizeOfTypeInternal(CVType cvt)1059061da546Spatrick template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
1060061da546Spatrick RecordType record;
1061061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
1062061da546Spatrick return record.getSize();
1063061da546Spatrick }
1064061da546Spatrick
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)1065061da546Spatrick size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
1066061da546Spatrick llvm::pdb::TpiStream &tpi) {
1067061da546Spatrick if (id.index.isSimple()) {
1068061da546Spatrick switch (id.index.getSimpleMode()) {
1069061da546Spatrick case SimpleTypeMode::Direct:
1070061da546Spatrick return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
1071061da546Spatrick case SimpleTypeMode::NearPointer32:
1072061da546Spatrick case SimpleTypeMode::FarPointer32:
1073061da546Spatrick return 4;
1074061da546Spatrick case SimpleTypeMode::NearPointer64:
1075061da546Spatrick return 8;
1076061da546Spatrick case SimpleTypeMode::NearPointer128:
1077061da546Spatrick return 16;
1078061da546Spatrick default:
1079061da546Spatrick break;
1080061da546Spatrick }
1081061da546Spatrick return 0;
1082061da546Spatrick }
1083061da546Spatrick
1084061da546Spatrick TypeIndex index = id.index;
1085061da546Spatrick if (IsForwardRefUdt(index, tpi))
1086061da546Spatrick index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
1087061da546Spatrick
1088061da546Spatrick CVType cvt = tpi.getType(index);
1089061da546Spatrick switch (cvt.kind()) {
1090061da546Spatrick case LF_MODIFIER:
1091061da546Spatrick return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
1092061da546Spatrick case LF_ENUM: {
1093061da546Spatrick EnumRecord record;
1094061da546Spatrick llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
1095061da546Spatrick return GetSizeOfType({record.UnderlyingType}, tpi);
1096061da546Spatrick }
1097061da546Spatrick case LF_POINTER:
1098061da546Spatrick return GetSizeOfTypeInternal<PointerRecord>(cvt);
1099061da546Spatrick case LF_ARRAY:
1100061da546Spatrick return GetSizeOfTypeInternal<ArrayRecord>(cvt);
1101061da546Spatrick case LF_CLASS:
1102061da546Spatrick case LF_STRUCTURE:
1103061da546Spatrick case LF_INTERFACE:
1104061da546Spatrick return GetSizeOfTypeInternal<ClassRecord>(cvt);
1105061da546Spatrick case LF_UNION:
1106061da546Spatrick return GetSizeOfTypeInternal<UnionRecord>(cvt);
1107*f6aab3d8Srobert case LF_BITFIELD: {
1108*f6aab3d8Srobert BitFieldRecord record;
1109*f6aab3d8Srobert llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1110*f6aab3d8Srobert return GetSizeOfType({record.Type}, tpi);
1111*f6aab3d8Srobert }
1112061da546Spatrick default:
1113061da546Spatrick break;
1114061da546Spatrick }
1115061da546Spatrick return 0;
1116061da546Spatrick }
1117