180814287SRaphael Isemann //===-- PdbUtil.cpp -------------------------------------------------------===//
2307f5ae8SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6307f5ae8SZachary Turner //
7307f5ae8SZachary Turner //===----------------------------------------------------------------------===//
8307f5ae8SZachary Turner 
9307f5ae8SZachary Turner #include "PdbUtil.h"
10594c85e9SZachary Turner 
11594c85e9SZachary Turner #include "DWARFLocationExpression.h"
12594c85e9SZachary Turner #include "PdbIndex.h"
136284aee9SZachary Turner #include "PdbSymUid.h"
14307f5ae8SZachary Turner 
155e9c9b32SZequan Wu #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17b96181c2SZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18758657e5SAleksandr Urakov #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
196284aee9SZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20307f5ae8SZachary Turner 
2144f19514SZachary Turner #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22758657e5SAleksandr Urakov #include "lldb/Symbol/Block.h"
23307f5ae8SZachary Turner #include "lldb/Utility/LLDBAssert.h"
245e9c9b32SZequan Wu #include "lldb/Utility/LLDBLog.h"
25b96181c2SZachary Turner #include "lldb/lldb-enumerations.h"
26b96181c2SZachary Turner 
27307f5ae8SZachary Turner using namespace lldb_private;
28307f5ae8SZachary Turner using namespace lldb_private::npdb;
29307f5ae8SZachary Turner using namespace llvm::codeview;
30307f5ae8SZachary Turner using namespace llvm::pdb;
31307f5ae8SZachary Turner 
32594c85e9SZachary Turner static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)33594c85e9SZachary Turner MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
34594c85e9SZachary Turner               llvm::ArrayRef<LocalVariableAddrGap> gaps) {
35594c85e9SZachary Turner   lldb::addr_t start =
36594c85e9SZachary Turner       index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
378a790e65SZequan Wu   if (start == LLDB_INVALID_ADDRESS)
388a790e65SZequan Wu     return {};
39594c85e9SZachary Turner   lldb::addr_t end = start + range.Range;
40594c85e9SZachary Turner 
41594c85e9SZachary Turner   Variable::RangeList result;
42594c85e9SZachary Turner   while (!gaps.empty()) {
43594c85e9SZachary Turner     const LocalVariableAddrGap &gap = gaps.front();
44c45975cbSZequan Wu     lldb::addr_t gap_start = start + gap.GapStartOffset;
45c45975cbSZequan Wu     result.Append(start, gap_start - start);
46c45975cbSZequan Wu     start = gap_start + gap.Range;
47594c85e9SZachary Turner     gaps = gaps.drop_front();
48594c85e9SZachary Turner   }
49594c85e9SZachary Turner 
50758657e5SAleksandr Urakov   result.Append(start, end - start);
51594c85e9SZachary Turner   return result;
52594c85e9SZachary Turner }
53594c85e9SZachary Turner 
545e9c9b32SZequan Wu namespace {
555e9c9b32SZequan Wu struct FindMembersSize : public TypeVisitorCallbacks {
FindMembersSize__anon204fc7730111::FindMembersSize563dbf524aSZequan Wu   FindMembersSize(
572fa27346SZequan Wu       std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
585e9c9b32SZequan Wu       TpiStream &tpi)
595e9c9b32SZequan Wu       : members_info(members_info), tpi(tpi) {}
602fa27346SZequan Wu   std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info;
615e9c9b32SZequan Wu   TpiStream &tpi;
visitKnownMember__anon204fc7730111::FindMembersSize625e9c9b32SZequan Wu   llvm::Error visitKnownMember(CVMemberRecord &cvr,
635e9c9b32SZequan Wu                                DataMemberRecord &member) override {
64d6710023SZequan Wu     members_info.insert(
652fa27346SZequan Wu         {member.getFieldOffset(),
662fa27346SZequan Wu          {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}});
675e9c9b32SZequan Wu     return llvm::Error::success();
685e9c9b32SZequan Wu   }
695e9c9b32SZequan Wu };
705e9c9b32SZequan Wu } // namespace
715e9c9b32SZequan Wu 
create(CVType type)72056e4ab4SZachary Turner CVTagRecord CVTagRecord::create(CVType type) {
73056e4ab4SZachary Turner   assert(IsTagRecord(type) && "type is not a tag record!");
74056e4ab4SZachary Turner   switch (type.kind()) {
75056e4ab4SZachary Turner   case LF_CLASS:
76056e4ab4SZachary Turner   case LF_STRUCTURE:
77056e4ab4SZachary Turner   case LF_INTERFACE: {
78056e4ab4SZachary Turner     ClassRecord cr;
79056e4ab4SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
80056e4ab4SZachary Turner     return CVTagRecord(std::move(cr));
81056e4ab4SZachary Turner   }
82056e4ab4SZachary Turner   case LF_UNION: {
83056e4ab4SZachary Turner     UnionRecord ur;
84056e4ab4SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
85056e4ab4SZachary Turner     return CVTagRecord(std::move(ur));
86056e4ab4SZachary Turner   }
87056e4ab4SZachary Turner   case LF_ENUM: {
88056e4ab4SZachary Turner     EnumRecord er;
89056e4ab4SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
90056e4ab4SZachary Turner     return CVTagRecord(std::move(er));
91056e4ab4SZachary Turner   }
92056e4ab4SZachary Turner   default:
93056e4ab4SZachary Turner     llvm_unreachable("Unreachable!");
94056e4ab4SZachary Turner   }
95056e4ab4SZachary Turner }
96056e4ab4SZachary Turner 
CVTagRecord(ClassRecord && c)97056e4ab4SZachary Turner CVTagRecord::CVTagRecord(ClassRecord &&c)
98056e4ab4SZachary Turner     : cvclass(std::move(c)),
99056e4ab4SZachary Turner       m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)100056e4ab4SZachary Turner CVTagRecord::CVTagRecord(UnionRecord &&u)
101056e4ab4SZachary Turner     : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)102056e4ab4SZachary Turner CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
103056e4ab4SZachary Turner 
CVSymToPDBSym(SymbolKind kind)104b96181c2SZachary Turner PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
105307f5ae8SZachary Turner   switch (kind) {
106307f5ae8SZachary Turner   case S_COMPILE3:
107307f5ae8SZachary Turner   case S_OBJNAME:
108307f5ae8SZachary Turner     return PDB_SymType::CompilandDetails;
109307f5ae8SZachary Turner   case S_ENVBLOCK:
110307f5ae8SZachary Turner     return PDB_SymType::CompilandEnv;
111307f5ae8SZachary Turner   case S_THUNK32:
112307f5ae8SZachary Turner   case S_TRAMPOLINE:
113307f5ae8SZachary Turner     return PDB_SymType::Thunk;
114307f5ae8SZachary Turner   case S_COFFGROUP:
115307f5ae8SZachary Turner     return PDB_SymType::CoffGroup;
116307f5ae8SZachary Turner   case S_EXPORT:
117307f5ae8SZachary Turner     return PDB_SymType::Export;
118307f5ae8SZachary Turner   case S_LPROC32:
119307f5ae8SZachary Turner   case S_GPROC32:
120307f5ae8SZachary Turner   case S_LPROC32_DPC:
121307f5ae8SZachary Turner     return PDB_SymType::Function;
122307f5ae8SZachary Turner   case S_PUB32:
123307f5ae8SZachary Turner     return PDB_SymType::PublicSymbol;
124307f5ae8SZachary Turner   case S_INLINESITE:
125307f5ae8SZachary Turner     return PDB_SymType::InlineSite;
126307f5ae8SZachary Turner   case S_LOCAL:
127307f5ae8SZachary Turner   case S_BPREL32:
128307f5ae8SZachary Turner   case S_REGREL32:
129307f5ae8SZachary Turner   case S_MANCONSTANT:
130307f5ae8SZachary Turner   case S_CONSTANT:
131307f5ae8SZachary Turner   case S_LDATA32:
132307f5ae8SZachary Turner   case S_GDATA32:
133307f5ae8SZachary Turner   case S_LMANDATA:
134307f5ae8SZachary Turner   case S_GMANDATA:
135307f5ae8SZachary Turner   case S_LTHREAD32:
136307f5ae8SZachary Turner   case S_GTHREAD32:
137307f5ae8SZachary Turner     return PDB_SymType::Data;
138307f5ae8SZachary Turner   case S_BLOCK32:
139307f5ae8SZachary Turner     return PDB_SymType::Block;
140307f5ae8SZachary Turner   case S_LABEL32:
141307f5ae8SZachary Turner     return PDB_SymType::Label;
142307f5ae8SZachary Turner   case S_CALLSITEINFO:
143307f5ae8SZachary Turner     return PDB_SymType::CallSite;
144307f5ae8SZachary Turner   case S_HEAPALLOCSITE:
145307f5ae8SZachary Turner     return PDB_SymType::HeapAllocationSite;
146307f5ae8SZachary Turner   case S_CALLEES:
147307f5ae8SZachary Turner     return PDB_SymType::Callee;
148307f5ae8SZachary Turner   case S_CALLERS:
149307f5ae8SZachary Turner     return PDB_SymType::Caller;
150307f5ae8SZachary Turner   default:
151307f5ae8SZachary Turner     lldbassert(false && "Invalid symbol record kind!");
152307f5ae8SZachary Turner   }
153307f5ae8SZachary Turner   return PDB_SymType::None;
154307f5ae8SZachary Turner }
155307f5ae8SZachary Turner 
CVTypeToPDBType(TypeLeafKind kind)156b96181c2SZachary Turner PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
157b96181c2SZachary Turner   switch (kind) {
158b96181c2SZachary Turner   case LF_ARRAY:
159b96181c2SZachary Turner     return PDB_SymType::ArrayType;
160b96181c2SZachary Turner   case LF_ARGLIST:
161b96181c2SZachary Turner     return PDB_SymType::FunctionSig;
162b96181c2SZachary Turner   case LF_BCLASS:
163b96181c2SZachary Turner     return PDB_SymType::BaseClass;
164b96181c2SZachary Turner   case LF_BINTERFACE:
165b96181c2SZachary Turner     return PDB_SymType::BaseInterface;
166b96181c2SZachary Turner   case LF_CLASS:
167b96181c2SZachary Turner   case LF_STRUCTURE:
168b96181c2SZachary Turner   case LF_INTERFACE:
169b96181c2SZachary Turner   case LF_UNION:
170b96181c2SZachary Turner     return PDB_SymType::UDT;
171b96181c2SZachary Turner   case LF_POINTER:
172b96181c2SZachary Turner     return PDB_SymType::PointerType;
173b96181c2SZachary Turner   case LF_ENUM:
174b96181c2SZachary Turner     return PDB_SymType::Enum;
175544a66d8SZachary Turner   case LF_PROCEDURE:
176544a66d8SZachary Turner     return PDB_SymType::FunctionSig;
177056e4ab4SZachary Turner   case LF_BITFIELD:
178056e4ab4SZachary Turner     return PDB_SymType::BuiltinType;
179b96181c2SZachary Turner   default:
180b96181c2SZachary Turner     lldbassert(false && "Invalid type record kind!");
181b96181c2SZachary Turner   }
182b96181c2SZachary Turner   return PDB_SymType::None;
183b96181c2SZachary Turner }
184b96181c2SZachary Turner 
SymbolHasAddress(const CVSymbol & sym)185b96181c2SZachary Turner bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
186307f5ae8SZachary Turner   switch (sym.kind()) {
187307f5ae8SZachary Turner   case S_GPROC32:
188307f5ae8SZachary Turner   case S_LPROC32:
189307f5ae8SZachary Turner   case S_GPROC32_ID:
190307f5ae8SZachary Turner   case S_LPROC32_ID:
191307f5ae8SZachary Turner   case S_LPROC32_DPC:
192307f5ae8SZachary Turner   case S_LPROC32_DPC_ID:
193307f5ae8SZachary Turner   case S_THUNK32:
194307f5ae8SZachary Turner   case S_TRAMPOLINE:
195307f5ae8SZachary Turner   case S_COFFGROUP:
196307f5ae8SZachary Turner   case S_BLOCK32:
197307f5ae8SZachary Turner   case S_LABEL32:
198307f5ae8SZachary Turner   case S_CALLSITEINFO:
199307f5ae8SZachary Turner   case S_HEAPALLOCSITE:
200307f5ae8SZachary Turner   case S_LDATA32:
201307f5ae8SZachary Turner   case S_GDATA32:
202307f5ae8SZachary Turner   case S_LMANDATA:
203307f5ae8SZachary Turner   case S_GMANDATA:
204307f5ae8SZachary Turner   case S_LTHREAD32:
205307f5ae8SZachary Turner   case S_GTHREAD32:
206307f5ae8SZachary Turner     return true;
207307f5ae8SZachary Turner   default:
208307f5ae8SZachary Turner     return false;
209307f5ae8SZachary Turner   }
210307f5ae8SZachary Turner }
211307f5ae8SZachary Turner 
SymbolIsCode(const CVSymbol & sym)212b96181c2SZachary Turner bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
213307f5ae8SZachary Turner   switch (sym.kind()) {
214307f5ae8SZachary Turner   case S_GPROC32:
215307f5ae8SZachary Turner   case S_LPROC32:
216307f5ae8SZachary Turner   case S_GPROC32_ID:
217307f5ae8SZachary Turner   case S_LPROC32_ID:
218307f5ae8SZachary Turner   case S_LPROC32_DPC:
219307f5ae8SZachary Turner   case S_LPROC32_DPC_ID:
220307f5ae8SZachary Turner   case S_THUNK32:
221307f5ae8SZachary Turner   case S_TRAMPOLINE:
222307f5ae8SZachary Turner   case S_COFFGROUP:
223307f5ae8SZachary Turner   case S_BLOCK32:
224307f5ae8SZachary Turner     return true;
225307f5ae8SZachary Turner   default:
226307f5ae8SZachary Turner     return false;
227307f5ae8SZachary Turner   }
228307f5ae8SZachary Turner }
229307f5ae8SZachary Turner 
createRecord(const CVSymbol & sym)230307f5ae8SZachary Turner template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
231307f5ae8SZachary Turner   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
232307f5ae8SZachary Turner   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
233307f5ae8SZachary Turner   return record;
234307f5ae8SZachary Turner }
235307f5ae8SZachary Turner 
236307f5ae8SZachary Turner template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)237307f5ae8SZachary Turner static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
238307f5ae8SZachary Turner   RecordT record = createRecord<RecordT>(sym);
239307f5ae8SZachary Turner   return {record.Segment, record.CodeOffset};
240307f5ae8SZachary Turner }
241307f5ae8SZachary Turner 
242307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)243307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
244307f5ae8SZachary Turner   TrampolineSym record = createRecord<TrampolineSym>(sym);
245307f5ae8SZachary Turner   return {record.ThunkSection, record.ThunkOffset};
246307f5ae8SZachary Turner }
247307f5ae8SZachary Turner 
GetSegmentAndOffset(const CVSymbol & sym)248307f5ae8SZachary Turner template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
249307f5ae8SZachary Turner   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
250307f5ae8SZachary Turner   return {record.Segment, record.Offset};
251307f5ae8SZachary Turner }
252307f5ae8SZachary Turner 
253307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)254307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
255307f5ae8SZachary Turner   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
256307f5ae8SZachary Turner   return {record.Segment, record.Offset};
257307f5ae8SZachary Turner }
258307f5ae8SZachary Turner 
GetSegmentAndOffset(const CVSymbol & sym)259307f5ae8SZachary Turner template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
260307f5ae8SZachary Turner   DataSym record = createRecord<DataSym>(sym);
261307f5ae8SZachary Turner   return {record.Segment, record.DataOffset};
262307f5ae8SZachary Turner }
263307f5ae8SZachary Turner 
264307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)265307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
266307f5ae8SZachary Turner   ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
267307f5ae8SZachary Turner   return {record.Segment, record.DataOffset};
268307f5ae8SZachary Turner }
269307f5ae8SZachary Turner 
GetSegmentAndOffset(const CVSymbol & sym)270b96181c2SZachary Turner SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
271307f5ae8SZachary Turner   switch (sym.kind()) {
272307f5ae8SZachary Turner   case S_GPROC32:
273307f5ae8SZachary Turner   case S_LPROC32:
274307f5ae8SZachary Turner   case S_GPROC32_ID:
275307f5ae8SZachary Turner   case S_LPROC32_ID:
276307f5ae8SZachary Turner   case S_LPROC32_DPC:
277307f5ae8SZachary Turner   case S_LPROC32_DPC_ID:
278307f5ae8SZachary Turner     return ::GetSegmentAndOffset<ProcSym>(sym);
279307f5ae8SZachary Turner   case S_THUNK32:
280307f5ae8SZachary Turner     return ::GetSegmentAndOffset<Thunk32Sym>(sym);
281307f5ae8SZachary Turner     break;
282307f5ae8SZachary Turner   case S_TRAMPOLINE:
283307f5ae8SZachary Turner     return ::GetSegmentAndOffset<TrampolineSym>(sym);
284307f5ae8SZachary Turner     break;
285307f5ae8SZachary Turner   case S_COFFGROUP:
286307f5ae8SZachary Turner     return ::GetSegmentAndOffset<CoffGroupSym>(sym);
287307f5ae8SZachary Turner     break;
288307f5ae8SZachary Turner   case S_BLOCK32:
289307f5ae8SZachary Turner     return ::GetSegmentAndOffset<BlockSym>(sym);
290307f5ae8SZachary Turner     break;
291307f5ae8SZachary Turner   case S_LABEL32:
292307f5ae8SZachary Turner     return ::GetSegmentAndOffset<LabelSym>(sym);
293307f5ae8SZachary Turner     break;
294307f5ae8SZachary Turner   case S_CALLSITEINFO:
295307f5ae8SZachary Turner     return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
296307f5ae8SZachary Turner     break;
297307f5ae8SZachary Turner   case S_HEAPALLOCSITE:
298307f5ae8SZachary Turner     return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
299307f5ae8SZachary Turner     break;
300307f5ae8SZachary Turner   case S_LDATA32:
301307f5ae8SZachary Turner   case S_GDATA32:
302307f5ae8SZachary Turner   case S_LMANDATA:
303307f5ae8SZachary Turner   case S_GMANDATA:
304307f5ae8SZachary Turner     return ::GetSegmentAndOffset<DataSym>(sym);
305307f5ae8SZachary Turner     break;
306307f5ae8SZachary Turner   case S_LTHREAD32:
307307f5ae8SZachary Turner   case S_GTHREAD32:
308307f5ae8SZachary Turner     return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
309307f5ae8SZachary Turner     break;
310307f5ae8SZachary Turner   default:
311307f5ae8SZachary Turner     lldbassert(false && "Record does not have a segment/offset!");
312307f5ae8SZachary Turner   }
313307f5ae8SZachary Turner   return {0, 0};
314307f5ae8SZachary Turner }
315307f5ae8SZachary Turner 
316307f5ae8SZachary Turner template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)317307f5ae8SZachary Turner SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
318307f5ae8SZachary Turner   RecordT record = createRecord<RecordT>(sym);
319307f5ae8SZachary Turner   return {record.Segment, record.CodeOffset, record.CodeSize};
320307f5ae8SZachary Turner }
321307f5ae8SZachary Turner 
322307f5ae8SZachary Turner template <>
323307f5ae8SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)324307f5ae8SZachary Turner GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
325307f5ae8SZachary Turner   TrampolineSym record = createRecord<TrampolineSym>(sym);
326307f5ae8SZachary Turner   return {record.ThunkSection, record.ThunkOffset, record.Size};
327307f5ae8SZachary Turner }
328307f5ae8SZachary Turner 
329307f5ae8SZachary Turner template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)330307f5ae8SZachary Turner SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
331307f5ae8SZachary Turner   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
332307f5ae8SZachary Turner   return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
333307f5ae8SZachary Turner }
334307f5ae8SZachary Turner 
335307f5ae8SZachary Turner template <>
336307f5ae8SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)337307f5ae8SZachary Turner GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
338307f5ae8SZachary Turner   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
339307f5ae8SZachary Turner   return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
340307f5ae8SZachary Turner }
341307f5ae8SZachary Turner 
342b96181c2SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)343b96181c2SZachary Turner lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
344307f5ae8SZachary Turner   switch (sym.kind()) {
345307f5ae8SZachary Turner   case S_GPROC32:
346307f5ae8SZachary Turner   case S_LPROC32:
347307f5ae8SZachary Turner   case S_GPROC32_ID:
348307f5ae8SZachary Turner   case S_LPROC32_ID:
349307f5ae8SZachary Turner   case S_LPROC32_DPC:
350307f5ae8SZachary Turner   case S_LPROC32_DPC_ID:
351307f5ae8SZachary Turner     return ::GetSegmentOffsetAndLength<ProcSym>(sym);
352307f5ae8SZachary Turner   case S_THUNK32:
353307f5ae8SZachary Turner     return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
354307f5ae8SZachary Turner     break;
355307f5ae8SZachary Turner   case S_TRAMPOLINE:
356307f5ae8SZachary Turner     return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
357307f5ae8SZachary Turner     break;
358307f5ae8SZachary Turner   case S_COFFGROUP:
359307f5ae8SZachary Turner     return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
360307f5ae8SZachary Turner     break;
361307f5ae8SZachary Turner   case S_BLOCK32:
362307f5ae8SZachary Turner     return ::GetSegmentOffsetAndLength<BlockSym>(sym);
363307f5ae8SZachary Turner     break;
364307f5ae8SZachary Turner   default:
365307f5ae8SZachary Turner     lldbassert(false && "Record does not have a segment/offset/length triple!");
366307f5ae8SZachary Turner   }
367307f5ae8SZachary Turner   return {0, 0, 0};
368307f5ae8SZachary Turner }
369b96181c2SZachary Turner 
IsForwardRefUdt(CVType cvt)370b96181c2SZachary Turner bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
371b96181c2SZachary Turner   ClassRecord cr;
372b96181c2SZachary Turner   UnionRecord ur;
373b96181c2SZachary Turner   EnumRecord er;
374b96181c2SZachary Turner   switch (cvt.kind()) {
375b96181c2SZachary Turner   case LF_CLASS:
376b96181c2SZachary Turner   case LF_STRUCTURE:
377b96181c2SZachary Turner   case LF_INTERFACE:
378b96181c2SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
379b96181c2SZachary Turner     return cr.isForwardRef();
380b96181c2SZachary Turner   case LF_UNION:
381b96181c2SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
382b96181c2SZachary Turner     return ur.isForwardRef();
383b96181c2SZachary Turner   case LF_ENUM:
384b96181c2SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
385b96181c2SZachary Turner     return er.isForwardRef();
386b96181c2SZachary Turner   default:
387b96181c2SZachary Turner     return false;
388b96181c2SZachary Turner   }
389b96181c2SZachary Turner }
390b96181c2SZachary Turner 
IsTagRecord(llvm::codeview::CVType cvt)391056e4ab4SZachary Turner bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
392056e4ab4SZachary Turner   switch (cvt.kind()) {
393056e4ab4SZachary Turner   case LF_CLASS:
394056e4ab4SZachary Turner   case LF_STRUCTURE:
395056e4ab4SZachary Turner   case LF_UNION:
396056e4ab4SZachary Turner   case LF_ENUM:
397056e4ab4SZachary Turner     return true;
398056e4ab4SZachary Turner   default:
399056e4ab4SZachary Turner     return false;
400056e4ab4SZachary Turner   }
401056e4ab4SZachary Turner }
402056e4ab4SZachary Turner 
IsClassStructUnion(llvm::codeview::CVType cvt)403594c85e9SZachary Turner bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
404594c85e9SZachary Turner   switch (cvt.kind()) {
405594c85e9SZachary Turner   case LF_CLASS:
406594c85e9SZachary Turner   case LF_STRUCTURE:
407594c85e9SZachary Turner   case LF_UNION:
408594c85e9SZachary Turner     return true;
409594c85e9SZachary Turner   default:
410594c85e9SZachary Turner     return false;
411594c85e9SZachary Turner   }
412594c85e9SZachary Turner }
413594c85e9SZachary Turner 
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)4146284aee9SZachary Turner bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
4156284aee9SZachary Turner                                          TpiStream &tpi) {
4166284aee9SZachary Turner   if (id.is_ipi || id.index.isSimple())
4176284aee9SZachary Turner     return false;
4186284aee9SZachary Turner   return IsForwardRefUdt(tpi.getType(id.index));
4196284aee9SZachary Turner }
4206284aee9SZachary Turner 
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)4216284aee9SZachary Turner bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
4226284aee9SZachary Turner   if (id.is_ipi || id.index.isSimple())
4236284aee9SZachary Turner     return false;
4246284aee9SZachary Turner   return IsTagRecord(tpi.getType(id.index));
4256284aee9SZachary Turner }
4266284aee9SZachary Turner 
427b96181c2SZachary Turner lldb::AccessType
TranslateMemberAccess(MemberAccess access)428b96181c2SZachary Turner lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
429b96181c2SZachary Turner   switch (access) {
430b96181c2SZachary Turner   case MemberAccess::Private:
431b96181c2SZachary Turner     return lldb::eAccessPrivate;
432b96181c2SZachary Turner   case MemberAccess::Protected:
433b96181c2SZachary Turner     return lldb::eAccessProtected;
434b96181c2SZachary Turner   case MemberAccess::Public:
435b96181c2SZachary Turner     return lldb::eAccessPublic;
436b96181c2SZachary Turner   case MemberAccess::None:
437b96181c2SZachary Turner     return lldb::eAccessNone;
438b96181c2SZachary Turner   }
439b96181c2SZachary Turner   llvm_unreachable("unreachable");
440b96181c2SZachary Turner }
441b96181c2SZachary Turner 
GetFieldListIndex(CVType cvt)442b96181c2SZachary Turner TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
443b96181c2SZachary Turner   switch (cvt.kind()) {
444b96181c2SZachary Turner   case LF_CLASS:
445b96181c2SZachary Turner   case LF_STRUCTURE:
446b96181c2SZachary Turner   case LF_INTERFACE: {
447b96181c2SZachary Turner     ClassRecord cr;
448b96181c2SZachary Turner     cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
449b96181c2SZachary Turner     return cr.FieldList;
450b96181c2SZachary Turner   }
451b96181c2SZachary Turner   case LF_UNION: {
452b96181c2SZachary Turner     UnionRecord ur;
453b96181c2SZachary Turner     cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
454b96181c2SZachary Turner     return ur.FieldList;
455b96181c2SZachary Turner   }
456b96181c2SZachary Turner   case LF_ENUM: {
457b96181c2SZachary Turner     EnumRecord er;
458b96181c2SZachary Turner     cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
459b96181c2SZachary Turner     return er.FieldList;
460b96181c2SZachary Turner   }
461b96181c2SZachary Turner   default:
462b96181c2SZachary Turner     llvm_unreachable("Unreachable!");
463b96181c2SZachary Turner   }
464b96181c2SZachary Turner }
465b96181c2SZachary Turner 
LookThroughModifierRecord(CVType modifier)466511bff21SZachary Turner TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
467511bff21SZachary Turner   lldbassert(modifier.kind() == LF_MODIFIER);
468511bff21SZachary Turner   ModifierRecord mr;
469511bff21SZachary Turner   llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
470511bff21SZachary Turner   return mr.ModifiedType;
471511bff21SZachary Turner }
472511bff21SZachary Turner 
DropNameScope(llvm::StringRef name)473b96181c2SZachary Turner llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
47444f19514SZachary Turner   return MSVCUndecoratedNameParser::DropScope(name);
475b96181c2SZachary Turner }
476a93458b0SZachary Turner 
GetVariableNameInfo(CVSymbol sym)477594c85e9SZachary Turner VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
478*4871dfc6SSlava Gurevich   VariableInfo result = {};
479594c85e9SZachary Turner 
480594c85e9SZachary Turner   if (sym.kind() == S_REGREL32) {
481594c85e9SZachary Turner     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
482594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
483594c85e9SZachary Turner     result.type = reg.Type;
484594c85e9SZachary Turner     result.name = reg.Name;
485594c85e9SZachary Turner     return result;
486594c85e9SZachary Turner   }
487594c85e9SZachary Turner 
488594c85e9SZachary Turner   if (sym.kind() == S_REGISTER) {
489594c85e9SZachary Turner     RegisterSym reg(SymbolRecordKind::RegisterSym);
490594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
491594c85e9SZachary Turner     result.type = reg.Index;
492594c85e9SZachary Turner     result.name = reg.Name;
493594c85e9SZachary Turner     return result;
494594c85e9SZachary Turner   }
495594c85e9SZachary Turner 
496594c85e9SZachary Turner   if (sym.kind() == S_LOCAL) {
497594c85e9SZachary Turner     LocalSym local(SymbolRecordKind::LocalSym);
498594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
499594c85e9SZachary Turner     result.type = local.Type;
500594c85e9SZachary Turner     result.name = local.Name;
5015e9c9b32SZequan Wu     result.is_param =
5025e9c9b32SZequan Wu         ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
503594c85e9SZachary Turner     return result;
504594c85e9SZachary Turner   }
505594c85e9SZachary Turner 
5063790029dSZachary Turner   if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
5073790029dSZachary Turner     DataSym data(SymbolRecordKind::DataSym);
5083790029dSZachary Turner     cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
5093790029dSZachary Turner     result.type = data.Type;
5103790029dSZachary Turner     result.name = data.Name;
5113790029dSZachary Turner     return result;
5123790029dSZachary Turner   }
5133790029dSZachary Turner 
5143790029dSZachary Turner   if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
5153790029dSZachary Turner     ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
5163790029dSZachary Turner     cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
5173790029dSZachary Turner     result.type = data.Type;
5183790029dSZachary Turner     result.name = data.Name;
5193790029dSZachary Turner     return result;
5203790029dSZachary Turner   }
5213790029dSZachary Turner 
5223790029dSZachary Turner   if (sym.kind() == S_CONSTANT) {
5233790029dSZachary Turner     ConstantSym constant(SymbolRecordKind::ConstantSym);
5243790029dSZachary Turner     cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
5253790029dSZachary Turner     result.type = constant.Type;
5263790029dSZachary Turner     result.name = constant.Name;
5273790029dSZachary Turner     return result;
5283790029dSZachary Turner   }
5293790029dSZachary Turner 
530594c85e9SZachary Turner   lldbassert(false && "Invalid variable record kind!");
531594c85e9SZachary Turner   return {};
532594c85e9SZachary Turner }
533594c85e9SZachary Turner 
5342c15fc56SAleksandr Urakov static llvm::FixedStreamArray<FrameData>::Iterator
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)535758657e5SAleksandr Urakov GetCorrespondingFrameData(lldb::addr_t load_addr,
536758657e5SAleksandr Urakov                           const DebugFrameDataSubsectionRef &fpo_data,
537758657e5SAleksandr Urakov                           const Variable::RangeList &ranges) {
538758657e5SAleksandr Urakov   lldbassert(!ranges.IsEmpty());
539758657e5SAleksandr Urakov 
540758657e5SAleksandr Urakov   // assume that all variable ranges correspond to one frame data
541758657e5SAleksandr Urakov   using RangeListEntry = Variable::RangeList::Entry;
542758657e5SAleksandr Urakov   const RangeListEntry &range = ranges.GetEntryRef(0);
543758657e5SAleksandr Urakov 
544758657e5SAleksandr Urakov   auto it = fpo_data.begin();
545758657e5SAleksandr Urakov 
546758657e5SAleksandr Urakov   // start by searching first frame data range containing variable range
547758657e5SAleksandr Urakov   for (; it != fpo_data.end(); ++it) {
548758657e5SAleksandr Urakov     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
549758657e5SAleksandr Urakov 
550758657e5SAleksandr Urakov     if (fd_range.Contains(range)) {
551758657e5SAleksandr Urakov       break;
552758657e5SAleksandr Urakov     }
553758657e5SAleksandr Urakov   }
554758657e5SAleksandr Urakov 
555758657e5SAleksandr Urakov   // then first most nested entry that still contains variable range
556758657e5SAleksandr Urakov   auto found = it;
557758657e5SAleksandr Urakov   for (; it != fpo_data.end(); ++it) {
558758657e5SAleksandr Urakov     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
559758657e5SAleksandr Urakov 
560758657e5SAleksandr Urakov     if (!fd_range.Contains(range)) {
561758657e5SAleksandr Urakov       break;
562758657e5SAleksandr Urakov     }
563758657e5SAleksandr Urakov     found = it;
564758657e5SAleksandr Urakov   }
565758657e5SAleksandr Urakov 
566758657e5SAleksandr Urakov   return found;
567758657e5SAleksandr Urakov }
568758657e5SAleksandr Urakov 
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)569758657e5SAleksandr Urakov static bool GetFrameDataProgram(PdbIndex &index,
570758657e5SAleksandr Urakov                                 const Variable::RangeList &ranges,
571758657e5SAleksandr Urakov                                 llvm::StringRef &out_program) {
572758657e5SAleksandr Urakov   const DebugFrameDataSubsectionRef &new_fpo_data =
573758657e5SAleksandr Urakov       index.dbi().getNewFpoRecords();
574758657e5SAleksandr Urakov 
575758657e5SAleksandr Urakov   auto frame_data_it =
576758657e5SAleksandr Urakov       GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
577758657e5SAleksandr Urakov   if (frame_data_it == new_fpo_data.end())
578758657e5SAleksandr Urakov     return false;
579758657e5SAleksandr Urakov 
580758657e5SAleksandr Urakov   PDBStringTable &strings = cantFail(index.pdb().getStringTable());
581758657e5SAleksandr Urakov   out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
582758657e5SAleksandr Urakov   return true;
583758657e5SAleksandr Urakov }
584758657e5SAleksandr Urakov 
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)585758657e5SAleksandr Urakov static RegisterId GetBaseFrameRegister(PdbIndex &index,
586758657e5SAleksandr Urakov                                        PdbCompilandSymId frame_proc_id,
587758657e5SAleksandr Urakov                                        bool is_parameter) {
588758657e5SAleksandr Urakov   CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
589d6710023SZequan Wu   if (frame_proc_cvs.kind() != S_FRAMEPROC)
590d6710023SZequan Wu     return RegisterId::NONE;
591758657e5SAleksandr Urakov 
592758657e5SAleksandr Urakov   FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
593758657e5SAleksandr Urakov   cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
594758657e5SAleksandr Urakov                                                            frame_proc));
595758657e5SAleksandr Urakov 
596758657e5SAleksandr Urakov   CPUType cpu_type = index.compilands()
597758657e5SAleksandr Urakov                          .GetCompiland(frame_proc_id.modi)
598758657e5SAleksandr Urakov                          ->m_compile_opts->Machine;
599758657e5SAleksandr Urakov 
600758657e5SAleksandr Urakov   return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
601758657e5SAleksandr Urakov                       : frame_proc.getLocalFramePtrReg(cpu_type);
602758657e5SAleksandr Urakov }
603758657e5SAleksandr Urakov 
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)604594c85e9SZachary Turner VariableInfo lldb_private::npdb::GetVariableLocationInfo(
605b74a01a8SZequan Wu     PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
606758657e5SAleksandr Urakov     lldb::ModuleSP module) {
607594c85e9SZachary Turner 
608594c85e9SZachary Turner   CVSymbol sym = index.ReadSymbolRecord(var_id);
609594c85e9SZachary Turner 
610594c85e9SZachary Turner   VariableInfo result = GetVariableNameInfo(sym);
611594c85e9SZachary Turner 
612594c85e9SZachary Turner   if (sym.kind() == S_REGREL32) {
613594c85e9SZachary Turner     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
614594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
615594c85e9SZachary Turner     result.location =
616594c85e9SZachary Turner         MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
617594c85e9SZachary Turner     result.ranges.emplace();
618594c85e9SZachary Turner     return result;
619594c85e9SZachary Turner   }
620594c85e9SZachary Turner 
621594c85e9SZachary Turner   if (sym.kind() == S_REGISTER) {
622594c85e9SZachary Turner     RegisterSym reg(SymbolRecordKind::RegisterSym);
623594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
624594c85e9SZachary Turner     result.location = MakeEnregisteredLocationExpression(reg.Register, module);
625594c85e9SZachary Turner     result.ranges.emplace();
626594c85e9SZachary Turner     return result;
627594c85e9SZachary Turner   }
628594c85e9SZachary Turner 
629594c85e9SZachary Turner   if (sym.kind() == S_LOCAL) {
630594c85e9SZachary Turner     LocalSym local(SymbolRecordKind::LocalSym);
631594c85e9SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
632594c85e9SZachary Turner 
633594c85e9SZachary Turner     PdbCompilandSymId loc_specifier_id(var_id.modi,
634594c85e9SZachary Turner                                        var_id.offset + sym.RecordData.size());
635594c85e9SZachary Turner     CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
6365e9c9b32SZequan Wu     switch(loc_specifier_cvs.kind()) {
6375e9c9b32SZequan Wu     case S_DEFRANGE_FRAMEPOINTER_REL: {
638594c85e9SZachary Turner       DefRangeFramePointerRelSym loc(
639594c85e9SZachary Turner           SymbolRecordKind::DefRangeFramePointerRelSym);
640594c85e9SZachary Turner       cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
641594c85e9SZachary Turner           loc_specifier_cvs, loc));
642758657e5SAleksandr Urakov 
643758657e5SAleksandr Urakov       Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
644758657e5SAleksandr Urakov 
645758657e5SAleksandr Urakov       PdbCompilandSymId func_scope_id =
646b74a01a8SZequan Wu           PdbSymUid(func_block.GetID()).asCompilandSym();
647758657e5SAleksandr Urakov       CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
648758657e5SAleksandr Urakov       lldbassert(func_block_cvs.kind() == S_GPROC32 ||
649758657e5SAleksandr Urakov                  func_block_cvs.kind() == S_LPROC32);
650758657e5SAleksandr Urakov 
651758657e5SAleksandr Urakov       PdbCompilandSymId frame_proc_id(
652758657e5SAleksandr Urakov           func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
653758657e5SAleksandr Urakov 
654758657e5SAleksandr Urakov       RegisterId base_reg =
6555e9c9b32SZequan Wu           GetBaseFrameRegister(index, frame_proc_id, result.is_param);
656d6710023SZequan Wu       if (base_reg == RegisterId::NONE)
657d6710023SZequan Wu         break;
658758657e5SAleksandr Urakov       if (base_reg == RegisterId::VFRAME) {
659758657e5SAleksandr Urakov         llvm::StringRef program;
660758657e5SAleksandr Urakov         if (GetFrameDataProgram(index, ranges, program)) {
661758657e5SAleksandr Urakov           result.location =
662da60fc81SNilanjana Basu               MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module);
663758657e5SAleksandr Urakov           result.ranges = std::move(ranges);
664758657e5SAleksandr Urakov         } else {
665758657e5SAleksandr Urakov           // invalid variable
666758657e5SAleksandr Urakov         }
667758657e5SAleksandr Urakov       } else {
668758657e5SAleksandr Urakov         result.location =
669da60fc81SNilanjana Basu             MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
670758657e5SAleksandr Urakov         result.ranges = std::move(ranges);
671758657e5SAleksandr Urakov       }
6725e9c9b32SZequan Wu       break;
6735e9c9b32SZequan Wu     }
6745e9c9b32SZequan Wu     case S_DEFRANGE_REGISTER_REL: {
675758657e5SAleksandr Urakov       DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
676758657e5SAleksandr Urakov       cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
677758657e5SAleksandr Urakov           loc_specifier_cvs, loc));
678758657e5SAleksandr Urakov 
679758657e5SAleksandr Urakov       Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
680758657e5SAleksandr Urakov 
681758657e5SAleksandr Urakov       RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
682758657e5SAleksandr Urakov 
683758657e5SAleksandr Urakov       if (base_reg == RegisterId::VFRAME) {
684758657e5SAleksandr Urakov         llvm::StringRef program;
685758657e5SAleksandr Urakov         if (GetFrameDataProgram(index, ranges, program)) {
686758657e5SAleksandr Urakov           result.location = MakeVFrameRelLocationExpression(
687758657e5SAleksandr Urakov               program, loc.Hdr.BasePointerOffset, module);
688758657e5SAleksandr Urakov           result.ranges = std::move(ranges);
689758657e5SAleksandr Urakov         } else {
690758657e5SAleksandr Urakov           // invalid variable
691758657e5SAleksandr Urakov         }
692758657e5SAleksandr Urakov       } else {
693758657e5SAleksandr Urakov         result.location = MakeRegRelLocationExpression(
694758657e5SAleksandr Urakov             base_reg, loc.Hdr.BasePointerOffset, module);
695758657e5SAleksandr Urakov         result.ranges = std::move(ranges);
696758657e5SAleksandr Urakov       }
6975e9c9b32SZequan Wu       break;
6985e9c9b32SZequan Wu     }
6995e9c9b32SZequan Wu     case S_DEFRANGE_REGISTER: {
7005e9c9b32SZequan Wu       DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
7015e9c9b32SZequan Wu       cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
7025e9c9b32SZequan Wu           loc_specifier_cvs, loc));
7035e9c9b32SZequan Wu 
7045e9c9b32SZequan Wu       RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
7055e9c9b32SZequan Wu       result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
7065e9c9b32SZequan Wu       result.location = MakeEnregisteredLocationExpression(base_reg, module);
7075e9c9b32SZequan Wu       break;
7085e9c9b32SZequan Wu     }
7095e9c9b32SZequan Wu     case S_DEFRANGE_SUBFIELD_REGISTER: {
7102fa27346SZequan Wu       // A map from offset in parent to pair of register id and size. If the
7112fa27346SZequan Wu       // variable is a simple type, then we don't know the number of subfields.
7122fa27346SZequan Wu       // Otherwise, the size of the map should be greater than or equal to the
7132fa27346SZequan Wu       // number of sub field record.
7142fa27346SZequan Wu       std::map<uint64_t, std::pair<RegisterId, uint32_t>> members_info;
7153dbf524aSZequan Wu       bool is_simple_type = result.type.isSimple();
7163dbf524aSZequan Wu       if (!is_simple_type) {
7175e9c9b32SZequan Wu         CVType class_cvt = index.tpi().getType(result.type);
718d6710023SZequan Wu         TypeIndex class_id = result.type;
719d6710023SZequan Wu         if (class_cvt.kind() == LF_MODIFIER)
720d6710023SZequan Wu           class_id = LookThroughModifierRecord(class_cvt);
721d6710023SZequan Wu         if (IsForwardRefUdt(class_id, index.tpi())) {
722d6710023SZequan Wu           auto expected_full_ti =
723d6710023SZequan Wu               index.tpi().findFullDeclForForwardRef(class_id);
724d6710023SZequan Wu           if (!expected_full_ti) {
725d6710023SZequan Wu             llvm::consumeError(expected_full_ti.takeError());
726d6710023SZequan Wu             break;
727d6710023SZequan Wu           }
728d6710023SZequan Wu           class_cvt = index.tpi().getType(*expected_full_ti);
729d6710023SZequan Wu         }
730d6710023SZequan Wu         if (IsTagRecord(class_cvt)) {
731d6710023SZequan Wu           TagRecord tag_record = CVTagRecord::create(class_cvt).asTag();
732bd2044c1SZequan Wu           CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
733bd2044c1SZequan Wu           FieldListRecord field_list;
734bd2044c1SZequan Wu           if (llvm::Error error =
735bd2044c1SZequan Wu                   TypeDeserializer::deserializeAs<FieldListRecord>(
736bd2044c1SZequan Wu                       field_list_cvt, field_list))
737bd2044c1SZequan Wu             llvm::consumeError(std::move(error));
7385e9c9b32SZequan Wu           FindMembersSize find_members_size(members_info, index.tpi());
739bd2044c1SZequan Wu           if (llvm::Error err = visitMemberRecordStream(field_list.Data,
740d6710023SZequan Wu                                                         find_members_size)) {
7415e9c9b32SZequan Wu             llvm::consumeError(std::move(err));
7423dbf524aSZequan Wu             break;
7433dbf524aSZequan Wu           }
744d6710023SZequan Wu         } else {
745d6710023SZequan Wu           // TODO: Handle poiner type.
746d6710023SZequan Wu           break;
747d6710023SZequan Wu         }
7483dbf524aSZequan Wu       }
7495e9c9b32SZequan Wu 
7505e9c9b32SZequan Wu       size_t member_idx = 0;
7515e9c9b32SZequan Wu       // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by
7525e9c9b32SZequan Wu       // S_DEFRANGE_SUBFIELD_REGISTER, need to verify.
7533dbf524aSZequan Wu       while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER) {
7543dbf524aSZequan Wu         if (!is_simple_type && member_idx >= members_info.size())
7553dbf524aSZequan Wu           break;
7563dbf524aSZequan Wu 
7575e9c9b32SZequan Wu         DefRangeSubfieldRegisterSym loc(
7585e9c9b32SZequan Wu             SymbolRecordKind::DefRangeSubfieldRegisterSym);
7595e9c9b32SZequan Wu         cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
7605e9c9b32SZequan Wu             loc_specifier_cvs, loc));
7615e9c9b32SZequan Wu 
7625e9c9b32SZequan Wu         if (result.ranges) {
7635e9c9b32SZequan Wu           result.ranges = Variable::RangeList::GetOverlaps(
7645e9c9b32SZequan Wu               *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps));
7655e9c9b32SZequan Wu         } else {
7665e9c9b32SZequan Wu           result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
7675e9c9b32SZequan Wu           result.ranges->Sort();
768758657e5SAleksandr Urakov         }
769758657e5SAleksandr Urakov 
7703dbf524aSZequan Wu         if (is_simple_type) {
7712fa27346SZequan Wu           if (members_info.count(loc.Hdr.OffsetInParent)) {
7722fa27346SZequan Wu             // Malformed record.
7732fa27346SZequan Wu             result.ranges->Clear();
7742fa27346SZequan Wu             return result;
7752fa27346SZequan Wu           }
7762fa27346SZequan Wu           members_info[loc.Hdr.OffsetInParent] = {
7772fa27346SZequan Wu               (RegisterId)(uint16_t)loc.Hdr.Register, 0};
7783dbf524aSZequan Wu         } else {
7792fa27346SZequan Wu           if (!members_info.count(loc.Hdr.OffsetInParent)) {
7802fa27346SZequan Wu             // Malformed record.
7812fa27346SZequan Wu             result.ranges->Clear();
7822fa27346SZequan Wu             return result;
7835e9c9b32SZequan Wu           }
7842fa27346SZequan Wu           members_info[loc.Hdr.OffsetInParent].first =
7855e9c9b32SZequan Wu               (RegisterId)(uint16_t)loc.Hdr.Register;
7863dbf524aSZequan Wu         }
7875e9c9b32SZequan Wu         // Go to next S_DEFRANGE_SUBFIELD_REGISTER.
7885e9c9b32SZequan Wu         loc_specifier_id = PdbCompilandSymId(
7895e9c9b32SZequan Wu             loc_specifier_id.modi,
7905e9c9b32SZequan Wu             loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
7915e9c9b32SZequan Wu         loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
7925e9c9b32SZequan Wu       }
7932fa27346SZequan Wu       // Fix size for simple type.
7942fa27346SZequan Wu       if (is_simple_type) {
7952fa27346SZequan Wu         auto cur = members_info.begin();
7962fa27346SZequan Wu         auto end = members_info.end();
7972fa27346SZequan Wu         auto next = cur;
7982fa27346SZequan Wu         ++next;
7992fa27346SZequan Wu         uint32_t size = 0;
8002fa27346SZequan Wu         while (next != end) {
8012fa27346SZequan Wu           cur->second.second = next->first - cur->first;
8022fa27346SZequan Wu           size += cur->second.second;
8032fa27346SZequan Wu           cur = next++;
8042fa27346SZequan Wu         }
8052fa27346SZequan Wu         cur->second.second =
8062fa27346SZequan Wu             GetTypeSizeForSimpleKind(result.type.getSimpleKind()) - size;
8072fa27346SZequan Wu       }
8085e9c9b32SZequan Wu       result.location =
8092fa27346SZequan Wu           MakeEnregisteredLocationExpressionForClass(members_info, module);
8105e9c9b32SZequan Wu       break;
8115e9c9b32SZequan Wu     }
8125e9c9b32SZequan Wu     default:
8135e9c9b32SZequan Wu       // FIXME: Handle other kinds. LLVM only generates the 4 types of records
8145e9c9b32SZequan Wu       // above.
8155e9c9b32SZequan Wu       break;
8165e9c9b32SZequan Wu     }
817594c85e9SZachary Turner     return result;
818594c85e9SZachary Turner   }
819594c85e9SZachary Turner   llvm_unreachable("Symbol is not a local variable!");
820594c85e9SZachary Turner   return result;
821594c85e9SZachary Turner }
822594c85e9SZachary Turner 
823a93458b0SZachary Turner lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)824a93458b0SZachary Turner lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
825a93458b0SZachary Turner   switch (kind) {
826a93458b0SZachary Turner   case SimpleTypeKind::Boolean128:
827a93458b0SZachary Turner   case SimpleTypeKind::Boolean16:
828a93458b0SZachary Turner   case SimpleTypeKind::Boolean32:
829a93458b0SZachary Turner   case SimpleTypeKind::Boolean64:
830a93458b0SZachary Turner   case SimpleTypeKind::Boolean8:
831a93458b0SZachary Turner     return lldb::eBasicTypeBool;
832a93458b0SZachary Turner   case SimpleTypeKind::Byte:
833a93458b0SZachary Turner   case SimpleTypeKind::UnsignedCharacter:
834a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedChar;
835a93458b0SZachary Turner   case SimpleTypeKind::NarrowCharacter:
836a93458b0SZachary Turner     return lldb::eBasicTypeChar;
837a93458b0SZachary Turner   case SimpleTypeKind::SignedCharacter:
838a93458b0SZachary Turner   case SimpleTypeKind::SByte:
839a93458b0SZachary Turner     return lldb::eBasicTypeSignedChar;
840a93458b0SZachary Turner   case SimpleTypeKind::Character16:
841a93458b0SZachary Turner     return lldb::eBasicTypeChar16;
842a93458b0SZachary Turner   case SimpleTypeKind::Character32:
843a93458b0SZachary Turner     return lldb::eBasicTypeChar32;
8445c9e20d7SZequan Wu   case SimpleTypeKind::Character8:
8455c9e20d7SZequan Wu     return lldb::eBasicTypeChar8;
846a93458b0SZachary Turner   case SimpleTypeKind::Complex80:
847a93458b0SZachary Turner     return lldb::eBasicTypeLongDoubleComplex;
848a93458b0SZachary Turner   case SimpleTypeKind::Complex64:
849a93458b0SZachary Turner     return lldb::eBasicTypeDoubleComplex;
850a93458b0SZachary Turner   case SimpleTypeKind::Complex32:
851a93458b0SZachary Turner     return lldb::eBasicTypeFloatComplex;
852a93458b0SZachary Turner   case SimpleTypeKind::Float128:
853a93458b0SZachary Turner   case SimpleTypeKind::Float80:
854a93458b0SZachary Turner     return lldb::eBasicTypeLongDouble;
855a93458b0SZachary Turner   case SimpleTypeKind::Float64:
856a93458b0SZachary Turner     return lldb::eBasicTypeDouble;
857a93458b0SZachary Turner   case SimpleTypeKind::Float32:
858a93458b0SZachary Turner     return lldb::eBasicTypeFloat;
859a93458b0SZachary Turner   case SimpleTypeKind::Float16:
860a93458b0SZachary Turner     return lldb::eBasicTypeHalf;
861a93458b0SZachary Turner   case SimpleTypeKind::Int128:
862a93458b0SZachary Turner     return lldb::eBasicTypeInt128;
863a93458b0SZachary Turner   case SimpleTypeKind::Int64:
864a93458b0SZachary Turner   case SimpleTypeKind::Int64Quad:
865a93458b0SZachary Turner     return lldb::eBasicTypeLongLong;
866a93458b0SZachary Turner   case SimpleTypeKind::Int32:
867a93458b0SZachary Turner     return lldb::eBasicTypeInt;
868a93458b0SZachary Turner   case SimpleTypeKind::Int16:
869a93458b0SZachary Turner   case SimpleTypeKind::Int16Short:
870a93458b0SZachary Turner     return lldb::eBasicTypeShort;
871a93458b0SZachary Turner   case SimpleTypeKind::UInt128:
872a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedInt128;
873a93458b0SZachary Turner   case SimpleTypeKind::UInt64:
874a93458b0SZachary Turner   case SimpleTypeKind::UInt64Quad:
875a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedLongLong;
876a93458b0SZachary Turner   case SimpleTypeKind::HResult:
877a93458b0SZachary Turner   case SimpleTypeKind::UInt32:
878a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedInt;
879a93458b0SZachary Turner   case SimpleTypeKind::UInt16:
880a93458b0SZachary Turner   case SimpleTypeKind::UInt16Short:
881a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedShort;
882a93458b0SZachary Turner   case SimpleTypeKind::Int32Long:
883a93458b0SZachary Turner     return lldb::eBasicTypeLong;
884a93458b0SZachary Turner   case SimpleTypeKind::UInt32Long:
885a93458b0SZachary Turner     return lldb::eBasicTypeUnsignedLong;
886a93458b0SZachary Turner   case SimpleTypeKind::Void:
887a93458b0SZachary Turner     return lldb::eBasicTypeVoid;
888a93458b0SZachary Turner   case SimpleTypeKind::WideCharacter:
889a93458b0SZachary Turner     return lldb::eBasicTypeWChar;
890a93458b0SZachary Turner   default:
891a93458b0SZachary Turner     return lldb::eBasicTypeInvalid;
892a93458b0SZachary Turner   }
893a93458b0SZachary Turner }
894a93458b0SZachary Turner 
GetTypeSizeForSimpleKind(SimpleTypeKind kind)895a93458b0SZachary Turner size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
896a93458b0SZachary Turner   switch (kind) {
897a93458b0SZachary Turner   case SimpleTypeKind::Boolean128:
898a93458b0SZachary Turner   case SimpleTypeKind::Int128:
899a93458b0SZachary Turner   case SimpleTypeKind::UInt128:
900a93458b0SZachary Turner   case SimpleTypeKind::Float128:
901a93458b0SZachary Turner     return 16;
902a93458b0SZachary Turner   case SimpleTypeKind::Complex80:
903a93458b0SZachary Turner   case SimpleTypeKind::Float80:
904a93458b0SZachary Turner     return 10;
905a93458b0SZachary Turner   case SimpleTypeKind::Boolean64:
906a93458b0SZachary Turner   case SimpleTypeKind::Complex64:
907a93458b0SZachary Turner   case SimpleTypeKind::UInt64:
908a93458b0SZachary Turner   case SimpleTypeKind::UInt64Quad:
909a93458b0SZachary Turner   case SimpleTypeKind::Float64:
910a93458b0SZachary Turner   case SimpleTypeKind::Int64:
911a93458b0SZachary Turner   case SimpleTypeKind::Int64Quad:
912a93458b0SZachary Turner     return 8;
913a93458b0SZachary Turner   case SimpleTypeKind::Boolean32:
914a93458b0SZachary Turner   case SimpleTypeKind::Character32:
915a93458b0SZachary Turner   case SimpleTypeKind::Complex32:
916a93458b0SZachary Turner   case SimpleTypeKind::Float32:
917a93458b0SZachary Turner   case SimpleTypeKind::Int32:
918a93458b0SZachary Turner   case SimpleTypeKind::Int32Long:
919a93458b0SZachary Turner   case SimpleTypeKind::UInt32Long:
920a93458b0SZachary Turner   case SimpleTypeKind::HResult:
921a93458b0SZachary Turner   case SimpleTypeKind::UInt32:
922a93458b0SZachary Turner     return 4;
923a93458b0SZachary Turner   case SimpleTypeKind::Boolean16:
924a93458b0SZachary Turner   case SimpleTypeKind::Character16:
925a93458b0SZachary Turner   case SimpleTypeKind::Float16:
926a93458b0SZachary Turner   case SimpleTypeKind::Int16:
927a93458b0SZachary Turner   case SimpleTypeKind::Int16Short:
928a93458b0SZachary Turner   case SimpleTypeKind::UInt16:
929a93458b0SZachary Turner   case SimpleTypeKind::UInt16Short:
930a93458b0SZachary Turner   case SimpleTypeKind::WideCharacter:
931a93458b0SZachary Turner     return 2;
932a93458b0SZachary Turner   case SimpleTypeKind::Boolean8:
933a93458b0SZachary Turner   case SimpleTypeKind::Byte:
934a93458b0SZachary Turner   case SimpleTypeKind::UnsignedCharacter:
935a93458b0SZachary Turner   case SimpleTypeKind::NarrowCharacter:
936a93458b0SZachary Turner   case SimpleTypeKind::SignedCharacter:
937a93458b0SZachary Turner   case SimpleTypeKind::SByte:
9385c9e20d7SZequan Wu   case SimpleTypeKind::Character8:
939a93458b0SZachary Turner     return 1;
940a93458b0SZachary Turner   case SimpleTypeKind::Void:
941a93458b0SZachary Turner   default:
942a93458b0SZachary Turner     return 0;
943a93458b0SZachary Turner   }
944a93458b0SZachary Turner }
945594c85e9SZachary Turner 
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)946594c85e9SZachary Turner PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
947594c85e9SZachary Turner                                                      TpiStream &tpi) {
948594c85e9SZachary Turner   if (id.index.isSimple())
949594c85e9SZachary Turner     return id;
950594c85e9SZachary Turner 
951594c85e9SZachary Turner   CVType cvt = tpi.getType(id.index);
952594c85e9SZachary Turner 
953594c85e9SZachary Turner   // Only tag records have a best and a worst record.
954594c85e9SZachary Turner   if (!IsTagRecord(cvt))
955594c85e9SZachary Turner     return id;
956594c85e9SZachary Turner 
957594c85e9SZachary Turner   // Tag records that are not forward decls are full decls, hence they are the
958594c85e9SZachary Turner   // best.
959594c85e9SZachary Turner   if (!IsForwardRefUdt(cvt))
960594c85e9SZachary Turner     return id;
961594c85e9SZachary Turner 
962594c85e9SZachary Turner   return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
963594c85e9SZachary Turner }
964594c85e9SZachary Turner 
GetSizeOfTypeInternal(CVType cvt)965594c85e9SZachary Turner template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
966594c85e9SZachary Turner   RecordType record;
967594c85e9SZachary Turner   llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
968594c85e9SZachary Turner   return record.getSize();
969594c85e9SZachary Turner }
970594c85e9SZachary Turner 
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)971594c85e9SZachary Turner size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
972594c85e9SZachary Turner                                          llvm::pdb::TpiStream &tpi) {
973594c85e9SZachary Turner   if (id.index.isSimple()) {
974594c85e9SZachary Turner     switch (id.index.getSimpleMode()) {
975594c85e9SZachary Turner     case SimpleTypeMode::Direct:
976594c85e9SZachary Turner       return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
977594c85e9SZachary Turner     case SimpleTypeMode::NearPointer32:
978594c85e9SZachary Turner     case SimpleTypeMode::FarPointer32:
979594c85e9SZachary Turner       return 4;
980594c85e9SZachary Turner     case SimpleTypeMode::NearPointer64:
981594c85e9SZachary Turner       return 8;
982594c85e9SZachary Turner     case SimpleTypeMode::NearPointer128:
983594c85e9SZachary Turner       return 16;
984594c85e9SZachary Turner     default:
985594c85e9SZachary Turner       break;
986594c85e9SZachary Turner     }
987594c85e9SZachary Turner     return 0;
988594c85e9SZachary Turner   }
989594c85e9SZachary Turner 
99022566330SZachary Turner   TypeIndex index = id.index;
99122566330SZachary Turner   if (IsForwardRefUdt(index, tpi))
99222566330SZachary Turner     index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
99322566330SZachary Turner 
99422566330SZachary Turner   CVType cvt = tpi.getType(index);
995594c85e9SZachary Turner   switch (cvt.kind()) {
996594c85e9SZachary Turner   case LF_MODIFIER:
997594c85e9SZachary Turner     return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
998594c85e9SZachary Turner   case LF_ENUM: {
999594c85e9SZachary Turner     EnumRecord record;
1000594c85e9SZachary Turner     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
1001594c85e9SZachary Turner     return GetSizeOfType({record.UnderlyingType}, tpi);
1002594c85e9SZachary Turner   }
1003594c85e9SZachary Turner   case LF_POINTER:
1004594c85e9SZachary Turner     return GetSizeOfTypeInternal<PointerRecord>(cvt);
1005594c85e9SZachary Turner   case LF_ARRAY:
1006594c85e9SZachary Turner     return GetSizeOfTypeInternal<ArrayRecord>(cvt);
1007594c85e9SZachary Turner   case LF_CLASS:
1008594c85e9SZachary Turner   case LF_STRUCTURE:
1009594c85e9SZachary Turner   case LF_INTERFACE:
1010594c85e9SZachary Turner     return GetSizeOfTypeInternal<ClassRecord>(cvt);
1011594c85e9SZachary Turner   case LF_UNION:
1012594c85e9SZachary Turner     return GetSizeOfTypeInternal<UnionRecord>(cvt);
1013594c85e9SZachary Turner   default:
1014594c85e9SZachary Turner     break;
1015594c85e9SZachary Turner   }
1016594c85e9SZachary Turner   return 0;
1017594c85e9SZachary Turner }
1018